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 Button Button;
10
11 struct Button
12 {
13 Control;
14 CImage *image;
15 CImage *mask;
16 CImage *light;
17 CImage *pale;
18 CImage *bordercolor;
19 int pressed;
20 int lastbut;
21 int lastshow;
22 int border;
23 int align;
24 int off;
25 int prepress;
26 };
27
28 enum{
29 EAlign,
30 EBorder,
31 EBordercolor,
32 EFocus,
33 EFormat,
34 EHide,
35 EImage,
36 ELight,
37 EMask,
38 EPale,
39 ERect,
40 EReveal,
41 EShow,
42 ESize,
43 EValue,
44 };
45
46 static char *cmds[] = {
47 [EAlign] = "align",
48 [EBorder] = "border",
49 [EBordercolor] = "bordercolor",
50 [EFocus] = "focus",
51 [EFormat] = "format",
52 [EHide] = "hide",
53 [EImage] = "image",
54 [ELight] = "light",
55 [EMask] = "mask",
56 [EPale] = "pale",
57 [ERect] = "rect",
58 [EReveal] = "reveal",
59 [EShow] = "show",
60 [ESize] = "size",
61 [EValue] = "value",
62 nil
63 };
64
65 static void
buttonfree(Control * c)66 buttonfree(Control *c)
67 {
68 Button *b;
69
70 b = (Button *)c;
71 _putctlimage(b->image);
72 _putctlimage(b->mask);
73 _putctlimage(b->light);
74 _putctlimage(b->pale);
75 _putctlimage(b->bordercolor);
76 }
77
78 static void
buttonshow(Button * b)79 buttonshow(Button *b)
80 {
81 Rectangle r;
82
83 if (b->hidden)
84 return;
85 r = b->rect;
86 if(b->border > 0){
87 border(b->screen, r, b->border, b->bordercolor->image, ZP);
88 r = insetrect(b->rect, b->border);
89 }
90 draw(b->screen, r, b->image->image, nil, b->image->image->r.min);
91 if(b->off)
92 draw(b->screen, r, b->pale->image, b->mask->image, b->mask->image->r.min);
93 else if(b->pressed)
94 draw(b->screen, r, b->light->image, b->mask->image, b->mask->image->r.min);
95 b->lastshow = b->pressed;
96 flushimage(display, 1);
97 }
98
99 static void
buttonmouse(Control * c,Mouse * m)100 buttonmouse(Control *c, Mouse *m)
101 {
102 Button *b;
103
104 b = (Button*)c;
105
106 if(m->buttons&7) {
107 if (ptinrect(m->xy,b->rect)) {
108 if (b->off) {
109 b->off = 0;
110 buttonshow(b);
111 }
112 } else {
113 if (!b->off) {
114 b->off = 1;
115 buttonshow(b);
116 }
117 }
118 }
119 if((m->buttons&7) != b->lastbut){
120 if(m->buttons & 7){
121 b->prepress = b->pressed;
122 if (b->pressed)
123 b->pressed = 0;
124 else
125 b->pressed = m->buttons & 7;
126 buttonshow(b);
127 }else /* generate event on button up */
128 if (ptinrect(m->xy,b->rect))
129 chanprint(b->event, b->format, b->name, b->pressed);
130 else {
131 b->off = 0;
132 b->pressed = b->prepress;
133 buttonshow(b);
134 }
135 }
136 b->lastbut = m->buttons & 7;
137 }
138
139 static void
buttonctl(Control * c,CParse * cp)140 buttonctl(Control *c, CParse *cp)
141 {
142 int cmd;
143 Rectangle r;
144 Button *b;
145
146 b = (Button*)c;
147 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
148 switch(cmd){
149 default:
150 ctlerror("%q: unrecognized message '%s'", b->name, cp->str);
151 break;
152 case EAlign:
153 _ctlargcount(b, cp, 2);
154 b->align = _ctlalignment(cp->args[1]);
155 b->lastshow = -1; /* force redraw */
156 break;
157 case EBorder:
158 _ctlargcount(b, cp, 2);
159 b->border = cp->iargs[1];
160 b->lastshow = -1; /* force redraw */
161 break;
162 case EBordercolor:
163 _ctlargcount(b, cp, 2);
164 _setctlimage(b, &b->bordercolor, cp->args[1]);
165 b->lastshow = -1; /* force redraw */
166 break;
167 case EFocus:
168 /* ignore focus change */
169 break;
170 case EFormat:
171 _ctlargcount(b, cp, 2);
172 b->format = ctlstrdup(cp->args[1]);
173 break;
174 case EHide:
175 _ctlargcount(b, cp, 1);
176 b->hidden = 1;
177 break;
178 case EImage:
179 _ctlargcount(b, cp, 2);
180 _setctlimage(b, &b->image, cp->args[1]);
181 b->lastshow = -1; /* force redraw */
182 break;
183 case ELight:
184 _ctlargcount(b, cp, 2);
185 _setctlimage(b, &b->light, cp->args[1]);
186 b->lastshow = -1; /* force redraw */
187 break;
188 case EMask:
189 _ctlargcount(b, cp, 2);
190 _setctlimage(b, &b->mask, cp->args[1]);
191 b->lastshow = -1; /* force redraw */
192 break;
193 case EPale:
194 _ctlargcount(b, cp, 2);
195 _setctlimage(b, &b->pale, cp->args[1]);
196 b->lastshow = -1; /* force redraw */
197 break;
198 case ERect:
199 _ctlargcount(b, cp, 5);
200 r.min.x = cp->iargs[1];
201 r.min.y = cp->iargs[2];
202 r.max.x = cp->iargs[3];
203 r.max.y = cp->iargs[4];
204 if(Dx(r)<0 || Dy(r)<0)
205 ctlerror("%q: bad rectangle: %s", b->name, cp->str);
206 b->rect = r;
207 b->lastshow = -1; /* force redraw */
208 break;
209 case EReveal:
210 _ctlargcount(b, cp, 1);
211 b->hidden = 0;
212 buttonshow(b);
213 break;
214 case EShow:
215 _ctlargcount(b, cp, 1);
216 buttonshow(b);
217 break;
218 case ESize:
219 if (cp->nargs == 3)
220 r.max = Pt(0x7fffffff, 0x7fffffff);
221 else{
222 _ctlargcount(b, cp, 5);
223 r.max.x = cp->iargs[3];
224 r.max.y = cp->iargs[4];
225 }
226 r.min.x = cp->iargs[1];
227 r.min.y = cp->iargs[2];
228 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)
229 ctlerror("%q: bad sizes: %s", b->name, cp->str);
230 b->size.min = r.min;
231 b->size.max = r.max;
232 break;
233 case EValue:
234 _ctlargcount(b, cp, 2);
235 if((cp->iargs[1]!=0) != b->pressed){
236 b->pressed ^= 1;
237 buttonshow(b);
238 }
239 break;
240 }
241 }
242
243 Control*
createbutton(Controlset * cs,char * name)244 createbutton(Controlset *cs, char *name)
245 {
246 Button *b;
247 b = (Button*)_createctl(cs, "button", sizeof(Button), name);
248 b->image = _getctlimage("white");
249 b->mask = _getctlimage("opaque");
250 b->light = _getctlimage("yellow");
251 b->pale = _getctlimage("paleyellow");
252 b->bordercolor = _getctlimage("black");
253 b->format = ctlstrdup("%q: value %d");
254 b->lastshow = -1;
255 b->border = 0;
256 b->align = Aupperleft;
257 b->ctl = buttonctl;
258 b->mouse = buttonmouse;
259 b->key = nil;
260 b->exit = buttonfree;
261 b->off = 0;
262 b->prepress = 0;
263 return (Control*)b;
264 }
265