189 lines · 4.6 KB · C
RawDownload
#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	3void pl_drawbutton(Panel *p){	Rectangle r;	Button *bp;	bp=p->data;	r=pl_boxf(p->b, p->r, p->flags, p->state);	switch(bp->btype){	case CHECK:		r=pl_check(p->b, r, bp->check);		break;	case RADIO:		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){		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 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 *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=plbutton(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;}