]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mothra/libpanel/draw.c
mothra: snarf and paste
[plan9front.git] / sys / src / cmd / mothra / libpanel / draw.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 #define PWID    1       /* width of label border */
8 #define BWID    1       /* width of button relief */
9 #define FWID    2       /* width of frame relief */
10 #define SPACE   1       /* space inside relief of button or frame */
11 #define CKSIZE  3       /* size of check mark */
12 #define CKSPACE 2       /* space around check mark */
13 #define CKWID   1       /* width of frame around check mark */
14 #define CKINSET 1       /* space around check mark frame */
15 #define CKBORDER 2      /* space around X inside frame */
16 static int plldepth;
17 static Image *pl_white, *pl_light, *pl_dark, *pl_black, *pl_hilit;
18 int pl_drawinit(int ldepth){
19         plldepth=ldepth;
20         pl_white=allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xFFFFFFFF);
21         pl_light=allocimagemix(display, DPalebluegreen, DWhite);
22         pl_dark =allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue);
23         pl_black=allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000FF);
24         pl_hilit=allocimage(display, Rect(0,0,1,1), CHAN1(CAlpha,8), 1, 0x80);
25         if(pl_white==0 || pl_light==0 || pl_black==0 || pl_dark==0) return 0;
26         return 1;
27 }
28 void pl_relief(Image *b, Image *ul, Image *lr, Rectangle r, int wid){
29         int x, y;
30         draw(b, Rect(r.min.x, r.max.y-wid, r.max.x, r.max.y), lr, 0, ZP); /* bottom */
31         draw(b, Rect(r.max.x-wid, r.min.y, r.max.x, r.max.y), lr, 0, ZP); /* right */
32         draw(b, Rect(r.min.x, r.min.y, r.min.x+wid, r.max.y), ul, 0, ZP); /* left */
33         draw(b, Rect(r.min.x, r.min.y, r.max.x, r.min.y+wid), ul, 0, ZP); /* top */
34         for(x=0;x!=wid;x++) for(y=wid-1-x;y!=wid;y++){
35                 draw(b, rectaddpt(Rect(0,0,1,1), Pt(x+r.max.x-wid, y+r.min.y)), lr, 0, ZP);
36                 draw(b, rectaddpt(Rect(0,0,1,1), Pt(x+r.min.x, y+r.max.y-wid)), lr, 0, ZP);
37         }
38 }
39 Rectangle pl_boxoutline(Image *b, Rectangle r, int style, int fill){
40         if(plldepth==0) switch(style){
41         case UP:
42                 pl_relief(b, pl_black, pl_black, r, BWID);
43                 r=insetrect(r, BWID);
44                 if(fill) draw(b, r, pl_white, 0, ZP);
45                 else border(b, r, SPACE, pl_white, ZP);
46                 break;
47         case DOWN:
48         case DOWN1:
49         case DOWN2:
50         case DOWN3:
51                 pl_relief(b, pl_black, pl_black, r, BWID);
52                 r=insetrect(r, BWID);
53                 if(fill) draw(b, r, pl_black, 0, ZP);
54                 border(b, r, SPACE, pl_black, ZP);
55                 break;
56         case PASSIVE:
57                 if(fill) draw(b, r, pl_white, 0, ZP);
58                 r=insetrect(r, PWID);
59                 if(!fill) border(b, r, SPACE, pl_white, ZP);
60                 break;
61         case FRAME:
62                 pl_relief(b, pl_white, pl_black, r, FWID);
63                 r=insetrect(r, FWID);
64                 pl_relief(b, pl_black, pl_white, r, FWID);
65                 r=insetrect(r, FWID);
66                 if(fill) draw(b, r, pl_white, 0, ZP);
67                 else border(b, r, SPACE, pl_white, ZP);
68                 break;
69         }
70         else switch(style){
71         case UP:
72                 pl_relief(b, pl_white, pl_black, r, BWID);
73                 r=insetrect(r, BWID);
74                 if(fill) draw(b, r, pl_light, 0, ZP);
75                 else border(b, r, SPACE, pl_white, ZP);
76                 break;
77         case DOWN:
78         case DOWN1:
79         case DOWN2:
80         case DOWN3:
81                 pl_relief(b, pl_black, pl_white, r, BWID);
82                 r=insetrect(r, BWID);
83                 if(fill) draw(b, r, pl_dark, 0, ZP);
84                 else border(b, r, SPACE, pl_black, ZP);
85                 break;
86         case PASSIVE:
87                 if(fill) draw(b, r, pl_light, 0, ZP);
88                 r=insetrect(r, PWID);
89                 if(!fill) border(b, r, SPACE, pl_white, ZP);
90                 break;
91         case FRAME:
92                 pl_relief(b, pl_white, pl_black, r, FWID);
93                 r=insetrect(r, FWID);
94                 pl_relief(b, pl_black, pl_white, r, FWID);
95                 r=insetrect(r, FWID);
96                 if(fill) draw(b, r, pl_light, 0, ZP);
97                 else border(b, r, SPACE, pl_white, ZP);
98                 break;
99         }
100         return insetrect(r, SPACE);
101 }
102 Rectangle pl_outline(Image *b, Rectangle r, int style){
103         return pl_boxoutline(b, r, style, 0);
104 }
105 Rectangle pl_box(Image *b, Rectangle r, int style){
106         return pl_boxoutline(b, r, style, 1);
107 }
108 Point pl_boxsize(Point interior, int state){
109         switch(state){
110         case UP:
111         case DOWN:
112         case DOWN1:
113         case DOWN2:
114         case DOWN3:
115                 return addpt(interior, Pt(2*(BWID+SPACE), 2*(BWID+SPACE)));
116         case PASSIVE:
117                 return addpt(interior, Pt(2*(PWID+SPACE), 2*(PWID+SPACE)));
118         case FRAME:
119                 return addpt(interior, Pt(4*FWID+2*SPACE, 4*FWID+2*SPACE));
120         }
121         return Pt(0, 0);
122 }
123 void pl_interior(int state, Point *ul, Point *size){
124         switch(state){
125         case UP:
126         case DOWN:
127         case DOWN1:
128         case DOWN2:
129         case DOWN3:
130                 *ul=addpt(*ul, Pt(BWID+SPACE, BWID+SPACE));
131                 *size=subpt(*size, Pt(2*(BWID+SPACE), 2*(BWID+SPACE)));
132                 break;
133         case PASSIVE:
134                 *ul=addpt(*ul, Pt(PWID+SPACE, PWID+SPACE));
135                 *size=subpt(*size, Pt(2*(PWID+SPACE), 2*(PWID+SPACE)));
136                 break;
137         case FRAME:
138                 *ul=addpt(*ul, Pt(2*FWID+SPACE, 2*FWID+SPACE));
139                 *size=subpt(*size, Pt(4*FWID+2*SPACE, 4*FWID+2*SPACE));
140         }
141 }
142
143 void pl_drawicon(Image *b, Rectangle r, int stick, int flags, Icon *s){
144         Rectangle save;
145         Point ul, offs;
146         ul=r.min;
147         offs=subpt(subpt(r.max, r.min), pl_iconsize(flags, s));
148         switch(stick){
149         case PLACENW:                                   break;
150         case PLACEN:    ul.x+=offs.x/2;                 break;
151         case PLACENE:   ul.x+=offs.x;                   break;
152         case PLACEW:                    ul.y+=offs.y/2; break;
153         case PLACECEN:  ul.x+=offs.x/2; ul.y+=offs.y/2; break;
154         case PLACEE:    ul.x+=offs.x;                   break;
155         case PLACESW:                   ul.y+=offs.y;   break;
156         case PLACES:    ul.x+=offs.x/2; ul.y+=offs.y;   break;
157         case PLACESE:   ul.x+=offs.x;   ul.y+=offs.y;   break;
158         }
159         save=b->clipr;
160         if(!rectclip(&r, save))
161                 return;
162         replclipr(b, b->repl, r);
163         if(flags&BITMAP) draw(b, Rpt(ul, addpt(ul, pl_iconsize(flags, s))), s, 0, ZP);
164         else string(b, ul, pl_black, ZP, font, s);
165         replclipr(b, b->repl, save);
166 }
167 /*
168  * Place a check mark at the left end of r.  Return the unused space.
169  * Caller must guarantee that r.max.x-r.min.x>=r.max.y-r.min.y!
170  */
171 Rectangle pl_radio(Image *b, Rectangle r, int val){
172         Rectangle remainder;
173         remainder=r;
174         r.max.x=r.min.x+r.max.y-r.min.y;
175         remainder.min.x=r.max.x;
176         r=insetrect(r, CKINSET);
177         if(plldepth==0)
178                 pl_relief(b, pl_black, pl_black, r, CKWID);
179         else
180                 pl_relief(b, pl_black, pl_white, r, CKWID);
181         r=insetrect(r, CKWID);
182         if(plldepth==0)
183                 draw(b, r, pl_white, 0, ZP);
184         else
185                 draw(b, r, pl_light, 0, ZP);
186         if(val) draw(b, insetrect(r, CKSPACE), pl_black, 0, ZP);
187         return remainder;
188 }
189 Rectangle pl_check(Image *b, Rectangle r, int val){
190         Rectangle remainder;
191         remainder=r;
192         r.max.x=r.min.x+r.max.y-r.min.y;
193         remainder.min.x=r.max.x;
194         r=insetrect(r, CKINSET);
195         if(plldepth==0)
196                 pl_relief(b, pl_black, pl_black, r, CKWID);
197         else
198                 pl_relief(b, pl_black, pl_white, r, CKWID);
199         r=insetrect(r, CKWID);
200         if(plldepth==0)
201                 draw(b, r, pl_white, 0, ZP);
202         else
203                 draw(b, r, pl_light, 0, ZP);
204         r=insetrect(r, CKBORDER);
205         if(val){
206                 line(b, Pt(r.min.x,   r.min.y+1), Pt(r.max.x-1, r.max.y  ), Endsquare, Endsquare, 0, pl_black, ZP);
207                 line(b, Pt(r.min.x,   r.min.y  ), Pt(r.max.x,   r.max.y  ), Endsquare, Endsquare, 0, pl_black, ZP);
208                 line(b, Pt(r.min.x+1, r.min.y  ), Pt(r.max.x,   r.max.y-1), Endsquare, Endsquare, 0, pl_black, ZP);
209                 line(b, Pt(r.min.x  , r.max.y-2), Pt(r.max.x-1, r.min.y-1), Endsquare, Endsquare, 0, pl_black, ZP);
210                 line(b, Pt(r.min.x,   r.max.y-1), Pt(r.max.x,   r.min.y-1), Endsquare, Endsquare, 0, pl_black, ZP);
211                 line(b, Pt(r.min.x+1, r.max.y-1), Pt(r.max.x,   r.min.y  ), Endsquare, Endsquare, 0, pl_black, ZP);
212         }
213         return remainder;
214 }
215 int pl_ckwid(void){
216         return 2*(CKINSET+CKSPACE+CKWID)+CKSIZE;
217 }
218 void pl_sliderupd(Image *b, Rectangle r1, int dir, int lo, int hi){
219         Rectangle r2, r3;
220         r2=r1;
221         r3=r1;
222         if(lo<0) lo=0;
223         if(hi<=lo) hi=lo+1;
224         switch(dir){
225         case HORIZ:
226                 r1.max.x=r1.min.x+lo;
227                 r2.min.x=r1.max.x;
228                 r2.max.x=r1.min.x+hi;
229                 if(r2.max.x>r3.max.x) r2.max.x=r3.max.x;
230                 r3.min.x=r2.max.x;
231                 break;
232         case VERT:
233                 r1.max.y=r1.min.y+lo;
234                 r2.min.y=r1.max.y;
235                 r2.max.y=r1.min.y+hi;
236                 if(r2.max.y>r3.max.y) r2.max.y=r3.max.y;
237                 r3.min.y=r2.max.y;
238                 break;
239         }
240         draw(b, r1, pl_light, 0, ZP);
241         draw(b, r2, pl_dark, 0, ZP);
242         draw(b, r3, pl_light, 0, ZP);
243 }
244 void pl_draw1(Panel *p, Image *b);
245 void pl_drawall(Panel *p, Image *b){
246         if(p->flags&INVIS) return;
247         p->b=b;
248         p->draw(p);
249         for(p=p->child;p;p=p->next) pl_draw1(p, b);
250 }
251 void pl_draw1(Panel *p, Image *b){
252         if(b!=0)
253                 pl_drawall(p, b);
254 }
255 void pldraw(Panel *p, Image *b){
256         pl_draw1(p, b);
257         flushimage(display, 1);
258 }
259 void pl_invis(Panel *p, int v){
260         for(;p;p=p->next){
261                 if(v) p->flags|=INVIS; else p->flags&=~INVIS;
262                 pl_invis(p->child, v);
263         }
264 }
265 Point pl_iconsize(int flags, Icon *p){
266         if(flags&BITMAP) return subpt(((Image *)p)->r.max, ((Image *)p)->r.min);
267         return stringsize(font, (char *)p);
268 }
269 void pl_highlight(Image *b, Rectangle r){
270         draw(b, r, pl_dark, pl_hilit, ZP);
271 }
272 void pl_clr(Image *b, Rectangle r){
273         draw(b, r, display->white, 0, ZP);
274 }
275 void pl_fill(Image *b, Rectangle r){
276         draw(b, r, plldepth==0? pl_white : pl_light, 0, ZP);
277 }
278 void pl_cpy(Image *b, Point dst, Rectangle src){
279         draw(b, Rpt(dst, addpt(dst, subpt(src.max, src.min))), b, 0, src.min);
280 }