/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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 voidtabshow(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 voidtabsize(Control *c){ Tab *t = (Tab*)c; if (t->tabcolumn && t->tabcolumn->setsize) t->tabcolumn->setsize((Control*)t->tabcolumn);} static voidtabctl(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 voidtabfree(Control*c){ Tab *t = (Tab*)c; t->nbuttons = 0; free(t->buttons); t->buttons = 0;} static voidactivatetab(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;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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;
}