xref: /plan9/sys/src/libcontrol/box.c (revision da79363fb9fd5a76e4ca65f2f996542f71fcdfef)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <keyboard.h>
7 #include <control.h>
8 
9 typedef struct Box Box;
10 
11 struct Box
12 {
13 	Control;
14 	int		border;
15 	CImage	*bordercolor;
16 	CImage	*image;
17 	int		align;
18 };
19 
20 enum{
21 	EAlign,
22 	EBorder,
23 	EBordercolor,
24 	EFocus,
25 	EHide,
26 	EImage,
27 	ERect,
28 	EReveal,
29 	EShow,
30 	ESize,
31 };
32 
33 static char *cmds[] = {
34 	[EAlign] =		"align",
35 	[EBorder] =	"border",
36 	[EBordercolor] ="bordercolor",
37 	[EFocus] = 	"focus",
38 	[EHide] =		"hide",
39 	[EImage] =	"image",
40 	[ERect] =		"rect",
41 	[EReveal] =	"reveal",
42 	[EShow] =		"show",
43 	[ESize] =		"size",
44 	nil
45 };
46 
47 static void
boxkey(Control * c,Rune * rp)48 boxkey(Control *c, Rune *rp)
49 {
50 	Box *b;
51 
52 	b = (Box*)c;
53 	chanprint(b->event, "%q: key 0x%x", b->name, rp[0]);
54 }
55 
56 static void
boxmouse(Control * c,Mouse * m)57 boxmouse(Control *c, Mouse *m)
58 {
59 	Box *b;
60 
61 	b = (Box*)c;
62 	if (ptinrect(m->xy,b->rect))
63 		chanprint(b->event, "%q: mouse %P %d %ld", b->name,
64 			m->xy, m->buttons, m->msec);
65 }
66 
67 static void
boxfree(Control * c)68 boxfree(Control *c)
69 {
70 	_putctlimage(((Box*)c)->image);
71 }
72 
73 static void
boxshow(Box * b)74 boxshow(Box *b)
75 {
76 	Image *i;
77 	Rectangle r;
78 
79 	if(b->hidden)
80 		return;
81 	if(b->border > 0){
82 		border(b->screen, b->rect, b->border, b->bordercolor->image, ZP);
83 		r = insetrect(b->rect, b->border);
84 	}else
85 		r = b->rect;
86 	i = b->image->image;
87 	/* BUG: ALIGNMENT AND CLIPPING */
88 	draw(b->screen, r, i, nil, ZP);
89 }
90 
91 static void
boxctl(Control * c,CParse * cp)92 boxctl(Control *c, CParse *cp)
93 {
94 	int cmd;
95 	Rectangle r;
96 	Box *b;
97 
98 	b = (Box*)c;
99 	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
100 	switch(cmd){
101 	default:
102 		ctlerror("%q: unrecognized message '%s'", b->name, cp->str);
103 		break;
104 	case EAlign:
105 		_ctlargcount(b, cp, 2);
106 		b->align = _ctlalignment(cp->args[1]);
107 		break;
108 	case EBorder:
109 		_ctlargcount(b, cp, 2);
110 		if(cp->iargs[1] < 0)
111 			ctlerror("%q: bad border: %c", b->name, cp->str);
112 		b->border = cp->iargs[1];
113 		break;
114 	case EBordercolor:
115 		_ctlargcount(b, cp, 2);
116 		_setctlimage(b, &b->bordercolor, cp->args[1]);
117 		break;
118 	case EFocus:
119 		_ctlargcount(b, cp, 2);
120 		chanprint(b->event, "%q: focus %s", b->name, cp->args[1]);
121 		break;
122 	case EHide:
123 		_ctlargcount(b, cp, 1);
124 		b->hidden = 1;
125 		break;
126 	case EImage:
127 		_ctlargcount(b, cp, 2);
128 		_setctlimage(b, &b->image, cp->args[1]);
129 		break;
130 	case ERect:
131 		_ctlargcount(b, cp, 5);
132 		r.min.x = cp->iargs[1];
133 		r.min.y = cp->iargs[2];
134 		r.max.x = cp->iargs[3];
135 		r.max.y = cp->iargs[4];
136 		if(Dx(r)<0 || Dy(r)<0)
137 			ctlerror("%q: bad rectangle: %s", b->name, cp->str);
138 		b->rect = r;
139 		break;
140 	case EReveal:
141 		_ctlargcount(b, cp, 1);
142 		b->hidden = 0;
143 		boxshow(b);
144 		break;
145 	case EShow:
146 		_ctlargcount(b, cp, 1);
147 		boxshow(b);
148 		break;
149 	case ESize:
150 		if (cp->nargs == 3)
151 			r.max = Pt(0x7fffffff, 0x7fffffff);
152 		else{
153 			_ctlargcount(b, cp, 5);
154 			r.max.x = cp->iargs[3];
155 			r.max.y = cp->iargs[4];
156 		}
157 		r.min.x = cp->iargs[1];
158 		r.min.y = cp->iargs[2];
159 		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)
160 			ctlerror("%q: bad sizes: %s", b->name, cp->str);
161 		b->size.min = r.min;
162 		b->size.max = r.max;
163 		break;
164 	}
165 }
166 
167 Control*
createbox(Controlset * cs,char * name)168 createbox(Controlset *cs, char *name)
169 {
170 	Box *b;
171 
172 	b = (Box *)_createctl(cs, "box", sizeof(Box), name);
173 	b->image = _getctlimage("white");
174 	b->bordercolor = _getctlimage("black");
175 	b->align = Aupperleft;
176 	b->key = boxkey;
177 	b->mouse = boxmouse;
178 	b->ctl = boxctl;
179 	b->exit = boxfree;
180 	return (Control *)b;
181 }
182