xref: /plan9/sys/src/libcontrol/box.c (revision da79363fb9fd5a76e4ca65f2f996542f71fcdfef)
180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <draw.h>
480ee5cbfSDavid du Colombier #include <thread.h>
580ee5cbfSDavid du Colombier #include <mouse.h>
680ee5cbfSDavid du Colombier #include <keyboard.h>
780ee5cbfSDavid du Colombier #include <control.h>
880ee5cbfSDavid du Colombier 
980ee5cbfSDavid du Colombier typedef struct Box Box;
1080ee5cbfSDavid du Colombier 
1180ee5cbfSDavid du Colombier struct Box
1280ee5cbfSDavid du Colombier {
1380ee5cbfSDavid du Colombier 	Control;
1480ee5cbfSDavid du Colombier 	int		border;
1580ee5cbfSDavid du Colombier 	CImage	*bordercolor;
1680ee5cbfSDavid du Colombier 	CImage	*image;
1780ee5cbfSDavid du Colombier 	int		align;
1880ee5cbfSDavid du Colombier };
1980ee5cbfSDavid du Colombier 
2080ee5cbfSDavid du Colombier enum{
2180ee5cbfSDavid du Colombier 	EAlign,
2280ee5cbfSDavid du Colombier 	EBorder,
2380ee5cbfSDavid du Colombier 	EBordercolor,
2480ee5cbfSDavid du Colombier 	EFocus,
259a747e4fSDavid du Colombier 	EHide,
2680ee5cbfSDavid du Colombier 	EImage,
2780ee5cbfSDavid du Colombier 	ERect,
289a747e4fSDavid du Colombier 	EReveal,
2980ee5cbfSDavid du Colombier 	EShow,
309a747e4fSDavid du Colombier 	ESize,
3180ee5cbfSDavid du Colombier };
3280ee5cbfSDavid du Colombier 
3380ee5cbfSDavid du Colombier static char *cmds[] = {
3480ee5cbfSDavid du Colombier 	[EAlign] =		"align",
3580ee5cbfSDavid du Colombier 	[EBorder] =	"border",
3680ee5cbfSDavid du Colombier 	[EBordercolor] ="bordercolor",
3780ee5cbfSDavid du Colombier 	[EFocus] = 	"focus",
389a747e4fSDavid du Colombier 	[EHide] =		"hide",
3980ee5cbfSDavid du Colombier 	[EImage] =	"image",
4080ee5cbfSDavid du Colombier 	[ERect] =		"rect",
419a747e4fSDavid du Colombier 	[EReveal] =	"reveal",
4280ee5cbfSDavid du Colombier 	[EShow] =		"show",
439a747e4fSDavid du Colombier 	[ESize] =		"size",
4480ee5cbfSDavid du Colombier 	nil
4580ee5cbfSDavid du Colombier };
4680ee5cbfSDavid du Colombier 
4780ee5cbfSDavid du Colombier static void
boxkey(Control * c,Rune * rp)489a747e4fSDavid du Colombier boxkey(Control *c, Rune *rp)
4980ee5cbfSDavid du Colombier {
5080ee5cbfSDavid du Colombier 	Box *b;
5180ee5cbfSDavid du Colombier 
529a747e4fSDavid du Colombier 	b = (Box*)c;
539a747e4fSDavid du Colombier 	chanprint(b->event, "%q: key 0x%x", b->name, rp[0]);
5480ee5cbfSDavid du Colombier }
5580ee5cbfSDavid du Colombier 
5680ee5cbfSDavid du Colombier static void
boxmouse(Control * c,Mouse * m)579a747e4fSDavid du Colombier boxmouse(Control *c, Mouse *m)
5880ee5cbfSDavid du Colombier {
599a747e4fSDavid du Colombier 	Box *b;
609a747e4fSDavid du Colombier 
619a747e4fSDavid du Colombier 	b = (Box*)c;
62*da79363fSDavid du Colombier 	if (ptinrect(m->xy,b->rect))
639a747e4fSDavid du Colombier 		chanprint(b->event, "%q: mouse %P %d %ld", b->name,
649a747e4fSDavid du Colombier 			m->xy, m->buttons, m->msec);
659a747e4fSDavid du Colombier }
669a747e4fSDavid du Colombier 
679a747e4fSDavid du Colombier static void
boxfree(Control * c)689a747e4fSDavid du Colombier boxfree(Control *c)
699a747e4fSDavid du Colombier {
709a747e4fSDavid du Colombier 	_putctlimage(((Box*)c)->image);
7180ee5cbfSDavid du Colombier }
7280ee5cbfSDavid du Colombier 
7380ee5cbfSDavid du Colombier static void
boxshow(Box * b)7480ee5cbfSDavid du Colombier boxshow(Box *b)
7580ee5cbfSDavid du Colombier {
7680ee5cbfSDavid du Colombier 	Image *i;
7780ee5cbfSDavid du Colombier 	Rectangle r;
7880ee5cbfSDavid du Colombier 
799a747e4fSDavid du Colombier 	if(b->hidden)
809a747e4fSDavid du Colombier 		return;
8180ee5cbfSDavid du Colombier 	if(b->border > 0){
8280ee5cbfSDavid du Colombier 		border(b->screen, b->rect, b->border, b->bordercolor->image, ZP);
8380ee5cbfSDavid du Colombier 		r = insetrect(b->rect, b->border);
8480ee5cbfSDavid du Colombier 	}else
8580ee5cbfSDavid du Colombier 		r = b->rect;
8680ee5cbfSDavid du Colombier 	i = b->image->image;
8780ee5cbfSDavid du Colombier 	/* BUG: ALIGNMENT AND CLIPPING */
8880ee5cbfSDavid du Colombier 	draw(b->screen, r, i, nil, ZP);
8980ee5cbfSDavid du Colombier }
9080ee5cbfSDavid du Colombier 
9180ee5cbfSDavid du Colombier static void
boxctl(Control * c,CParse * cp)929a747e4fSDavid du Colombier boxctl(Control *c, CParse *cp)
9380ee5cbfSDavid du Colombier {
9480ee5cbfSDavid du Colombier 	int cmd;
9580ee5cbfSDavid du Colombier 	Rectangle r;
9680ee5cbfSDavid du Colombier 	Box *b;
9780ee5cbfSDavid du Colombier 
9880ee5cbfSDavid du Colombier 	b = (Box*)c;
999a747e4fSDavid du Colombier 	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
10080ee5cbfSDavid du Colombier 	switch(cmd){
10180ee5cbfSDavid du Colombier 	default:
1029a747e4fSDavid du Colombier 		ctlerror("%q: unrecognized message '%s'", b->name, cp->str);
10380ee5cbfSDavid du Colombier 		break;
10480ee5cbfSDavid du Colombier 	case EAlign:
1059a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 2);
1069a747e4fSDavid du Colombier 		b->align = _ctlalignment(cp->args[1]);
10780ee5cbfSDavid du Colombier 		break;
10880ee5cbfSDavid du Colombier 	case EBorder:
1099a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 2);
1109a747e4fSDavid du Colombier 		if(cp->iargs[1] < 0)
1119a747e4fSDavid du Colombier 			ctlerror("%q: bad border: %c", b->name, cp->str);
1129a747e4fSDavid du Colombier 		b->border = cp->iargs[1];
11380ee5cbfSDavid du Colombier 		break;
11480ee5cbfSDavid du Colombier 	case EBordercolor:
1159a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 2);
1169a747e4fSDavid du Colombier 		_setctlimage(b, &b->bordercolor, cp->args[1]);
11780ee5cbfSDavid du Colombier 		break;
11880ee5cbfSDavid du Colombier 	case EFocus:
1199a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 2);
1209a747e4fSDavid du Colombier 		chanprint(b->event, "%q: focus %s", b->name, cp->args[1]);
1219a747e4fSDavid du Colombier 		break;
1229a747e4fSDavid du Colombier 	case EHide:
1239a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 1);
1249a747e4fSDavid du Colombier 		b->hidden = 1;
12580ee5cbfSDavid du Colombier 		break;
12680ee5cbfSDavid du Colombier 	case EImage:
1279a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 2);
1289a747e4fSDavid du Colombier 		_setctlimage(b, &b->image, cp->args[1]);
12980ee5cbfSDavid du Colombier 		break;
13080ee5cbfSDavid du Colombier 	case ERect:
1319a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 5);
1329a747e4fSDavid du Colombier 		r.min.x = cp->iargs[1];
1339a747e4fSDavid du Colombier 		r.min.y = cp->iargs[2];
1349a747e4fSDavid du Colombier 		r.max.x = cp->iargs[3];
1359a747e4fSDavid du Colombier 		r.max.y = cp->iargs[4];
13680ee5cbfSDavid du Colombier 		if(Dx(r)<0 || Dy(r)<0)
1379a747e4fSDavid du Colombier 			ctlerror("%q: bad rectangle: %s", b->name, cp->str);
13880ee5cbfSDavid du Colombier 		b->rect = r;
13980ee5cbfSDavid du Colombier 		break;
1409a747e4fSDavid du Colombier 	case EReveal:
1419a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 1);
1429a747e4fSDavid du Colombier 		b->hidden = 0;
14380ee5cbfSDavid du Colombier 		boxshow(b);
14480ee5cbfSDavid du Colombier 		break;
1459a747e4fSDavid du Colombier 	case EShow:
1469a747e4fSDavid du Colombier 		_ctlargcount(b, cp, 1);
1479a747e4fSDavid du Colombier 		boxshow(b);
1489a747e4fSDavid du Colombier 		break;
1499a747e4fSDavid du Colombier 	case ESize:
1509a747e4fSDavid du Colombier 		if (cp->nargs == 3)
1519a747e4fSDavid du Colombier 			r.max = Pt(0x7fffffff, 0x7fffffff);
1529a747e4fSDavid du Colombier 		else{
1539a747e4fSDavid du Colombier 			_ctlargcount(b, cp, 5);
1549a747e4fSDavid du Colombier 			r.max.x = cp->iargs[3];
1559a747e4fSDavid du Colombier 			r.max.y = cp->iargs[4];
15680ee5cbfSDavid du Colombier 		}
1579a747e4fSDavid du Colombier 		r.min.x = cp->iargs[1];
1589a747e4fSDavid du Colombier 		r.min.y = cp->iargs[2];
1599a747e4fSDavid du Colombier 		if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y)
1609a747e4fSDavid du Colombier 			ctlerror("%q: bad sizes: %s", b->name, cp->str);
1619a747e4fSDavid du Colombier 		b->size.min = r.min;
1629a747e4fSDavid du Colombier 		b->size.max = r.max;
1639a747e4fSDavid du Colombier 		break;
1649a747e4fSDavid du Colombier 	}
1659a747e4fSDavid du Colombier }
1669a747e4fSDavid du Colombier 
1679a747e4fSDavid du Colombier Control*
createbox(Controlset * cs,char * name)1689a747e4fSDavid du Colombier createbox(Controlset *cs, char *name)
1699a747e4fSDavid du Colombier {
1709a747e4fSDavid du Colombier 	Box *b;
1719a747e4fSDavid du Colombier 
1729a747e4fSDavid du Colombier 	b = (Box *)_createctl(cs, "box", sizeof(Box), name);
1739a747e4fSDavid du Colombier 	b->image = _getctlimage("white");
1749a747e4fSDavid du Colombier 	b->bordercolor = _getctlimage("black");
1759a747e4fSDavid du Colombier 	b->align = Aupperleft;
1769a747e4fSDavid du Colombier 	b->key = boxkey;
1779a747e4fSDavid du Colombier 	b->mouse = boxmouse;
1789a747e4fSDavid du Colombier 	b->ctl = boxctl;
1799a747e4fSDavid du Colombier 	b->exit = boxfree;
1809a747e4fSDavid du Colombier 	return (Control *)b;
18180ee5cbfSDavid du Colombier }
182