xref: /plan9-contrib/sys/src/libcontrol/tabs.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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