telephil9initial importc9c50ad6 years agoHistory
160 lines · 3.6 KB · C
RawDownload
/* * pulldown *	makes a button that pops up a panel when hit */#include <u.h>#include <libc.h>#include <draw.h>#include <event.h>#include <panel.h>#include "pldefs.h"typedef struct Pulldown Pulldown;struct Pulldown{	Icon *icon;		/* button label */	Panel *pull;		/* Panel to pull down */	int side;		/* which side of the button to put the panel on */	Image *save;		/* where to save what we draw the panel on */};void pl_drawpulldown(Panel *p){	pl_drawicon(p->b, pl_box(p->b, p->r, p->state), PLACECEN,		p->flags, ((Pulldown *)p->data)->icon);}int pl_hitpulldown(Panel *g, Mouse *m){	int oldstate, passon;	Rectangle r;	Panel *p, *hitme;	Pulldown *pp;	pp=g->data;	oldstate=g->state;	p=pp->pull;	hitme=0;	switch(g->state){	case UP:		if(!ptinrect(m->xy, g->r))			g->state=UP;		else if(m->buttons&7){			r=g->b->r;			p->flags&=~PLACE;			switch(pp->side){			case PACKN:				r.min.x=g->r.min.x;				r.max.y=g->r.min.y;				p->flags|=PLACESW;				break;			case PACKS:				r.min.x=g->r.min.x;				r.min.y=g->r.max.y;				p->flags|=PLACENW;				break;			case PACKE:				r.min.x=g->r.max.x;				r.min.y=g->r.min.y;				p->flags|=PLACENW;				break;			case PACKW:				r.max.x=g->r.min.x;				r.min.y=g->r.min.y;				p->flags|=PLACENE;				break;			case PACKCEN:				r.min=g->r.min;				p->flags|=PLACENW;				break;			}			plpack(p, r);			pp->save=allocimage(display, p->r, g->b->chan, 0, DNofill);			if(pp->save!=0) draw(pp->save, p->r, g->b, 0, p->r.min);			pl_invis(p, 0);			pldraw(p, g->b);			g->state=DOWN;		}		break;	case DOWN:		if(!ptinrect(m->xy, g->r)){			switch(pp->side){			default: SET(passon); break;		/* doesn't happen */			case PACKN: passon=m->xy.y<g->r.min.y; break;			case PACKS: passon=m->xy.y>=g->r.max.y; break;			case PACKE: passon=m->xy.x>=g->r.max.x; break;			case PACKW: passon=m->xy.x<g->r.min.x; break;			case PACKCEN: passon=1; break;			}			if(passon){				hitme=p;				if((m->buttons&7)==0) g->state=UP;			}			else	g->state=UP;		}		else if((m->buttons&7)==0) g->state=UP;		else hitme=p;		if(g->state!=DOWN && pp->save){			draw(g->b, p->r, pp->save, 0, p->r.min);			freeimage(pp->save);			pp->save=0;			pl_invis(p, 1);			hitme=p;		}	}	if(g->state!=oldstate) pldraw(g, g->b);	if(hitme) plmouse(hitme, m);	return g->state==DOWN;}void pl_typepulldown(Panel *p, Rune c){	USED(p, c);}Point pl_getsizepulldown(Panel *p, Point children){	USED(p, children);	return pl_boxsize(pl_iconsize(p->flags, ((Pulldown *)p->data)->icon), p->state);}void pl_childspacepulldown(Panel *p, Point *ul, Point *size){	USED(p, ul, size);}void plinitpulldown(Panel *v, int flags, Icon *icon, Panel *pullthis, int side){	Pulldown *pp;	pp=v->data;	v->flags=flags|LEAF;	v->draw=pl_drawpulldown;	v->hit=pl_hitpulldown;	v->type=pl_typepulldown;	v->getsize=pl_getsizepulldown;	v->childspace=pl_childspacepulldown;	pp->pull=pullthis;	pp->side=side;	pp->icon=icon;	v->kind="pulldown";}Panel *plpulldown(Panel *parent, int flags, Icon *icon, Panel *pullthis, int side){	Panel *v;	v=pl_newpanel(parent, sizeof(Pulldown));	v->state=UP;	((Pulldown *)v->data)->save=0;	plinitpulldown(v, flags, icon, pullthis, side);	return v;}Panel *plmenubar(Panel *parent, int flags, int cflags, Icon *l1, Panel *m1, Icon *l2, ...){	Panel *v;	va_list arg;	Icon *s;	int pulldir;	switch(cflags&PACK){	default:		SET(pulldir);		break;	case PACKE:	case PACKW:		pulldir=PACKS;		break;	case PACKN:	case PACKS:		pulldir=PACKE;		break;	}	v=plgroup(parent, flags);	va_start(arg, cflags);	while((s=va_arg(arg, Icon *))!=0)		plpulldown(v, cflags, s, va_arg(arg, Panel *), pulldir);	va_end(arg);	USED(l1, m1, l2);	v->kind="menubar";	return v;}