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