ref: c5c19dfe4998fa40de5f58f61439fd5fd65c9056
dir: /sys/src/cmd/mothra/libpanel/button.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <event.h> #include <panel.h> #include "pldefs.h" typedef struct Button Button; struct Button{ int btype; /* button type */ Icon *icon; /* what to write on the button */ int check; /* for check/radio buttons */ void (*hit)(Panel *, int, int); /* call back user code on check/radio hit */ void (*menuhit)(int, int); /* call back user code on menu item hit */ void (*pl_buttonhit)(Panel *, int); /* call back user code on button hit */ int index; /* arg to menuhit */ int buttons; }; /* * Button types */ #define BUTTON 1 #define CHECK 2 #define RADIO 3 #define MENU 4 void pl_drawbutton(Panel *p){ Rectangle r; Button *bp; bp=p->data; switch(bp->btype){ case MENU: r=pl_box(p->b, p->r, p->state); break; case BUTTON: r=pl_box(p->b, p->r, p->state|BORDER); break; case CHECK: r=pl_box(p->b, p->r, p->state|BORDER); r=pl_check(p->b, r, bp->check); break; case RADIO: r=pl_box(p->b, p->r, p->state|BORDER); r=pl_radio(p->b, r, bp->check); break; } pl_drawicon(p->b, r, PLACECEN, p->flags, bp->icon); } int pl_hitbutton(Panel *p, Mouse *m){ int oldstate, hitme; Panel *sib; Button *bp; bp=p->data; oldstate=p->state; if(m->buttons&OUT){ hitme=0; p->state=UP; } else if(m->buttons&7){ hitme=0; p->state=DOWN; bp->buttons=m->buttons; } else{ /* mouse inside, but no buttons down */ hitme=p->state==DOWN; p->state=UP; } if(hitme) switch(bp->btype){ case CHECK: if(hitme) bp->check=!bp->check; break; case RADIO: if(bp->check) bp->check=0; else{ if(p->parent){ for(sib=p->parent->child;sib;sib=sib->next){ if(sib->hit==pl_hitbutton && ((Button *)sib->data)->btype==RADIO && ((Button *)sib->data)->check){ ((Button *)sib->data)->check=0; pldraw(sib, p->b); } } } bp->check=1; } break; } if(hitme || oldstate!=p->state) pldraw(p, p->b); if(hitme && bp->hit){ bp->hit(p, bp->buttons, bp->check); p->state=UP; } return 0; } void pl_typebutton(Panel *g, Rune c){ USED(g, c); } Point pl_getsizebutton(Panel *p, Point children){ Point s; int ckw; Button *bp; USED(children); /* shouldn't have any children */ bp=p->data; s=pl_iconsize(p->flags, bp->icon); if(bp->btype!=BUTTON && bp->btype!=MENU){ ckw=pl_ckwid(); if(s.y<ckw){ s.x+=ckw; s.y=ckw; } else s.x+=s.y; } return pl_boxsize(s, p->state); } void pl_childspacebutton(Panel *g, Point *ul, Point *size){ USED(g, ul, size); } void pl_initbtype(Panel *v, int flags, Icon *icon, void (*hit)(Panel *, int, int), int btype){ Button *bp; bp=v->data; v->flags=flags|LEAF; v->state=UP; v->draw=pl_drawbutton; v->hit=pl_hitbutton; v->type=pl_typebutton; v->getsize=pl_getsizebutton; v->childspace=pl_childspacebutton; bp->btype=btype; bp->check=0; bp->hit=hit; bp->icon=icon; switch(btype){ case MENU: v->kind="button"; break; case BUTTON: v->kind="button"; break; case CHECK: v->kind="checkbutton"; break; case RADIO: v->kind="radiobutton"; break; } } void pl_buttonhit(Panel *p, int buttons, int check){ USED(check); if(((Button *)p->data)->pl_buttonhit) ((Button *)p->data)->pl_buttonhit(p, buttons); } void plinitbutton(Panel *p, int flags, Icon *icon, void (*hit)(Panel *, int)){ ((Button *)p->data)->pl_buttonhit=hit; pl_initbtype(p, flags, icon, pl_buttonhit, BUTTON); } void plinitcheckbutton(Panel *p, int flags, Icon *icon, void (*hit)(Panel *, int, int)){ pl_initbtype(p, flags, icon, hit, CHECK); } void plinitradiobutton(Panel *p, int flags, Icon *icon, void (*hit)(Panel *, int, int)){ pl_initbtype(p, flags, icon, hit, RADIO); } Panel *pl_menubutton(Panel *parent, int flags, Icon *icon, void (*hit)(Panel *, int)){ Panel *p; p=pl_newpanel(parent, sizeof(Button)); ((Button *)p->data)->pl_buttonhit=hit; pl_initbtype(p, flags, icon, pl_buttonhit, MENU); return p; } Panel *plbutton(Panel *parent, int flags, Icon *icon, void (*hit)(Panel *, int)){ Panel *p; p=pl_newpanel(parent, sizeof(Button)); plinitbutton(p, flags, icon, hit); return p; } Panel *plcheckbutton(Panel *parent, int flags, Icon *icon, void (*hit)(Panel *, int, int)){ Panel *p; p=pl_newpanel(parent, sizeof(Button)); plinitcheckbutton(p, flags, icon, hit); return p; } Panel *plradiobutton(Panel *parent, int flags, Icon *icon, void (*hit)(Panel *, int, int)){ Panel *p; p=pl_newpanel(parent, sizeof(Button)); plinitradiobutton(p, flags, icon, hit); return p; } void pl_hitmenu(Panel *p, int buttons){ void (*hit)(int, int); hit=((Button *)p->data)->menuhit; if(hit) hit(buttons, ((Button *)p->data)->index); } void plinitmenu(Panel *v, int flags, Icon **item, int cflags, void (*hit)(int, int)){ Panel *b; int i; v->flags=flags; v->kind="menu"; if(v->child){ plfree(v->child); v->child=0; } for(i=0;item[i];i++){ b=pl_menubutton(v, cflags, item[i], pl_hitmenu); ((Button *)b->data)->menuhit=hit; ((Button *)b->data)->index=i; } } Panel *plmenu(Panel *parent, int flags, Icon **item, int cflags, void (*hit)(int, int)){ Panel *v; v=plgroup(parent, flags); plinitmenu(v, flags, item, cflags, hit); return v; } void plsetbutton(Panel *p, int val){ ((Button *)p->data)->check=val; }