161 lines
3.6 KiB
C
161 lines
3.6 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|