196 lines
4.0 KiB
C
196 lines
4.0 KiB
C
/*
|
|
* This file is part of the UCB release of Plan 9. It is subject to the license
|
|
* terms in the LICENSE file found in the top-level directory of this
|
|
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
|
|
* part of the UCB release of Plan 9, including this file, may be copied,
|
|
* modified, propagated, or distributed except according to the terms contained
|
|
* in the LICENSE file.
|
|
*/
|
|
|
|
#include <u.h>
|
|
#include <lib9.h>
|
|
#include <draw.h>
|
|
#include <thread.h>
|
|
#include <mouse.h>
|
|
#include <keyboard.h>
|
|
#include <control.h>
|
|
|
|
typedef struct Radio Radio;
|
|
|
|
struct Radio
|
|
{
|
|
Control;
|
|
int value;
|
|
int lastbut;
|
|
Control **buttons;
|
|
int nbuttons;
|
|
char *eventstr;
|
|
};
|
|
|
|
enum{
|
|
EAdd,
|
|
EButton,
|
|
EFocus,
|
|
EFormat,
|
|
EHide,
|
|
ERect,
|
|
EReveal,
|
|
EShow,
|
|
ESize,
|
|
EValue,
|
|
};
|
|
|
|
static char *cmds[] = {
|
|
[EAdd] = "add",
|
|
[EButton] = "button",
|
|
[EFocus] = "focus",
|
|
[EFormat] = "format",
|
|
[EHide] = "hide",
|
|
[ERect] = "rect",
|
|
[EReveal] = "reveal",
|
|
[EShow] = "show",
|
|
[ESize] = "size",
|
|
[EValue] = "value",
|
|
nil
|
|
};
|
|
|
|
static void radioshow(Radio*);
|
|
|
|
static void
|
|
radiomouse(Control *c, Mouse *m)
|
|
{
|
|
Radio *r;
|
|
int i;
|
|
|
|
r = (Radio*)c;
|
|
for(i=0; i<r->nbuttons; i++)
|
|
if(ptinrect(m->xy, r->buttons[i]->rect) && r->buttons[i]->mouse){
|
|
(r->buttons[i]->mouse)(r->buttons[i], m);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
radioshow(Radio *r)
|
|
{
|
|
int i;
|
|
|
|
if (r->hidden)
|
|
return;
|
|
for(i=0; i<r->nbuttons; i++){
|
|
_ctlprint(r->buttons[i], "value %d", (r->value==i));
|
|
_ctlprint(r->buttons[i], "show");
|
|
}
|
|
}
|
|
|
|
static void
|
|
radioctl(Control *c, CParse *cp)
|
|
{
|
|
int cmd, i;
|
|
Rectangle rect;
|
|
Radio *r;
|
|
char fmt[256];
|
|
|
|
r = (Radio*)c;
|
|
|
|
cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
|
|
switch(cmd){
|
|
default:
|
|
ctlerror("%q: unrecognized message '%s'", r->name, cp->str);
|
|
break;
|
|
case EAdd:
|
|
_ctlargcount(r, cp, 2);
|
|
c = controlcalled(cp->args[1]);
|
|
if(c == nil)
|
|
ctlerror("%q: can't add %s: %r", r->name, cp->args[1]);
|
|
snprint(fmt, sizeof fmt, "%%q: %q button %%d", r->name);
|
|
_ctlprint(c, "format %q", fmt);
|
|
controlwire(c, "event", c->controlset->ctl);
|
|
r->buttons = ctlrealloc(r->buttons, (r->nbuttons+1)*sizeof(Control*));
|
|
r->buttons[r->nbuttons] = c;
|
|
r->nbuttons++;
|
|
r->value = -1;
|
|
radioshow(r);
|
|
break;
|
|
case EButton:
|
|
if (cp->sender == nil)
|
|
ctlerror("%q: senderless buttonevent: %q", r->name, cp->str);
|
|
c = controlcalled(cp->sender);
|
|
for(i=0; i<r->nbuttons; i++)
|
|
if (c == r->buttons[i])
|
|
break;
|
|
if (i == r->nbuttons)
|
|
ctlerror("%q: not my event: %q", r->name, cp->str);
|
|
if(cp->iargs[1] == 0){
|
|
/* button was turned off; turn it back on */
|
|
_ctlprint(c, "value 1");
|
|
}else{
|
|
r->value = i;
|
|
chanprint(r->event, r->format, r->name, i);
|
|
radioshow(r);
|
|
}
|
|
break;
|
|
case EFormat:
|
|
_ctlargcount(r, cp, 2);
|
|
r->format = ctlstrdup(cp->args[1]);
|
|
break;
|
|
case EHide:
|
|
_ctlargcount(r, cp, 1);
|
|
r->hidden = 1;
|
|
break;
|
|
case EFocus:
|
|
/* ignore focus change */
|
|
break;
|
|
case ERect:
|
|
_ctlargcount(r, cp, 5);
|
|
rect.min.x = cp->iargs[1];
|
|
rect.min.y = cp->iargs[2];
|
|
rect.max.x = cp->iargs[3];
|
|
rect.max.y = cp->iargs[4];
|
|
r->rect = rect;
|
|
break;
|
|
case EReveal:
|
|
_ctlargcount(r, cp, 1);
|
|
r->hidden = 0;
|
|
radioshow(r);
|
|
break;
|
|
case EShow:
|
|
_ctlargcount(r, cp, 1);
|
|
radioshow(r);
|
|
break;
|
|
case ESize:
|
|
if (cp->nargs == 3)
|
|
rect.max = Pt(0x7fffffff, 0x7fffffff);
|
|
else{
|
|
_ctlargcount(r, cp, 5);
|
|
rect.max.x = cp->iargs[3];
|
|
rect.max.y = cp->iargs[4];
|
|
}
|
|
rect.min.x = cp->iargs[1];
|
|
rect.min.y = cp->iargs[2];
|
|
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)
|
|
ctlerror("%q: bad sizes: %s", r->name, cp->str);
|
|
r->size.min = rect.min;
|
|
r->size.max = rect.max;
|
|
break;
|
|
case EValue:
|
|
_ctlargcount(r, cp, 2);
|
|
r->value = cp->iargs[1];
|
|
radioshow(r);
|
|
break;
|
|
}
|
|
}
|
|
|
|
Control*
|
|
createradiobutton(Controlset *cs, char *name)
|
|
{
|
|
Radio *r;
|
|
|
|
r = (Radio*)_createctl(cs, "label", sizeof(Radio), name);
|
|
r->format = ctlstrdup("%q: value %d");
|
|
r->value = -1; /* nobody set at first */
|
|
r->mouse = radiomouse;
|
|
r->ctl = radioctl;
|
|
return (Control*)r;
|
|
}
|