]> git.decadent.org.uk Git - ion3.git/blob - ioncore/framedpholder.c
Merge commit '20071220' into HEAD
[ion3.git] / ioncore / framedpholder.c
1 /*
2  * ion/ioncore/framedpholder.c
3  *
4  * Copyright (c) Tuomo Valkonen 2005-2007. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <libtu/objp.h>
10 #include <libtu/obj.h>
11 #include <libtu/minmax.h>
12
13 #include "frame.h"
14 #include "framedpholder.h"
15 #include "sizehint.h"
16
17
18 /*{{{ Init/deinit */
19
20
21 bool framedpholder_init(WFramedPHolder *ph, WPHolder *cont,
22                         const WFramedParam *param)
23 {
24     assert(cont!=NULL);
25     
26     pholder_init(&(ph->ph));
27
28     ph->cont=cont;
29     ph->param=*param;
30     
31     watch_init(&ph->frame_watch);
32     
33     return TRUE;
34 }
35  
36
37 WFramedPHolder *create_framedpholder(WPHolder *cont,
38                                      const WFramedParam *param)
39 {
40     CREATEOBJ_IMPL(WFramedPHolder, framedpholder, (p, cont, param));
41 }
42
43
44 void framedpholder_deinit(WFramedPHolder *ph)
45 {
46     if(ph->cont!=NULL){
47         destroy_obj((Obj*)ph->cont);
48         ph->cont=NULL;
49     }
50     
51     pholder_deinit(&(ph->ph));
52     watch_reset(&ph->frame_watch);
53 }
54
55
56 /*}}}*/
57
58
59 /*{{{ Attach */
60
61
62 typedef struct{
63     WRegionAttachData *data;
64     WFramedParam *param;
65     WRegion *reg_ret;
66 } AP;
67
68
69 void frame_adjust_to_initial(WFrame *frame, const WFitParams *fp, 
70                              const WFramedParam *param, WRegion *reg)
71 {
72     WRectangle rqg, mg;
73  
74     if(!(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER)))
75         return;
76
77     mplex_managed_geom((WMPlex*)frame, &mg);
78
79     /* Adjust geometry */
80     if(!param->inner_geom_gravity_set){
81         rqg.x=REGION_GEOM(frame).x;
82         rqg.y=REGION_GEOM(frame).y;
83         rqg.w=maxof(1, REGION_GEOM(reg).w+(REGION_GEOM(frame).w-mg.w));
84         rqg.h=maxof(1, REGION_GEOM(reg).h+(REGION_GEOM(frame).h-mg.h));
85     }else{
86         int bl=mg.x;
87         int br=REGION_GEOM(frame).w-(mg.x+mg.w);
88         int bt=mg.y;
89         int bb=REGION_GEOM(frame).h-(mg.y+mg.h);
90         
91         rqg.x=(/*fp->g.x+*/param->inner_geom.x+
92                xgravity_deltax(param->gravity, bl, br));
93         rqg.y=(/*fp->g.y+*/param->inner_geom.y+
94                xgravity_deltay(param->gravity, bt, bb));
95         rqg.w=maxof(1, param->inner_geom.w+(REGION_GEOM(frame).w-mg.w));
96         rqg.h=maxof(1, param->inner_geom.h+(REGION_GEOM(frame).h-mg.h));
97     }
98
99     if(!(fp->mode&REGION_FIT_WHATEVER))
100         rectangle_constrain(&rqg, &fp->g);
101     
102     region_fit((WRegion*)frame, &rqg, REGION_FIT_EXACT);
103 }
104
105
106 WRegion *framed_handler(WWindow *par, 
107                         const WFitParams *fp, 
108                         void *ap_)
109 {
110     AP *ap=(AP*)ap_;
111     WMPlexAttachParams mp=MPLEXATTACHPARAMS_INIT;
112     WFramedParam *param=ap->param;
113     WFrame *frame;
114     WRegion *reg;
115     
116     frame=create_frame(par, fp, param->mode);
117     
118     if(frame==NULL)
119         return NULL;
120     
121     if(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER))
122         mp.flags|=MPLEX_ATTACH_WHATEVER;
123
124     reg=mplex_do_attach(&frame->mplex, &mp, ap->data);
125     
126     ap->reg_ret=reg;
127     
128     if(reg==NULL){
129         destroy_obj((Obj*)frame);
130         return NULL;
131     }
132     
133     frame_adjust_to_initial(frame, fp, param, reg);
134     
135     return (WRegion*)frame;
136 }
137
138
139 WRegion *region_attach_framed(WRegion *reg, WFramedParam *param,
140                               WRegionAttachFn *fn, void *fn_param,
141                               WRegionAttachData *data)
142 {
143     WRegionAttachData data2;
144     AP ap;
145
146     data2.type=REGION_ATTACH_NEW;
147     data2.u.n.fn=framed_handler;
148     data2.u.n.param=&ap;
149     
150     ap.data=data;
151     ap.param=param;
152     ap.reg_ret=NULL;
153     
154     return fn(reg, fn_param, &data2);
155 }
156
157
158 WRegion *framedpholder_do_attach(WFramedPHolder *ph, int flags,
159                                  WRegionAttachData *data)
160 {
161     WRegionAttachData data2;
162     WFrame *frame;
163     AP ap;
164     
165     frame=(WFrame*)ph->frame_watch.obj;
166     
167     if(frame!=NULL){
168         WMPlexAttachParams mp=MPLEXATTACHPARAMS_INIT;
169         return mplex_do_attach(&frame->mplex, &mp, data);
170     }
171     
172     if(ph->cont==NULL)
173         return FALSE;
174
175     data2.type=REGION_ATTACH_NEW;
176     data2.u.n.fn=framed_handler;
177     data2.u.n.param=&ap;
178     
179     ap.data=data;
180     ap.param=&ph->param;
181     ap.reg_ret=NULL;
182         
183     frame=(WFrame*)pholder_do_attach(ph->cont, flags, &data2);
184     
185     if(frame!=NULL){
186         assert(OBJ_IS(frame, WFrame));
187         watch_setup(&ph->frame_watch, (Obj*)frame, NULL);
188     }
189     
190     return ap.reg_ret;
191 }
192
193
194 /*}}}*/
195
196
197 /*{{{ Other dynfuns */
198
199
200 bool framedpholder_do_goto(WFramedPHolder *ph)
201 {
202     WRegion *frame=(WRegion*)ph->frame_watch.obj;
203     
204     if(frame!=NULL)
205         return region_goto((WRegion*)frame);
206     else if(ph->cont!=NULL)
207         return pholder_goto(ph->cont);
208     else
209         return FALSE;
210 }
211
212
213 WRegion *framedpholder_do_target(WFramedPHolder *ph)
214 {
215     WRegion *frame=(WRegion*)ph->frame_watch.obj;
216     
217     return (frame!=NULL
218             ? frame
219             : (ph->cont!=NULL
220                ? pholder_target(ph->cont)
221                : NULL));
222 }
223
224
225 bool framedpholder_stale(WFramedPHolder *ph)
226 {
227     WRegion *frame=(WRegion*)ph->frame_watch.obj;
228     
229     return (frame==NULL && (ph->cont==NULL || pholder_stale(ph->cont)));
230 }
231
232
233 /*}}}*/
234
235
236 /*{{{ Class information */
237
238
239 static DynFunTab framedpholder_dynfuntab[]={
240     {(DynFun*)pholder_do_attach, 
241      (DynFun*)framedpholder_do_attach},
242
243     {(DynFun*)pholder_do_goto, 
244      (DynFun*)framedpholder_do_goto},
245
246     {(DynFun*)pholder_do_target, 
247      (DynFun*)framedpholder_do_target},
248      
249     {(DynFun*)pholder_stale, 
250      (DynFun*)framedpholder_stale},
251     
252     END_DYNFUNTAB
253 };
254
255 IMPLCLASS(WFramedPHolder, WPHolder, framedpholder_deinit, 
256           framedpholder_dynfuntab);
257
258
259 /*}}}*/
260