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
tabshow(Tab * t)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
tabsize(Control * c)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
tabctl(Control * c,CParse * cp)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
tabfree(Control * c)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
activatetab(Control * c,int act)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 *
createtab(Controlset * cs,char * name)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 }
257