]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libcontrol/button.c
snoopy(8): avoid extra spaces in dhcp filter output
[plan9front.git] / sys / src / libcontrol / button.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 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
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
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
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
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*
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 }