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 } 257