xref: /plan9/sys/src/libcontrol/box.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
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
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
57 boxmouse(Control *c, Mouse *m)
58 {
59 	Box *b;
60 
61 	b = (Box*)c;
62 	chanprint(b->event, "%q: mouse %P %d %ld", b->name,
63 		m->xy, m->buttons, m->msec);
64 }
65 
66 static void
67 boxfree(Control *c)
68 {
69 	_putctlimage(((Box*)c)->image);
70 }
71 
72 static void
73 boxshow(Box *b)
74 {
75 	Image *i;
76 	Rectangle r;
77 
78 	if(b->hidden)
79 		return;
80 	if(b->border > 0){
81 		border(b->screen, b->rect, b->border, b->bordercolor->image, ZP);
82 		r = insetrect(b->rect, b->border);
83 	}else
84 		r = b->rect;
85 	i = b->image->image;
86 	/* BUG: ALIGNMENT AND CLIPPING */
87 	draw(b->screen, r, i, nil, ZP);
88 }
89 
90 static void
91 boxctl(Control *c, CParse *cp)
92 {
93 	int cmd;
94 	Rectangle r;
95 	Box *b;
96 
97 	b = (Box*)c;
98 	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
99 	switch(cmd){
100 	default:
101 		ctlerror("%q: unrecognized message '%s'", b->name, cp->str);
102 		break;
103 	case EAlign:
104 		_ctlargcount(b, cp, 2);
105 		b->align = _ctlalignment(cp->args[1]);
106 		break;
107 	case EBorder:
108 		_ctlargcount(b, cp, 2);
109 		if(cp->iargs[1] < 0)
110 			ctlerror("%q: bad border: %c", b->name, cp->str);
111 		b->border = cp->iargs[1];
112 		break;
113 	case EBordercolor:
114 		_ctlargcount(b, cp, 2);
115 		_setctlimage(b, &b->bordercolor, cp->args[1]);
116 		break;
117 	case EFocus:
118 		_ctlargcount(b, cp, 2);
119 		chanprint(b->event, "%q: focus %s", b->name, cp->args[1]);
120 		break;
121 	case EHide:
122 		_ctlargcount(b, cp, 1);
123 		b->hidden = 1;
124 		break;
125 	case EImage:
126 		_ctlargcount(b, cp, 2);
127 		_setctlimage(b, &b->image, cp->args[1]);
128 		break;
129 	case ERect:
130 		_ctlargcount(b, cp, 5);
131 		r.min.x = cp->iargs[1];
132 		r.min.y = cp->iargs[2];
133 		r.max.x = cp->iargs[3];
134 		r.max.y = cp->iargs[4];
135 		if(Dx(r)<0 || Dy(r)<0)
136 			ctlerror("%q: bad rectangle: %s", b->name, cp->str);
137 		b->rect = r;
138 		break;
139 	case EReveal:
140 		_ctlargcount(b, cp, 1);
141 		b->hidden = 0;
142 		boxshow(b);
143 		break;
144 	case EShow:
145 		_ctlargcount(b, cp, 1);
146 		boxshow(b);
147 		break;
148 	case ESize:
149 		if (cp->nargs == 3)
150 			r.max = Pt(0x7fffffff, 0x7fffffff);
151 		else{
152 			_ctlargcount(b, cp, 5);
153 			r.max.x = cp->iargs[3];
154 			r.max.y = cp->iargs[4];
155 		}
156 		r.min.x = cp->iargs[1];
157 		r.min.y = cp->iargs[2];
158 		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)
159 			ctlerror("%q: bad sizes: %s", b->name, cp->str);
160 		b->size.min = r.min;
161 		b->size.max = r.max;
162 		break;
163 	}
164 }
165 
166 Control*
167 createbox(Controlset *cs, char *name)
168 {
169 	Box *b;
170 
171 	b = (Box *)_createctl(cs, "box", sizeof(Box), name);
172 	b->image = _getctlimage("white");
173 	b->bordercolor = _getctlimage("black");
174 	b->align = Aupperleft;
175 	b->key = boxkey;
176 	b->mouse = boxmouse;
177 	b->ctl = boxctl;
178 	b->exit = boxfree;
179 	return (Control *)b;
180 }
181