#include "paint.h" typedef struct Icon { CanvasTool *tool; uchar *bits; Image *up; } Icon; typedef struct Aux { int selection; Widget *canvas; } Aux; static Point dim = {32, 32}; static uchar brushbits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x92, 0x24, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x92, 0x48, 0x80, 0x00, 0x92, 0x48, 0x80, 0x01, 0x24, 0x91, 0x00, 0x01, 0x24, 0x91, 0x00, 0x02, 0x49, 0x22, 0x00, 0x04, 0x92, 0x42, 0x00, 0x1B, 0x6D, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, }; static uchar pipettebits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x03, 0xA0, 0x00, 0x00, 0x07, 0xD0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x03, 0xA0, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x03, 0xA0, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x03, 0xA0, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, }; static uchar selectbits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x71, 0xC7, 0x18, 0x1C, 0x71, 0xC7, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0xE3, 0x8E, 0x38, 0x18, 0xE3, 0x8E, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static uchar zoombits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0xC1, 0x80, 0x00, 0x03, 0x00, 0x60, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x10, 0x00, 0x04, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x18, 0x00, 0x03, 0x00, 0x7C, 0x00, 0x00, 0xC1, 0xBE, 0x00, 0x00, 0x3E, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static uchar clearbits[] = { 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x0C, 0x30, 0x00, 0x00, 0x10, 0x08, 0x18, 0x00, 0x20, 0x0E, 0x34, 0x00, 0x20, 0x0B, 0xF4, 0x00, 0x20, 0x0E, 0x34, 0x00, 0x3F, 0xF8, 0x18, 0x00, 0x15, 0x50, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x15, 0x50, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x2A, 0xA3, 0xEC, 0x00, 0x2A, 0xA2, 0x10, 0x00, 0x2A, 0xA3, 0xEC, 0x00, 0x35, 0xDC, 0x00, 0x00, 0x64, 0x92, 0x00, 0x00, 0x64, 0x92, 0x00, 0x00, 0x24, 0x49, 0x00, 0x00, 0x62, 0x49, 0x00, 0x00, 0x62, 0x49, 0x00, 0x00, 0x22, 0x24, 0x80, 0x00, 0x61, 0x24, 0x80, 0x00, 0x61, 0x24, 0x80, 0x00, 0x21, 0x12, 0x40, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x10, 0x00, 0x40, 0x00, 0x10, 0x00, 0x3F, 0xFF, 0xE0, 0x00, }; enum { TBrush, TPipette, TSelect, TZoom, TClear, }; static Icon icons[] = { [TBrush] {&brushtool, brushbits}, [TPipette] {&pipette, pipettebits}, [TSelect] {&rselect, selectbits}, [TZoom] {&zoom, zoombits}, [TClear] {&noptool, clearbits}, }; static Image *lite; static Image *dark; static int select(Aux *aux, int s) { CanvasTool *t; if(aux->selection >= 0 && icons[aux->selection].tool->cleanup != nil) icons[aux->selection].tool->cleanup(aux->canvas); t = &((Canvas *)aux->canvas->aux)->tool; if(s < 0) { aux->selection = -1; *t = noptool; return 0; } aux->selection = s; *t = *icons[s].tool; if(t->mouse == nil) { fprint(2, "broken tool\n"); /* it probably wasn't added to the mkfile */ goto err; } if(t->init != nil && t->init(aux->canvas) < 0) goto err; return 0; err: aux->selection = -1; *t = noptool; return -1; } static Rectangle irect(Widget *w, int s) { int y0, y1; Rectangle r; y0 = s * dim.y + s; y1 = y0 + dim.y; r = rectaddpt(Rect(0, y0, dim.x, y1), w->r.min); return r; } static int mouse(Widget *w, Mousectl *mctl) { Aux *aux; Point m; int s; Rectangle r; int failed; if((mctl->buttons & 7) == 0) return 0; aux = w->aux; if(aux->selection >= 0) { r = irect(w, aux->selection); draw(w->screen, r, lite, nil, ZP); draw(w->screen, r, dark, icons[aux->selection].up, ZP); } m = subpt(mctl->xy, w->r.min); s = m.y / (dim.y + 1); if(s < 0 || s >= nelem(icons)) { fprint(2, "toolbox: bad selection: %d %d\n", s, m.y); return -1; } r = irect(w, s); draw(w->screen, r, dark, nil, ZP); draw(w->screen, r, lite, icons[s].up, ZP); failed = select(aux, s) < 0; do { readmouse(mctl); } while(mctl->buttons); if(failed) { draw(w->screen, r, lite, nil, ZP); draw(w->screen, r, dark, icons[s].up, ZP); } return 0; } static void redraw(Widget *w, RedrawMode) { Aux *aux; int i, y0, y1; Rectangle r; aux = w->aux; draw(w->screen, w->r, lite, nil, ZP); for(i = 1; i < nelem(icons); i++) { y0 = i*dim.y + i-1; y1 = y0 + 1; r = rectaddpt(Rect(0, y0, dim.x, y1), w->r.min); draw(w->screen, r, dark, nil, ZP); } for(i = 0; i < nelem(icons); i++) { y0 = i*dim.y + i; y1 = y0 + dim.y; r = rectaddpt(Rect(0, y0, dim.x, y1), w->r.min); draw(w->screen, r, dark, icons[i].up, ZP); } if(aux->selection < 0) return; r = irect(w, aux->selection); draw(w->screen, r, dark, nil, ZP); draw(w->screen, r, lite, icons[aux->selection].up, ZP); } static void wfree(Widget *w) { deselecttool(w); free(w->aux); free(w); } void deselecttool(Widget *w) { select(w->aux, -1); } Widget * mktoolboxwidget(Widget *canvas) { Widget *w; Aux *aux; int i; Rectangle r; if(lite == nil) { if((lite = allocimage(display, Rect(0, 0, 1, 1), GREY8, 1, 0xD7D7D7FF)) == nil || (dark = allocimage(display, Rect(0, 0, 1, 1), GREY8, 1, 0x000000FF)) == nil ) sysfatal("mktoolboxwidget: alloc colors: %r"); for(i = 0; i < nelem(icons); i++) { if(icons[i].bits == nil) icons[i].up = allocimage(display, Rect(0, 0, 1, 1), GREY1, 1, DTransparent); else icons[i].up = loadbitmap((Bitmap){32, 32, GREY1, icons[i].bits}); if(icons[i].up == nil) sysfatal("mktoolboxwidget: load bitmap %d: %r", i); } } aux = emalloc(sizeof(*aux)); aux->canvas = canvas; select(aux, TBrush); r = Rect(0, 0, dim.x, dim.y * nelem(icons) + nelem(icons)-1); if((w = mkwidget(r, mouse, widgetsyncnop, redraw, widgetdimsnop, widgetresizenop, wfree, aux)) == nil) sysfatal("mktoolboxwidget: %r"); return w; }