xref: /plan9/sys/src/libcontrol/radiobutton.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <keyboard.h>
7 #include <control.h>
8 
9 typedef struct Radio Radio;
10 
11 struct Radio
12 {
13 	Control;
14 	int		value;
15 	int		lastbut;
16 	Control	**buttons;
17 	int		nbuttons;
18 	char		*eventstr;
19 };
20 
21 enum{
22 	EAdd,
23 	EButton,
24 	EFocus,
25 	EFormat,
26 	EHide,
27 	ERect,
28 	EReveal,
29 	EShow,
30 	ESize,
31 	EValue,
32 };
33 
34 static char *cmds[] = {
35 	[EAdd] =		"add",
36 	[EButton] =	"button",
37 	[EFocus] = 	"focus",
38 	[EFormat] = 	"format",
39 	[EHide] =		"hide",
40 	[ERect] =		"rect",
41 	[EReveal] =	"reveal",
42 	[EShow] =		"show",
43 	[ESize] =		"size",
44 	[EValue] =		"value",
45 	nil
46 };
47 
48 static void	radioshow(Radio*);
49 static void	radiofree(Radio*);
50 
51 static void
radiomouse(Control * c,Mouse * m)52 radiomouse(Control *c, Mouse *m)
53 {
54 	Radio *r;
55 	int i;
56 
57 	r = (Radio*)c;
58 	for(i=0; i<r->nbuttons; i++)
59 		if(ptinrect(m->xy, r->buttons[i]->rect) && r->buttons[i]->mouse){
60 			(r->buttons[i]->mouse)(r->buttons[i], m);
61 			break;
62 		}
63 }
64 
65 static void
radiofree(Radio *)66 radiofree(Radio*)
67 {
68 }
69 
70 static void
radioshow(Radio * r)71 radioshow(Radio *r)
72 {
73 	int i;
74 
75 	if (r->hidden)
76 		return;
77 	for(i=0; i<r->nbuttons; i++){
78 		_ctlprint(r->buttons[i], "value %d", (r->value==i));
79 		_ctlprint(r->buttons[i], "show");
80 	}
81 }
82 
83 static void
radioctl(Control * c,CParse * cp)84 radioctl(Control *c, CParse *cp)
85 {
86 	int cmd, i;
87 	Rectangle rect;
88 	Radio *r;
89 	char fmt[256];
90 
91 	r = (Radio*)c;
92 
93 	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
94 	switch(cmd){
95 	default:
96 		ctlerror("%q: unrecognized message '%s'", r->name, cp->str);
97 		break;
98 	case EAdd:
99 		_ctlargcount(r, cp, 2);
100 		c = controlcalled(cp->args[1]);
101 		if(c == nil)
102 			ctlerror("%q: can't add %s: %r", r->name, cp->args[1]);
103 		snprint(fmt, sizeof fmt, "%%q: %q button %%d", r->name);
104 		_ctlprint(c, "format %q", fmt);
105 		controlwire(c, "event", c->controlset->ctl);
106 		r->buttons = ctlrealloc(r->buttons, (r->nbuttons+1)*sizeof(Control*));
107 		r->buttons[r->nbuttons] = c;
108 		r->nbuttons++;
109 		r->value = -1;
110 		radioshow(r);
111 		break;
112 	case EButton:
113 		if (cp->sender == nil)
114 			ctlerror("%q: senderless buttonevent: %q", r->name, cp->str);
115 		c = controlcalled(cp->sender);
116 		for(i=0; i<r->nbuttons; i++)
117 			if (c == r->buttons[i])
118 				break;
119 		if (i == r->nbuttons)
120 			ctlerror("%q: not my event: %q", r->name, cp->str);
121 		if(cp->iargs[1] == 0){
122 			/* button was turned off; turn it back on */
123 			_ctlprint(c, "value 1");
124 		}else{
125 			r->value = i;
126 			chanprint(r->event, r->format, r->name, i);
127 			radioshow(r);
128 		}
129 		break;
130 	case EFormat:
131 		_ctlargcount(r, cp, 2);
132 		r->format = ctlstrdup(cp->args[1]);
133 		break;
134 	case EHide:
135 		_ctlargcount(r, cp, 1);
136 		r->hidden = 1;
137 		break;
138 	case EFocus:
139 		/* ignore focus change */
140 		break;
141 	case ERect:
142 		_ctlargcount(r, cp, 5);
143 		rect.min.x = cp->iargs[1];
144 		rect.min.y = cp->iargs[2];
145 		rect.max.x = cp->iargs[3];
146 		rect.max.y = cp->iargs[4];
147 		r->rect = rect;
148 		break;
149 	case EReveal:
150 		_ctlargcount(r, cp, 1);
151 		r->hidden = 0;
152 		radioshow(r);
153 		break;
154 	case EShow:
155 		_ctlargcount(r, cp, 1);
156 		radioshow(r);
157 		break;
158 	case ESize:
159 		if (cp->nargs == 3)
160 			rect.max = Pt(0x7fffffff, 0x7fffffff);
161 		else{
162 			_ctlargcount(r, cp, 5);
163 			rect.max.x = cp->iargs[3];
164 			rect.max.y = cp->iargs[4];
165 		}
166 		rect.min.x = cp->iargs[1];
167 		rect.min.y = cp->iargs[2];
168 		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 			ctlerror("%q: bad sizes: %s", r->name, cp->str);
170 		r->size.min = rect.min;
171 		r->size.max = rect.max;
172 		break;
173 	case EValue:
174 		_ctlargcount(r, cp, 2);
175 		r->value = cp->iargs[1];
176 		radioshow(r);
177 		break;
178 	}
179 }
180 
181 Control*
createradiobutton(Controlset * cs,char * name)182 createradiobutton(Controlset *cs, char *name)
183 {
184 	Radio *r;
185 
186 	r = (Radio*)_createctl(cs, "label", sizeof(Radio), name);
187 	r->format = ctlstrdup("%q: value %d");
188 	r->value = -1;	/* nobody set at first */
189 	r->mouse = radiomouse;
190 	r->ctl = radioctl;
191 	return (Control*)r;
192 }
193