xref: /plan9/sys/src/libcontrol/textbutton3.c (revision 6f314b92956e16637888967d7478acfbd2ac8dab)
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