]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libcontrol/tabs.c
usbxhci: implement command timeouts and aborts, serialize unstall
[plan9front.git] / sys / src / libcontrol / tabs.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <draw.h>
5 #include <mouse.h>
6 #include <keyboard.h>
7 #include <control.h>
8 #include "group.h"
9
10 typedef struct Tab Tab;
11
12 struct Tab {
13         Control;
14         int             border;
15         int             selected;
16         int             separation;
17         char            *format;
18         CImage  *bordercolor;
19         CImage  *image;
20         Control *tabrow;
21         Control *tabstack;
22         Control *tabcolumn;
23         int             ntabs;
24         int             nbuttons;
25         Control **buttons;
26 };
27
28 enum{
29         EAdd,
30         EBorder,
31         EBordercolor,
32         EButton,
33         EFocus,
34         EFormat,
35         EHide,
36         EImage,
37         ERect,
38         EReveal,
39         ESeparation,
40         ESeparatorcolor,
41         EShow,
42         ESize,
43         EValue,
44 };
45
46 static char *cmds[] = {
47         [EAdd] =                        "add",
48         [EBorder] =             "border",
49         [EBordercolor] =        "bordercolor",
50         [EButton] =             "button",
51         [EFocus] =              "focus",
52         [EFormat] =             "format",
53         [EHide] =                       "hide",
54         [EImage] =              "image",
55         [ERect] =                       "rect",
56         [EReveal] =             "reveal",
57         [ESeparation] =         "separation",
58         [ESeparatorcolor] =     "separatorcolor",
59         [EShow] =                       "show",
60         [ESize] =                       "size",
61         [EValue] =                      "value",
62 };
63
64 static void
65 tabshow(Tab *t)
66 {
67         int i;
68         Rectangle r;
69         Group *g;
70
71         if (t->hidden)
72                 return;
73         for(i=0; i<t->nbuttons; i++){
74                 _ctlprint(t->buttons[i], "value %d", (t->selected==i));
75         }
76         _ctlprint(t->tabstack, "reveal %d", t->selected);
77         _ctlprint(t->tabcolumn, "show");
78         if (t->selected < 0)
79                 return;
80         g = (Group*)t->tabcolumn;
81         if (g->nseparators == 0){
82                 return;
83         }
84         r = g->separators[0];
85         r.min.x = t->buttons[t->selected]->rect.min.x;
86         r.max.x = t->buttons[t->selected]->rect.max.x;
87         draw(t->screen, r, t->image->image, nil, t->image->image->r.min);
88         flushimage(display, 1);
89 }
90
91 static void
92 tabsize(Control *c)
93 {
94         Tab *t = (Tab*)c;
95         if (t->tabcolumn && t->tabcolumn->setsize)
96                 t->tabcolumn->setsize((Control*)t->tabcolumn);
97 }
98
99 static void
100 tabctl(Control *c, CParse *cp)
101 {
102         int cmd, i;
103         Control *cbut, *cwin;
104         Tab *t;
105         Rectangle r;
106
107         t = (Tab*)c;
108         cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
109         switch(cmd){
110         case EAdd:
111                 if ((cp->nargs & 1) == 0)
112                         ctlerror("%q: arg count: %s", t->name, cp->args[1]);
113                 for (i = 1; i < cp->nargs; i += 2){
114                         cbut = controlcalled(cp->args[i]);
115                         if (cbut == nil)
116                                 ctlerror("%q: no such control: %s", t->name, cp->args[i]);
117                         cwin = controlcalled(cp->args[i+1]);
118                         if (cwin == nil)
119                                 ctlerror("%q: no such control: %s", t->name, cp->args[i+1]);
120                         _ctladdgroup(t->tabrow, cbut);
121                         _ctlprint(t->tabstack, "add %q", cp->args[i+1]);
122                         _ctlprint(cbut, "format '%%s: %q button %%d'", t->name);
123                         controlwire(cbut, "event", t->controlset->ctl);
124                         t->buttons = ctlrealloc(t->buttons, (t->nbuttons+1)*sizeof(Control*));
125                         t->buttons[t->nbuttons] = cbut;
126                         t->nbuttons++;
127                         t->selected = -1;
128                 }
129                 _ctlprint(t->tabcolumn, "size");
130                 t->size = t->tabcolumn->size;
131                 break;
132         case EBorder:
133                 _ctlargcount(t, cp, 2);
134                 if(cp->iargs[1] < 0)
135                         ctlerror("%q: bad border: %c", t->name, cp->str);
136                 t->border = cp->iargs[1];
137                 break;
138         case EBordercolor:
139                 _ctlargcount(t, cp, 2);
140                 _setctlimage(t, &t->bordercolor, cp->args[1]);
141                 break;
142         case EButton:
143                 _ctlargcount(t, cp, 2);
144                 if (cp->sender == nil)
145                         ctlerror("%q: senderless buttonevent: %q", t->name, cp->str);
146                 cbut = controlcalled(cp->sender);
147                 for(i=0; i<t->nbuttons; i++)
148                         if (cbut == t->buttons[i])
149                                 break;
150                 if (i == t->nbuttons)
151                         ctlerror("%q: not my event: %q", t->name, cp->str);
152                 if(cp->iargs[1] == 0){
153                         /* button was turned off; turn it back on */
154                         _ctlprint(cbut, "value 1");
155                 }else{
156                         t->selected = i;
157                         if (t->format)
158                                 chanprint(t->event, t->format, t->name, i);
159                         tabshow(t);
160                 }
161                 break;
162         case EFocus:
163                 /* ignore focus change */
164                 break;
165         case EFormat:
166                 _ctlargcount(t, cp, 2);
167                 t->format = ctlstrdup(cp->args[1]);
168                 break;
169         case EImage:
170                 _ctlargcount(t, cp, 2);
171                 _setctlimage(t, &t->image, cp->args[1]);
172                 break;
173         case ESeparation:
174                 t->tabrow->ctl(t->tabrow, cp);
175                 t->tabcolumn->ctl(t->tabcolumn, cp);
176                 break;
177         case ERect:
178                 _ctlargcount(t, cp, 5);
179                 r.min.x = cp->iargs[1];
180                 r.min.y = cp->iargs[2];
181                 r.max.x = cp->iargs[3];
182                 r.max.y = cp->iargs[4];
183                 if(Dx(r)<=0 || Dy(r)<=0)
184                         ctlerror("%q: bad rectangle: %s", t->name, cp->str);
185                 t->rect = r;
186                 r = insetrect(r, t->border);
187                 _ctlprint(t->tabcolumn, "rect %R", r);
188                 break;
189         case EReveal:
190                 _ctlargcount(t, cp, 1);
191         case EHide:
192         case ESize:
193                 t->tabcolumn->ctl(t->tabcolumn, cp);
194                 break;
195         case EShow:
196                 tabshow(t);
197                 break;
198         case EValue:
199                 _ctlargcount(t, cp, 2);
200                 if (cp->iargs[1] < 0 || cp->iargs[1] >= t->nbuttons)
201                         ctlerror("%q: illegal value '%s'", t->name, cp->str);
202                 t->selected = cp->iargs[1];
203                 tabshow(t);
204                 break;
205         default:
206                 ctlerror("%q: unrecognized message '%s'", t->name, cp->str);
207                 break;
208         }
209 }
210
211 static void
212 tabfree(Control*c)
213 {
214         Tab *t = (Tab*)c;
215         t->nbuttons = 0;
216         free(t->buttons);
217         t->buttons = 0;
218 }
219
220 static void
221 activatetab(Control *c, int act)
222 {
223         Tab *t;
224
225         t = (Tab*)c;
226         if (act)
227                 activate(t->tabcolumn);
228         else
229                 deactivate(t->tabcolumn);
230 }
231         
232 Control *
233 createtab(Controlset *cs, char *name)
234 {
235         char s[128];
236
237         Tab *t;
238         t = (Tab*)_createctl(cs, "tab", sizeof(Tab), name);
239         t->selected = -1;
240         t->nbuttons = 0;
241         t->ctl = tabctl;
242         t->mouse = nil;
243         t->exit = tabfree;
244         snprint(s, sizeof s, "_%s-row", name);
245         t->tabrow = createrow(cs, s);
246         snprint(s, sizeof s, "_%s-stack", name);
247         t->tabstack = createstack(cs, s);
248         snprint(s, sizeof s, "_%s-column", name);
249         t->tabcolumn = createcolumn(cs, s);
250         ctlprint(t->tabcolumn, "add %q %q", t->tabrow->name, t->tabstack->name);
251         t->bordercolor = _getctlimage("black");
252         t->image = _getctlimage("white");
253         t->setsize = tabsize;
254         t->activate = activatetab;
255         return (Control*)t;
256 }