257 lines
5.4 KiB
C
257 lines
5.4 KiB
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;
|
||
|
}
|