]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libcontrol/textbutton.c
fix fuckup
[plan9front.git] / sys / src / libcontrol / textbutton.c
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
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
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
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
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*
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 }