]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mothra/libpanel/pack.c
mothra: fix alt display resizing, filter control characters in panel entries, use...
[plan9front.git] / sys / src / cmd / mothra / libpanel / pack.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <event.h>
5 #include <panel.h>
6 #include "pldefs.h"
7 int pl_max(int a, int b){
8         return a>b?a:b;
9 }
10 Point pl_sizesibs(Panel *p){
11         Point s;
12         if(p==0) return Pt(0,0);
13         s=pl_sizesibs(p->next);
14         switch(p->flags&PACK){
15         case PACKN:
16         case PACKS:
17                 s.x=pl_max(s.x, p->sizereq.x);
18                 s.y+=p->sizereq.y;
19                 break;
20         case PACKE:
21         case PACKW:
22                 s.x+=p->sizereq.x;
23                 s.y=pl_max(s.y, p->sizereq.y);
24                 break;
25         }
26         return s;
27 }
28 /*
29  * Compute the requested size of p and its descendants.
30  */
31 void pl_sizereq(Panel *p){
32         Panel *cp;
33         Point maxsize;
34         maxsize=Pt(0,0);
35         for(cp=p->child;cp;cp=cp->next){
36                 pl_sizereq(cp);
37                 if(cp->sizereq.x>maxsize.x) maxsize.x=cp->sizereq.x;
38                 if(cp->sizereq.y>maxsize.y) maxsize.y=cp->sizereq.y;
39         }
40         for(cp=p->child;cp;cp=cp->next){
41                 if(cp->flags&MAXX) cp->sizereq.x=maxsize.x;
42                 if(cp->flags&MAXY) cp->sizereq.y=maxsize.y;
43         }
44         p->childreq=pl_sizesibs(p->child);
45         p->sizereq=addpt(addpt(p->getsize(p, p->childreq), p->ipad), p->pad);
46         if(p->flags&FIXEDX) p->sizereq.x=p->fixedsize.x;
47         if(p->flags&FIXEDY) p->sizereq.y=p->fixedsize.y;
48 }
49 Point pl_getshare(Panel *p){
50         Point share;
51         if(p==0) return Pt(0,0);
52         share=pl_getshare(p->next);
53         if(p->flags&EXPAND) switch(p->flags&PACK){
54         case PACKN:
55         case PACKS:
56                 if(share.x==0) share.x=1;
57                 share.y++;
58                 break;
59         case PACKE:
60         case PACKW:
61                 share.x++;
62                 if(share.y==0) share.y=1;
63                 break;
64         }
65         return share;
66 }
67 /*
68  * Set the sizes and rectangles of p and its descendants, given their requested sizes.
69  * Returns 1 if everything fit, 0 otherwise.
70  * For now we punt in the case that the children don't all fit.
71  * Possibly we should shrink all the children's sizereqs to fit,
72  * by the same means used to do EXPAND, except clamping at some minimum size,
73  * but that smacks of AI.
74  */
75 Panel *pl_toosmall;
76 int pl_setrect(Panel *p, Point ul, Point avail){
77         Point space, newul, newspace, slack, share;
78         int l;
79         Panel *c;
80         p->size=subpt(p->sizereq, p->pad);
81         ul=addpt(ul, divpt(p->pad, 2));
82         avail=subpt(avail, p->pad);
83         if(p->size.x>avail.x || p->size.y>avail.y){
84                 pl_toosmall=p;
85                 return 0;       /* not enough space! */
86         }
87         if(p->flags&(FILLX|EXPAND)) p->size.x=avail.x;
88         if(p->flags&(FILLY|EXPAND)) p->size.y=avail.y;
89         switch(p->flags&PLACE){
90         case PLACECEN:  ul.x+=(avail.x-p->size.x)/2; ul.y+=(avail.y-p->size.y)/2; break;
91         case PLACES:    ul.x+=(avail.x-p->size.x)/2; ul.y+= avail.y-p->size.y   ; break;
92         case PLACEE:    ul.x+= avail.x-p->size.x   ; ul.y+=(avail.y-p->size.y)/2; break;
93         case PLACEW:                                 ul.y+=(avail.y-p->size.y)/2; break;
94         case PLACEN:    ul.x+=(avail.x-p->size.x)/2;                              break;
95         case PLACENE:   ul.x+= avail.x-p->size.x   ;                              break;
96         case PLACENW:                                                             break;
97         case PLACESE:   ul.x+= avail.x-p->size.x   ; ul.y+= avail.y-p->size.y   ; break;
98         case PLACESW:                                ul.y+= avail.y-p->size.y   ; break;
99         }
100         p->r=Rpt(ul, addpt(ul, p->size));
101         space=p->size;
102         p->childspace(p, &ul, &space);
103         slack=subpt(space, p->childreq);
104         share=pl_getshare(p->child);
105         for(c=p->child;c;c=c->next){
106                 if(c->flags&EXPAND){
107                         switch(c->flags&PACK){
108                         case PACKN:
109                         case PACKS:
110                                 c->sizereq.x+=slack.x;
111                                 l=slack.y/share.y;
112                                 c->sizereq.y+=l;
113                                 slack.y-=l;
114                                 --share.y;
115                                 break;
116                         case PACKE:
117                         case PACKW:
118                                 l=slack.x/share.x;
119                                 c->sizereq.x+=l;
120                                 slack.x-=l;
121                                 --share.x;
122                                 c->sizereq.y+=slack.y;
123                                 break;
124                         }
125                 }
126                 switch(c->flags&PACK){
127                 case PACKN:
128                         newul=Pt(ul.x, ul.y+c->sizereq.y);
129                         newspace=Pt(space.x, space.y-c->sizereq.y);
130                         if(!pl_setrect(c, ul, Pt(space.x, c->sizereq.y))) return 0;
131                         break;
132                 case PACKW:
133                         newul=Pt(ul.x+c->sizereq.x, ul.y);
134                         newspace=Pt(space.x-c->sizereq.x, space.y);
135                         if(!pl_setrect(c, ul, Pt(c->sizereq.x, space.y))) return 0;
136                         break;
137                 case PACKS:
138                         newul=ul;
139                         newspace=Pt(space.x, space.y-c->sizereq.y);
140                         if(!pl_setrect(c, Pt(ul.x, ul.y+space.y-c->sizereq.y),
141                                 Pt(space.x, c->sizereq.y))) return 0;
142                         break;
143                 case PACKE:
144                         newul=ul;
145                         newspace=Pt(space.x-c->sizereq.x, space.y);
146                         if(!pl_setrect(c, Pt(ul.x+space.x-c->sizereq.x, ul.y),
147                                 Pt(c->sizereq.x, space.y))) return 0;
148                         break;
149                 }
150                 ul=newul;
151                 space=newspace;
152         }
153         return 1;
154 }
155 int plpack(Panel *p, Rectangle where){
156         pl_sizereq(p);
157         return pl_setrect(p, where.min, subpt(where.max, where.min));
158 }
159 /*
160  * move an already-packed panel so that p->r=raddp(p->r, d)
161  */
162 void plmove(Panel *p, Point d){
163         if(strcmp(p->kind, "edit") == 0)        /* sorry */
164                 plemove(p, d);
165         p->r=rectaddpt(p->r, d);
166         for(p=p->child;p;p=p->next) plmove(p, d);
167 }