]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mothra/libpanel/popup.c
mothra: snarf and paste
[plan9front.git] / sys / src / cmd / mothra / libpanel / popup.c
1 /*
2  * popup
3  *      looks like a group, except diverts hits on certain buttons to
4  *      panels that it temporarily pops up.
5  */
6 #include <u.h>
7 #include <libc.h>
8 #include <draw.h>
9 #include <event.h>
10 #include <panel.h>
11 #include "pldefs.h"
12 typedef struct Popup Popup;
13 struct Popup{
14         Image *save;                    /* where to save what the popup covers */
15         Panel *pop[3];                  /* what to pop up */
16 };
17 void pl_drawpopup(Panel *p){
18         USED(p);
19 }
20 int pl_hitpopup(Panel *g, Mouse *m){
21         Panel *p;
22         Point d;
23         Popup *pp;
24
25         pp=g->data;
26         if(g->state==UP){
27                 switch(m->buttons&7){
28                 case 0: p=g->child; break;
29                 case 1: p=pp->pop[0]; g->state=DOWN1; break;
30                 case 2: p=pp->pop[1]; g->state=DOWN2; break;
31                 case 4: p=pp->pop[2]; g->state=DOWN3; break;
32                 default: p=0; break;
33                 }
34                 if(p==0){
35                         p=g->child;
36                         g->state=DOWN;
37                 }
38                 else if(g->state!=UP){
39                         plpack(p, screen->clipr);
40                         if(p->lastmouse)
41                                 d=subpt(m->xy, divpt(addpt(p->lastmouse->r.min,
42                                                      p->lastmouse->r.max), 2));
43                         else
44                                 d=subpt(m->xy, divpt(addpt(p->r.min, p->r.max), 2));
45                         if(p->r.min.x+d.x<g->r.min.x) d.x=g->r.min.x-p->r.min.x;
46                         if(p->r.max.x+d.x>g->r.max.x) d.x=g->r.max.x-p->r.max.x;
47                         if(p->r.min.y+d.y<g->r.min.y) d.y=g->r.min.y-p->r.min.y;
48                         if(p->r.max.y+d.y>g->r.max.y) d.y=g->r.max.y-p->r.max.y;
49                         plmove(p, d);
50                         pp->save=allocimage(display, p->r, g->b->chan, 0, DNofill);
51                         if(pp->save!=0) draw(pp->save, p->r, g->b, 0, p->r.min);
52                         pl_invis(p, 0);
53                         pldraw(p, g->b);
54                 }
55         }
56         else{
57                 switch(g->state){
58                 default: SET(p); break;                 /* can't happen! */
59                 case DOWN1: p=pp->pop[0]; break;
60                 case DOWN2: p=pp->pop[1]; break;
61                 case DOWN3: p=pp->pop[2]; break;
62                 case DOWN:  p=g->child;  break;
63                 }
64                 if((m->buttons&7)==0){
65                         if(g->state!=DOWN){
66                                 if(pp->save!=0){
67                                         draw(g->b, p->r, pp->save, 0, p->r.min);
68                                         flushimage(display, 1);
69                                         freeimage(pp->save);
70                                         pp->save=0;
71                                 }
72                                 pl_invis(p, 1);
73                         }
74                         g->state=UP;
75                 }
76         }
77         plmouse(p, m);
78         if((m->buttons&7)==0)
79                 g->state=UP;
80         return (m->buttons&7)!=0;
81 }
82 void pl_typepopup(Panel *g, Rune c){
83         USED(g, c);
84 }
85 Point pl_getsizepopup(Panel *g, Point children){
86         USED(g);
87         return children;
88 }
89 void pl_childspacepopup(Panel *g, Point *ul, Point *size){
90         USED(g, ul, size);
91 }
92 int pl_pripopup(Panel *, Point){
93         return PRI_POPUP;
94 }
95 void plinitpopup(Panel *v, int flags, Panel *pop0, Panel *pop1, Panel *pop2){
96         Popup *pp;
97         pp=v->data;
98         v->flags=flags;
99         v->pri=pl_pripopup;
100         v->state=UP;
101         v->draw=pl_drawpopup;
102         v->hit=pl_hitpopup;
103         v->type=pl_typepopup;
104         v->getsize=pl_getsizepopup;
105         v->childspace=pl_childspacepopup;
106         pp->pop[0]=pop0;
107         pp->pop[1]=pop1;
108         pp->pop[2]=pop2;
109         pp->save=0;
110         v->kind="popup";
111 }
112 Panel *plpopup(Panel *parent, int flags, Panel *pop0, Panel *pop1, Panel *pop2){
113         Panel *v;
114         v=pl_newpanel(parent, sizeof(Popup));
115         plinitpopup(v, flags, pop0, pop1, pop2);
116         return v;
117 }