xref: /plan9/sys/src/libcontrol/radiobutton.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <draw.h>
480ee5cbfSDavid du Colombier #include <thread.h>
580ee5cbfSDavid du Colombier #include <mouse.h>
680ee5cbfSDavid du Colombier #include <keyboard.h>
780ee5cbfSDavid du Colombier #include <control.h>
880ee5cbfSDavid du Colombier 
980ee5cbfSDavid du Colombier typedef struct Radio Radio;
1080ee5cbfSDavid du Colombier 
1180ee5cbfSDavid du Colombier struct Radio
1280ee5cbfSDavid du Colombier {
1380ee5cbfSDavid du Colombier 	Control;
1480ee5cbfSDavid du Colombier 	int		value;
1580ee5cbfSDavid du Colombier 	int		lastbut;
1680ee5cbfSDavid du Colombier 	Control	**buttons;
1780ee5cbfSDavid du Colombier 	int		nbuttons;
1880ee5cbfSDavid du Colombier 	char		*eventstr;
1980ee5cbfSDavid du Colombier };
2080ee5cbfSDavid du Colombier 
2180ee5cbfSDavid du Colombier enum{
2280ee5cbfSDavid du Colombier 	EAdd,
23*9a747e4fSDavid du Colombier 	EButton,
2480ee5cbfSDavid du Colombier 	EFocus,
2580ee5cbfSDavid du Colombier 	EFormat,
26*9a747e4fSDavid du Colombier 	EHide,
2780ee5cbfSDavid du Colombier 	ERect,
28*9a747e4fSDavid du Colombier 	EReveal,
2980ee5cbfSDavid du Colombier 	EShow,
30*9a747e4fSDavid du Colombier 	ESize,
3180ee5cbfSDavid du Colombier 	EValue,
3280ee5cbfSDavid du Colombier };
3380ee5cbfSDavid du Colombier 
3480ee5cbfSDavid du Colombier static char *cmds[] = {
3580ee5cbfSDavid du Colombier 	[EAdd] =		"add",
36*9a747e4fSDavid du Colombier 	[EButton] =	"button",
3780ee5cbfSDavid du Colombier 	[EFocus] = 	"focus",
3880ee5cbfSDavid du Colombier 	[EFormat] = 	"format",
39*9a747e4fSDavid du Colombier 	[EHide] =		"hide",
4080ee5cbfSDavid du Colombier 	[ERect] =		"rect",
41*9a747e4fSDavid du Colombier 	[EReveal] =	"reveal",
4280ee5cbfSDavid du Colombier 	[EShow] =		"show",
43*9a747e4fSDavid du Colombier 	[ESize] =		"size",
4480ee5cbfSDavid du Colombier 	[EValue] =		"value",
4580ee5cbfSDavid du Colombier 	nil
4680ee5cbfSDavid du Colombier };
4780ee5cbfSDavid du Colombier 
4880ee5cbfSDavid du Colombier static void	radioshow(Radio*);
4980ee5cbfSDavid du Colombier static void	radiofree(Radio*);
5080ee5cbfSDavid du Colombier 
5180ee5cbfSDavid du Colombier static void
radiomouse(Control * c,Mouse * m)52*9a747e4fSDavid du Colombier radiomouse(Control *c, Mouse *m)
5380ee5cbfSDavid du Colombier {
5480ee5cbfSDavid du Colombier 	Radio *r;
55*9a747e4fSDavid du Colombier 	int i;
5680ee5cbfSDavid du Colombier 
57*9a747e4fSDavid du Colombier 	r = (Radio*)c;
5880ee5cbfSDavid du Colombier 	for(i=0; i<r->nbuttons; i++)
59*9a747e4fSDavid du Colombier 		if(ptinrect(m->xy, r->buttons[i]->rect) && r->buttons[i]->mouse){
60*9a747e4fSDavid du Colombier 			(r->buttons[i]->mouse)(r->buttons[i], m);
6180ee5cbfSDavid du Colombier 			break;
6280ee5cbfSDavid du Colombier 		}
6380ee5cbfSDavid du Colombier }
6480ee5cbfSDavid du Colombier 
6580ee5cbfSDavid du Colombier static void
radiofree(Radio *)6680ee5cbfSDavid du Colombier radiofree(Radio*)
6780ee5cbfSDavid du Colombier {
6880ee5cbfSDavid du Colombier }
6980ee5cbfSDavid du Colombier 
7080ee5cbfSDavid du Colombier static void
radioshow(Radio * r)7180ee5cbfSDavid du Colombier radioshow(Radio *r)
7280ee5cbfSDavid du Colombier {
7380ee5cbfSDavid du Colombier 	int i;
7480ee5cbfSDavid du Colombier 
75*9a747e4fSDavid du Colombier 	if (r->hidden)
76*9a747e4fSDavid du Colombier 		return;
77*9a747e4fSDavid du Colombier 	for(i=0; i<r->nbuttons; i++){
78*9a747e4fSDavid du Colombier 		_ctlprint(r->buttons[i], "value %d", (r->value==i));
79*9a747e4fSDavid du Colombier 		_ctlprint(r->buttons[i], "show");
80*9a747e4fSDavid du Colombier 	}
8180ee5cbfSDavid du Colombier }
8280ee5cbfSDavid du Colombier 
8380ee5cbfSDavid du Colombier static void
radioctl(Control * c,CParse * cp)84*9a747e4fSDavid du Colombier radioctl(Control *c, CParse *cp)
8580ee5cbfSDavid du Colombier {
86*9a747e4fSDavid du Colombier 	int cmd, i;
8780ee5cbfSDavid du Colombier 	Rectangle rect;
8880ee5cbfSDavid du Colombier 	Radio *r;
89*9a747e4fSDavid du Colombier 	char fmt[256];
9080ee5cbfSDavid du Colombier 
9180ee5cbfSDavid du Colombier 	r = (Radio*)c;
9280ee5cbfSDavid du Colombier 
93*9a747e4fSDavid du Colombier 	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
9480ee5cbfSDavid du Colombier 	switch(cmd){
9580ee5cbfSDavid du Colombier 	default:
96*9a747e4fSDavid du Colombier 		ctlerror("%q: unrecognized message '%s'", r->name, cp->str);
9780ee5cbfSDavid du Colombier 		break;
9880ee5cbfSDavid du Colombier 	case EAdd:
99*9a747e4fSDavid du Colombier 		_ctlargcount(r, cp, 2);
100*9a747e4fSDavid du Colombier 		c = controlcalled(cp->args[1]);
10180ee5cbfSDavid du Colombier 		if(c == nil)
102*9a747e4fSDavid du Colombier 			ctlerror("%q: can't add %s: %r", r->name, cp->args[1]);
103*9a747e4fSDavid du Colombier 		snprint(fmt, sizeof fmt, "%%q: %q button %%d", r->name);
104*9a747e4fSDavid du Colombier 		_ctlprint(c, "format %q", fmt);
105*9a747e4fSDavid du Colombier 		controlwire(c, "event", c->controlset->ctl);
10680ee5cbfSDavid du Colombier 		r->buttons = ctlrealloc(r->buttons, (r->nbuttons+1)*sizeof(Control*));
10780ee5cbfSDavid du Colombier 		r->buttons[r->nbuttons] = c;
10880ee5cbfSDavid du Colombier 		r->nbuttons++;
10980ee5cbfSDavid du Colombier 		r->value = -1;
11080ee5cbfSDavid du Colombier 		radioshow(r);
11180ee5cbfSDavid du Colombier 		break;
112*9a747e4fSDavid du Colombier 	case EButton:
113*9a747e4fSDavid du Colombier 		if (cp->sender == nil)
114*9a747e4fSDavid du Colombier 			ctlerror("%q: senderless buttonevent: %q", r->name, cp->str);
115*9a747e4fSDavid du Colombier 		c = controlcalled(cp->sender);
116*9a747e4fSDavid du Colombier 		for(i=0; i<r->nbuttons; i++)
117*9a747e4fSDavid du Colombier 			if (c == r->buttons[i])
118*9a747e4fSDavid du Colombier 				break;
119*9a747e4fSDavid du Colombier 		if (i == r->nbuttons)
120*9a747e4fSDavid du Colombier 			ctlerror("%q: not my event: %q", r->name, cp->str);
121*9a747e4fSDavid du Colombier 		if(cp->iargs[1] == 0){
122*9a747e4fSDavid du Colombier 			/* button was turned off; turn it back on */
123*9a747e4fSDavid du Colombier 			_ctlprint(c, "value 1");
124*9a747e4fSDavid du Colombier 		}else{
125*9a747e4fSDavid du Colombier 			r->value = i;
126*9a747e4fSDavid du Colombier 			chanprint(r->event, r->format, r->name, i);
127*9a747e4fSDavid du Colombier 			radioshow(r);
128*9a747e4fSDavid du Colombier 		}
129*9a747e4fSDavid du Colombier 		break;
13080ee5cbfSDavid du Colombier 	case EFormat:
131*9a747e4fSDavid du Colombier 		_ctlargcount(r, cp, 2);
132*9a747e4fSDavid du Colombier 		r->format = ctlstrdup(cp->args[1]);
133*9a747e4fSDavid du Colombier 		break;
134*9a747e4fSDavid du Colombier 	case EHide:
135*9a747e4fSDavid du Colombier 		_ctlargcount(r, cp, 1);
136*9a747e4fSDavid du Colombier 		r->hidden = 1;
13780ee5cbfSDavid du Colombier 		break;
13880ee5cbfSDavid du Colombier 	case EFocus:
13980ee5cbfSDavid du Colombier 		/* ignore focus change */
14080ee5cbfSDavid du Colombier 		break;
14180ee5cbfSDavid du Colombier 	case ERect:
142*9a747e4fSDavid du Colombier 		_ctlargcount(r, cp, 5);
143*9a747e4fSDavid du Colombier 		rect.min.x = cp->iargs[1];
144*9a747e4fSDavid du Colombier 		rect.min.y = cp->iargs[2];
145*9a747e4fSDavid du Colombier 		rect.max.x = cp->iargs[3];
146*9a747e4fSDavid du Colombier 		rect.max.y = cp->iargs[4];
14780ee5cbfSDavid du Colombier 		r->rect = rect;
14880ee5cbfSDavid du Colombier 		break;
149*9a747e4fSDavid du Colombier 	case EReveal:
150*9a747e4fSDavid du Colombier 		_ctlargcount(r, cp, 1);
151*9a747e4fSDavid du Colombier 		r->hidden = 0;
152*9a747e4fSDavid du Colombier 		radioshow(r);
153*9a747e4fSDavid du Colombier 		break;
15480ee5cbfSDavid du Colombier 	case EShow:
155*9a747e4fSDavid du Colombier 		_ctlargcount(r, cp, 1);
15680ee5cbfSDavid du Colombier 		radioshow(r);
15780ee5cbfSDavid du Colombier 		break;
158*9a747e4fSDavid du Colombier 	case ESize:
159*9a747e4fSDavid du Colombier 		if (cp->nargs == 3)
160*9a747e4fSDavid du Colombier 			rect.max = Pt(0x7fffffff, 0x7fffffff);
161*9a747e4fSDavid du Colombier 		else{
162*9a747e4fSDavid du Colombier 			_ctlargcount(r, cp, 5);
163*9a747e4fSDavid du Colombier 			rect.max.x = cp->iargs[3];
164*9a747e4fSDavid du Colombier 			rect.max.y = cp->iargs[4];
165*9a747e4fSDavid du Colombier 		}
166*9a747e4fSDavid du Colombier 		rect.min.x = cp->iargs[1];
167*9a747e4fSDavid du Colombier 		rect.min.y = cp->iargs[2];
168*9a747e4fSDavid du Colombier 		if(rect.min.x<=0 || rect.min.y<=0 || rect.max.x<=0 || rect.max.y<=0 || rect.max.x < rect.min.x || rect.max.y < rect.min.y)
169*9a747e4fSDavid du Colombier 			ctlerror("%q: bad sizes: %s", r->name, cp->str);
170*9a747e4fSDavid du Colombier 		r->size.min = rect.min;
171*9a747e4fSDavid du Colombier 		r->size.max = rect.max;
172*9a747e4fSDavid du Colombier 		break;
17380ee5cbfSDavid du Colombier 	case EValue:
174*9a747e4fSDavid du Colombier 		_ctlargcount(r, cp, 2);
175*9a747e4fSDavid du Colombier 		r->value = cp->iargs[1];
17680ee5cbfSDavid du Colombier 		radioshow(r);
17780ee5cbfSDavid du Colombier 		break;
17880ee5cbfSDavid du Colombier 	}
17980ee5cbfSDavid du Colombier }
18080ee5cbfSDavid du Colombier 
181*9a747e4fSDavid du Colombier Control*
createradiobutton(Controlset * cs,char * name)182*9a747e4fSDavid du Colombier createradiobutton(Controlset *cs, char *name)
18380ee5cbfSDavid du Colombier {
184*9a747e4fSDavid du Colombier 	Radio *r;
18580ee5cbfSDavid du Colombier 
186*9a747e4fSDavid du Colombier 	r = (Radio*)_createctl(cs, "label", sizeof(Radio), name);
187*9a747e4fSDavid du Colombier 	r->format = ctlstrdup("%q: value %d");
188*9a747e4fSDavid du Colombier 	r->value = -1;	/* nobody set at first */
189*9a747e4fSDavid du Colombier 	r->mouse = radiomouse;
190*9a747e4fSDavid du Colombier 	r->ctl = radioctl;
191*9a747e4fSDavid du Colombier 	return (Control*)r;
19280ee5cbfSDavid du Colombier }
193