ref: 152159a8297a7595b4455c03361851d354288177
dir: /sys/src/libcontrol/tabs.c/
#include <u.h> #include <libc.h> #include <thread.h> #include <draw.h> #include <mouse.h> #include <keyboard.h> #include <control.h> #include "group.h" typedef struct Tab Tab; struct Tab { Control; int border; int selected; int separation; char *format; CImage *bordercolor; CImage *image; Control *tabrow; Control *tabstack; Control *tabcolumn; int ntabs; int nbuttons; Control **buttons; }; enum{ EAdd, EBorder, EBordercolor, EButton, EFocus, EFormat, EHide, EImage, ERect, EReveal, ESeparation, ESeparatorcolor, EShow, ESize, EValue, }; static char *cmds[] = { [EAdd] = "add", [EBorder] = "border", [EBordercolor] = "bordercolor", [EButton] = "button", [EFocus] = "focus", [EFormat] = "format", [EHide] = "hide", [EImage] = "image", [ERect] = "rect", [EReveal] = "reveal", [ESeparation] = "separation", [ESeparatorcolor] = "separatorcolor", [EShow] = "show", [ESize] = "size", [EValue] = "value", }; static void tabshow(Tab *t) { int i; Rectangle r; Group *g; if (t->hidden) return; for(i=0; i<t->nbuttons; i++){ _ctlprint(t->buttons[i], "value %d", (t->selected==i)); } _ctlprint(t->tabstack, "reveal %d", t->selected); _ctlprint(t->tabcolumn, "show"); if (t->selected < 0) return; g = (Group*)t->tabcolumn; if (g->nseparators == 0){ return; } r = g->separators[0]; r.min.x = t->buttons[t->selected]->rect.min.x; r.max.x = t->buttons[t->selected]->rect.max.x; draw(t->screen, r, t->image->image, nil, t->image->image->r.min); flushimage(display, 1); } static void tabsize(Control *c) { Tab *t = (Tab*)c; if (t->tabcolumn && t->tabcolumn->setsize) t->tabcolumn->setsize((Control*)t->tabcolumn); } static void tabctl(Control *c, CParse *cp) { int cmd, i; Control *cbut, *cwin; Tab *t; Rectangle r; t = (Tab*)c; cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); switch(cmd){ case EAdd: if ((cp->nargs & 1) == 0) ctlerror("%q: arg count: %s", t->name, cp->args[1]); for (i = 1; i < cp->nargs; i += 2){ cbut = controlcalled(cp->args[i]); if (cbut == nil) ctlerror("%q: no such control: %s", t->name, cp->args[i]); cwin = controlcalled(cp->args[i+1]); if (cwin == nil) ctlerror("%q: no such control: %s", t->name, cp->args[i+1]); _ctladdgroup(t->tabrow, cbut); _ctlprint(t->tabstack, "add %q", cp->args[i+1]); _ctlprint(cbut, "format '%%s: %q button %%d'", t->name); controlwire(cbut, "event", t->controlset->ctl); t->buttons = ctlrealloc(t->buttons, (t->nbuttons+1)*sizeof(Control*)); t->buttons[t->nbuttons] = cbut; t->nbuttons++; t->selected = -1; } _ctlprint(t->tabcolumn, "size"); t->size = t->tabcolumn->size; break; case EBorder: _ctlargcount(t, cp, 2); if(cp->iargs[1] < 0) ctlerror("%q: bad border: %c", t->name, cp->str); t->border = cp->iargs[1]; break; case EBordercolor: _ctlargcount(t, cp, 2); _setctlimage(t, &t->bordercolor, cp->args[1]); break; case EButton: _ctlargcount(t, cp, 2); if (cp->sender == nil) ctlerror("%q: senderless buttonevent: %q", t->name, cp->str); cbut = controlcalled(cp->sender); for(i=0; i<t->nbuttons; i++) if (cbut == t->buttons[i]) break; if (i == t->nbuttons) ctlerror("%q: not my event: %q", t->name, cp->str); if(cp->iargs[1] == 0){ /* button was turned off; turn it back on */ _ctlprint(cbut, "value 1"); }else{ t->selected = i; if (t->format) chanprint(t->event, t->format, t->name, i); tabshow(t); } break; case EFocus: /* ignore focus change */ break; case EFormat: _ctlargcount(t, cp, 2); t->format = ctlstrdup(cp->args[1]); break; case EImage: _ctlargcount(t, cp, 2); _setctlimage(t, &t->image, cp->args[1]); break; case ESeparation: t->tabrow->ctl(t->tabrow, cp); t->tabcolumn->ctl(t->tabcolumn, cp); break; case ERect: _ctlargcount(t, cp, 5); r.min.x = cp->iargs[1]; r.min.y = cp->iargs[2]; r.max.x = cp->iargs[3]; r.max.y = cp->iargs[4]; if(Dx(r)<=0 || Dy(r)<=0) ctlerror("%q: bad rectangle: %s", t->name, cp->str); t->rect = r; r = insetrect(r, t->border); _ctlprint(t->tabcolumn, "rect %R", r); break; case EReveal: _ctlargcount(t, cp, 1); case EHide: case ESize: t->tabcolumn->ctl(t->tabcolumn, cp); break; case EShow: tabshow(t); break; case EValue: _ctlargcount(t, cp, 2); if (cp->iargs[1] < 0 || cp->iargs[1] >= t->nbuttons) ctlerror("%q: illegal value '%s'", t->name, cp->str); t->selected = cp->iargs[1]; tabshow(t); break; default: ctlerror("%q: unrecognized message '%s'", t->name, cp->str); break; } } static void tabfree(Control*c) { Tab *t = (Tab*)c; t->nbuttons = 0; free(t->buttons); t->buttons = 0; } static void activatetab(Control *c, int act) { Tab *t; t = (Tab*)c; if (act) activate(t->tabcolumn); else deactivate(t->tabcolumn); } Control * createtab(Controlset *cs, char *name) { char s[128]; Tab *t; t = (Tab*)_createctl(cs, "tab", sizeof(Tab), name); t->selected = -1; t->nbuttons = 0; t->ctl = tabctl; t->mouse = nil; t->exit = tabfree; snprint(s, sizeof s, "_%s-row", name); t->tabrow = createrow(cs, s); snprint(s, sizeof s, "_%s-stack", name); t->tabstack = createstack(cs, s); snprint(s, sizeof s, "_%s-column", name); t->tabcolumn = createcolumn(cs, s); ctlprint(t->tabcolumn, "add %q %q", t->tabrow->name, t->tabstack->name); t->bordercolor = _getctlimage("black"); t->image = _getctlimage("white"); t->setsize = tabsize; t->activate = activatetab; return (Control*)t; }