]> git.decadent.org.uk Git - ion3.git/blob - ioncore/framedpholder.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[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     return TRUE;
32 }
33  
34
35 WFramedPHolder *create_framedpholder(WPHolder *cont,
36                                      const WFramedParam *param)
37 {
38     CREATEOBJ_IMPL(WFramedPHolder, framedpholder, (p, cont, param));
39 }
40
41
42 void framedpholder_deinit(WFramedPHolder *ph)
43 {
44     if(ph->cont!=NULL){
45         destroy_obj((Obj*)ph->cont);
46         ph->cont=NULL;
47     }
48     
49     pholder_deinit(&(ph->ph));
50 }
51
52
53 /*}}}*/
54
55
56 /*{{{ Attach */
57
58
59 typedef struct{
60     WRegionAttachData *data;
61     WFramedParam *param;
62 } AP;
63
64
65 void frame_adjust_to_initial(WFrame *frame, const WFitParams *fp, 
66                              const WFramedParam *param, WRegion *reg)
67 {
68     WRectangle rqg, mg;
69  
70     if(!(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER)))
71         return;
72
73     mplex_managed_geom((WMPlex*)frame, &mg);
74
75     /* Adjust geometry */
76     if(!param->inner_geom_gravity_set){
77         rqg.x=REGION_GEOM(frame).x;
78         rqg.y=REGION_GEOM(frame).y;
79         rqg.w=maxof(1, REGION_GEOM(reg).w+(REGION_GEOM(frame).w-mg.w));
80         rqg.h=maxof(1, REGION_GEOM(reg).h+(REGION_GEOM(frame).h-mg.h));
81     }else{
82         int bl=mg.x;
83         int br=REGION_GEOM(frame).w-(mg.x+mg.w);
84         int bt=mg.y;
85         int bb=REGION_GEOM(frame).h-(mg.y+mg.h);
86         
87         rqg.x=(/*fp->g.x+*/param->inner_geom.x+
88                xgravity_deltax(param->gravity, bl, br));
89         rqg.y=(/*fp->g.y+*/param->inner_geom.y+
90                xgravity_deltay(param->gravity, bt, bb));
91         rqg.w=maxof(1, param->inner_geom.w+(REGION_GEOM(frame).w-mg.w));
92         rqg.h=maxof(1, param->inner_geom.h+(REGION_GEOM(frame).h-mg.h));
93     }
94
95     if(!(fp->mode&REGION_FIT_WHATEVER))
96         rectangle_constrain(&rqg, &fp->g);
97     
98     region_fit((WRegion*)frame, &rqg, REGION_FIT_EXACT);
99 }
100
101
102 WRegion *framed_handler(WWindow *par, 
103                         const WFitParams *fp, 
104                         void *ap_)
105 {
106     AP *ap=(AP*)ap_;
107     WMPlexAttachParams mp=MPLEXATTACHPARAMS_INIT;
108     WFramedParam *param=ap->param;
109     WFrame *frame;
110     WRegion *reg;
111     
112     frame=create_frame(par, fp, param->mode);
113     
114     if(frame==NULL)
115         return NULL;
116     
117     if(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER))
118         mp.flags|=MPLEX_ATTACH_WHATEVER;
119
120     reg=mplex_do_attach(&frame->mplex, &mp, ap->data);
121     
122     if(reg==NULL){
123         destroy_obj((Obj*)frame);
124         return NULL;
125     }
126     
127     frame_adjust_to_initial(frame, fp, param, reg);
128     
129     return (WRegion*)frame;
130 }
131
132
133 WRegion *region_attach_framed(WRegion *reg, WFramedParam *param,
134                               WRegionAttachFn *fn, void *fn_param,
135                               WRegionAttachData *data)
136 {
137     WRegionAttachData data2;
138     AP ap;
139
140     data2.type=REGION_ATTACH_NEW;
141     data2.u.n.fn=framed_handler;
142     data2.u.n.param=&ap;
143     
144     ap.data=data;
145     ap.param=param;
146     
147     return fn(reg, fn_param, &data2);
148 }
149
150
151 WRegion *framedpholder_do_attach(WFramedPHolder *ph, int flags,
152                                  WRegionAttachData *data)
153 {
154     WRegionAttachData data2;
155     AP ap;
156     
157     if(ph->cont==NULL)
158         return FALSE;
159
160     data2.type=REGION_ATTACH_NEW;
161     data2.u.n.fn=framed_handler;
162     data2.u.n.param=&ap;
163     
164     ap.data=data;
165     ap.param=&ph->param;
166         
167     return pholder_do_attach(ph->cont, flags, &data2);
168 }
169
170
171 /*}}}*/
172
173
174 /*{{{ Other dynfuns */
175
176
177 bool framedpholder_do_goto(WFramedPHolder *ph)
178 {
179     return (ph->cont!=NULL
180             ? pholder_goto(ph->cont)
181             : FALSE);
182 }
183
184
185 WRegion *framedpholder_do_target(WFramedPHolder *ph)
186 {
187     return (ph->cont!=NULL
188             ? pholder_target(ph->cont)
189             : NULL);
190 }
191
192
193 WPHolder *framedpholder_do_root(WFramedPHolder *ph)
194 {
195     WPHolder *root;
196     
197     if(ph->cont==NULL)
198         return NULL;
199     
200     root=pholder_root(ph->cont);
201     
202     return (root!=ph->cont 
203             ? root
204             : &ph->ph);
205 }
206
207
208 /*}}}*/
209
210
211 /*{{{ Class information */
212
213
214 static DynFunTab framedpholder_dynfuntab[]={
215     {(DynFun*)pholder_do_attach, 
216      (DynFun*)framedpholder_do_attach},
217
218     {(DynFun*)pholder_do_goto, 
219      (DynFun*)framedpholder_do_goto},
220
221     {(DynFun*)pholder_do_target, 
222      (DynFun*)framedpholder_do_target},
223      
224     {(DynFun*)pholder_do_root, 
225      (DynFun*)framedpholder_do_root},
226     
227     END_DYNFUNTAB
228 };
229
230 IMPLCLASS(WFramedPHolder, WPHolder, framedpholder_deinit, 
231           framedpholder_dynfuntab);
232
233
234 /*}}}*/
235