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