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 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 66 radiofree(Radio*) 67 { 68 } 69 70 static void 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 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* 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