1 /* use button 3 for a proper function to the application, that is not for plumber
2 * as default control(2) supposes.
3 * codes are mostly from /sys/src/libcontrol/textbutton.c
4 */
5 #include <u.h>
6 #include <libc.h>
7 #include <draw.h>
8 #include <thread.h>
9 #include <mouse.h>
10 #include <keyboard.h>
11 #include <control.h>
12
13 typedef struct Textbutton3 Textbutton3;
14
15 struct Textbutton3
16 {
17 Control;
18 CFont *font;
19 CImage *image;
20 CImage *mask;
21 CImage *light;
22 CImage *bordercolor;
23 CImage *textcolor;
24 CImage *pressedtextcolor;
25 int pressed;
26 int lastbut;
27 int lastshow;
28 char **line;
29 int nline;
30 int align;
31 int border;
32 int left;
33 int middle;
34 int right;
35 int toggle;
36 int gettextflg;
37 };
38
39 enum{
40 EAlign,
41 EBorder,
42 EBordercolor,
43 EFocus,
44 EFont,
45 EFormat,
46 EHide,
47 EImage,
48 ELight,
49 EMask,
50 EPressedtextcolor,
51 ERect,
52 EReveal,
53 EShow,
54 ESize,
55 EText,
56 ETextcolor,
57 EEnable,
58 EDisable,
59 EToggle,
60 EGettext,
61 EValue,
62 };
63
64 static char *cmds[] = {
65 [EAlign] = "align",
66 [EBorder] = "border",
67 [EBordercolor] = "bordercolor",
68 [EFocus] = "focus",
69 [EFont] = "font",
70 [EFormat] = "format",
71 [EHide] = "hide",
72 [EImage] = "image",
73 [ELight] = "light",
74 [EMask] = "mask",
75 [EPressedtextcolor] ="pressedtextcolor",
76 [ERect] = "rect",
77 [EReveal] = "reveal",
78 [EShow] = "show",
79 [ESize] = "size",
80 [EText] = "text",
81 [ETextcolor] = "textcolor",
82 [EEnable] = "enable",
83 [EDisable] = "disable",
84 [EToggle] = "toggle",
85 [EGettext] = "gettext",
86 [EValue] = "value",
87 nil
88 };
89
90 static void textbutton3show(Textbutton3 *);
91
92 static void
textbutton3mouse(Control * c,Mouse * m)93 textbutton3mouse(Control *c, Mouse *m)
94 {
95 Textbutton3 *t;
96
97 t = (Textbutton3 *)c;
98 if(t->left == 1) {
99 if((m->buttons&1) == 1 && (t->lastbut&1) == 0){
100 t->pressed ^= 1;
101 textbutton3show(t);
102 t->lastbut = m->buttons & 1;
103 }else if((m->buttons&1) == 0 && (t->lastbut&1) == 1){
104 if(t->gettextflg == 0)
105 chanprint(t->event, t->format, t->name, t->pressed, m->xy.x, m->xy.y);
106 else
107 chanprint(t->event, "%q: value %q", t->name, t->line[0]);
108 t->pressed ^= 1;
109 textbutton3show(t);
110 t->lastbut = m->buttons & 1;
111 }
112 }
113 if(t->middle == 1) {
114 if((m->buttons&2) == 2 && (t->lastbut&2) == 0){
115 t->pressed ^= 2;
116 textbutton3show(t);
117 t->lastbut = m->buttons & 2;
118 }else if((m->buttons&2) == 0 && (t->lastbut&2) == 2){
119 if(t->gettextflg == 0)
120 chanprint(t->event, t->format, t->name, t->pressed, m->xy.x, m->xy.y);
121 else
122 chanprint(t->event, "%q: value %q", t->name, t->line[0]);
123 t->pressed ^= 2;
124 textbutton3show(t);
125 t->lastbut = m->buttons & 2;
126 }
127 }
128 if(t->right == 1) {
129 if((m->buttons&4) == 4 && (t->lastbut&4) == 0){
130 t->pressed ^= 4;
131 textbutton3show(t);
132 t->lastbut = m->buttons & 4;
133 }else if((m->buttons&4) == 0 && (t->lastbut&4) == 4){
134 if(t->gettextflg == 0)
135 chanprint(t->event, t->format, t->name, t->pressed, m->xy.x, m->xy.y);
136 else
137 chanprint(t->event, "%q: value %q", t->name, t->line[0]);
138 t->pressed ^= 4;
139 textbutton3show(t);
140 t->lastbut = m->buttons & 4;
141 }
142 }
143 }
144
145 static void
textbutton3free(Control * c)146 textbutton3free(Control *c)
147 {
148 int i;
149 Textbutton3 *t;
150
151 t = (Textbutton3*)c;
152 _putctlfont(t->font);
153 _putctlimage(t->image);
154 _putctlimage(t->light);
155 _putctlimage(t->mask);
156 _putctlimage(t->textcolor);
157 _putctlimage(t->bordercolor);
158 _putctlimage(t->pressedtextcolor);
159 for(i=0; i<t->nline; i++)
160 free(t->line[i]);
161 free(t->line);
162 }
163
164 static void
textbutton3show(Textbutton3 * t)165 textbutton3show(Textbutton3 *t)
166 {
167 Rectangle r, clipr;
168 int i, dx, dy, w;
169 Font *f;
170 Point p, q;
171 Image *im;
172
173 if(t->hidden || t->lastshow == t->pressed)
174 return;
175 f = t->font->font;
176 draw(t->screen, t->rect, t->image->image, nil, t->image->image->r.min);
177 if(t->pressed || t->toggle)
178 draw(t->screen, t->rect, t->light->image, t->mask->image, t->mask->image->r.min);
179 if(t->border > 0)
180 border(t->screen, t->rect, t->border, t->bordercolor->image, ZP);
181 /* text goes here */
182 dx = 0;
183 for(i=0; i<t->nline; i++){
184 w = stringwidth(f, t->line[i]); /*****/
185 if(dx < w)
186 dx = w;
187 }
188 dy = t->nline*f->height;
189 clipr = insetrect(t->rect, t->border);
190 p = _ctlalignpoint(clipr, dx, dy, t->align);
191 im = t->textcolor->image;
192 if(t->pressed)
193 im = t->pressedtextcolor->image;
194 for(i=0; i<t->nline; i++){
195 r.min = p;
196 r.max.x = p.x+dx;
197 r.max.y = p.y+f->height;
198 q = _ctlalignpoint(r, stringwidth(f, t->line[i]), f->height, t->align%3);
199 _string(t->screen, q, im,
200 ZP, f, t->line[i], nil, strlen(t->line[i]),
201 clipr, nil, ZP, SoverD);
202 p.y += f->height;
203 }
204 t->lastshow = t->pressed;
205 flushimage(display, 1);
206 }
207
208 static void
textbutton3ctl(Control * c,CParse * cp)209 textbutton3ctl(Control *c, CParse *cp)
210 {
211 int cmd, i;
212 Rectangle r;
213 Textbutton3 *t;
214
215 t = (Textbutton3*)c;
216 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
217 switch(cmd){
218 default:
219 ctlerror("%q: unrecognized message '%s'", t->name, cp->str);
220 break;
221 case EAlign:
222 _ctlargcount(t, cp, 2);
223 t->align = _ctlalignment(cp->args[1]);
224 t->lastshow = -1; /* force redraw */
225 break;
226 case EBorder:
227 _ctlargcount(t, cp, 2);
228 t->border = cp->iargs[1];
229 t->lastshow = -1; /* force redraw */
230 break;
231 case EBordercolor:
232 _ctlargcount(t, cp, 2);
233 _setctlimage(t, &t->bordercolor, cp->args[1]);
234 t->lastshow = -1; /* force redraw */
235 break;
236 case EFocus:
237 break;
238 case EFont:
239 _ctlargcount(t, cp, 2);
240 _setctlfont(t, &t->font, cp->args[1]);
241 t->lastshow = -1; /* force redraw */
242 break;
243 case EFormat:
244 _ctlargcount(t, cp, 2);
245 t->format = ctlstrdup(cp->args[1]);
246 break;
247 case EHide:
248 _ctlargcount(t, cp, 1);
249 t->hidden = 1;
250 break;
251 case EImage:
252 _ctlargcount(t, cp, 2);
253 _setctlimage(t, &t->image, cp->args[1]);
254 t->lastshow = -1; /* force redraw */
255 break;
256 case ELight:
257 _ctlargcount(t, cp, 2);
258 _setctlimage(t, &t->light, cp->args[1]);
259 t->lastshow = -1; /* force redraw */
260 break;
261 case EMask:
262 _ctlargcount(t, cp, 2);
263 _setctlimage(t, &t->mask, cp->args[1]);
264 t->lastshow = -1; /* force redraw */
265 break;
266 case EPressedtextcolor:
267 _ctlargcount(t, cp, 2);
268 _setctlimage(t, &t->pressedtextcolor, cp->args[1]);
269 t->lastshow = -1; /* force redraw */
270 break;
271 case ERect:
272 _ctlargcount(t, cp, 5);
273 r.min.x = cp->iargs[1];
274 r.min.y = cp->iargs[2];
275 r.max.x = cp->iargs[3];
276 r.max.y = cp->iargs[4];
277 if(Dx(r)<=0 || Dy(r)<=0)
278 ctlerror("%q: bad rectangle: %s", t->name, cp->str);
279 t->rect = r;
280 t->lastshow = -1; /* force redraw */
281 break;
282 case EReveal:
283 _ctlargcount(t, cp, 1);
284 t->hidden = 0;
285 t->lastshow = -1; /* force redraw */
286 textbutton3show(t);
287 break;
288 case EShow:
289 _ctlargcount(t, cp, 1);
290 t->lastshow = -1; /* force redraw */
291 textbutton3show(t);
292 break;
293 case ESize:
294 if (cp->nargs == 3)
295 r.max = Pt(0x7fffffff, 0x7fffffff);
296 else{
297 _ctlargcount(t, cp, 5);
298 r.max.x = cp->iargs[3];
299 r.max.y = cp->iargs[4];
300 }
301 r.min.x = cp->iargs[1];
302 r.min.y = cp->iargs[2];
303 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)
304 ctlerror("%q: bad sizes: %s", t->name, cp->str);
305 t->size.min = r.min;
306 t->size.max = r.max;
307 break;
308 case EText:
309 /* free existing text */
310 for(i=0; i<t->nline; i++)
311 free(t->line[i]);
312 t->nline = cp->nargs-1;
313 t->line = ctlrealloc(t->line, t->nline*sizeof(char*));
314 for(i=0; i<t->nline; i++)
315 t->line[i] = ctlstrdup(cp->args[i+1]);
316 t->lastshow = -1; /* force redraw */
317 textbutton3show(t);
318 break;
319 case ETextcolor:
320 _ctlargcount(t, cp, 2);
321 _setctlimage(t, &t->textcolor, cp->args[1]);
322 t->lastshow = -1; /* force redraw */
323 break;
324 case EEnable:
325 _ctlargcount(t, cp, 2);
326 if(strcmp(cp->args[1], "left") == 0)
327 t->left = 1;
328 else if(strcmp(cp->args[1], "middle") == 0)
329 t->middle = 1;
330 else if(strcmp(cp->args[1], "right") == 0)
331 t->right = 1;
332 break;
333 case EDisable:
334 _ctlargcount(t, cp, 2);
335 if(strcmp(cp->args[1], "left") == 0)
336 t->left = 0;
337 else if(strcmp(cp->args[1], "middle") == 0)
338 t->middle = 0;
339 else if(strcmp(cp->args[1], "right") == 0)
340 t->right = 0;
341 break;
342 case EToggle:
343 _ctlargcount(t, cp, 2);
344 if(strcmp(cp->args[1], "on") == 0)
345 t->toggle = 1;
346 else if(strcmp(cp->args[1], "off") == 0)
347 t->toggle = 0;
348 t->lastshow = -1; /* force redraw */
349 break;
350 case EGettext:
351 _ctlargcount(t, cp, 2);
352 if(strcmp(cp->args[1], "on") == 0)
353 t->gettextflg = 1;
354 else if(strcmp(cp->args[1], "off") == 0)
355 t->gettextflg = 0;
356 break;
357 case EValue:
358 _ctlargcount(t, cp, 2);
359 if((cp->iargs[1]!=0) != t->pressed){
360 t->pressed ^= 1;
361 textbutton3show(t);
362 }
363 break;
364 }
365 }
366
367 Control*
createtextbutton3(Controlset * cs,char * name)368 createtextbutton3(Controlset *cs, char *name)
369 {
370 Textbutton3 *t;
371
372 t = (Textbutton3 *)_createctl(cs, "textbutton3", sizeof(Textbutton3), name);
373 t->line = ctlmalloc(sizeof(char*));
374 t->nline = 0;
375 t->image = _getctlimage("white");
376 t->light = _getctlimage("yellow");
377 t->mask = _getctlimage("opaque");
378 t->bordercolor = _getctlimage("black");
379 t->textcolor = _getctlimage("black");
380 t->pressedtextcolor = _getctlimage("black");
381 t->font = _getctlfont("font");
382 t->format = ctlstrdup("%q: value %d %d %d");
383 t->lastshow = -1;
384 t->mouse = textbutton3mouse;
385 t->ctl = textbutton3ctl;
386 t->exit = textbutton3free;
387 t->left = 1;
388 t->middle = 1;
389 t->right = 1;
390 t->toggle = 0;
391 t->gettextflg = 0;
392 return (Control *)t;
393 }
394