6c824ad0d9005ad7b1ee2b9b9f6716c856111195
[framework/uifw/elementary.git] / src / lib / els_box.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 static void
5 _smart_extents_calculate(Evas_Object *box, Evas_Object_Box_Data *priv, int horizontal, int homogeneous, int extended)
6 {
7         Evas_Coord minw, minh, maxw, maxh, mnw, mnh, ww;
8         Evas_Coord w, cw = 0, cmaxh = 0;
9         const Eina_List *l;
10         Evas_Object_Box_Option *opt;
11     double wx;
12
13         /* FIXME: need to calc max */
14         minw = 0;
15         minh = 0;
16         maxw = -1;
17         maxh = -1;
18
19         if (homogeneous)
20         {
21                 EINA_LIST_FOREACH(priv->children, l, opt)
22                 {
23                         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
24                         if (minh < mnh) minh = mnh;
25                         if (minw < mnw) minw = mnw;
26                 }
27                 if (horizontal)
28                         minw *= eina_list_count(priv->children);
29                 else
30                         minh *= eina_list_count(priv->children);
31         }
32         else
33         {
34                 if (horizontal && extended)
35                 {
36                         evas_object_geometry_get(box, NULL, NULL, &w, NULL);
37                         evas_object_size_hint_min_get(box, &minw, NULL);
38                 }
39
40                 EINA_LIST_FOREACH(priv->children, l, opt)
41                 {
42                         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
43
44                         if (horizontal)
45                         {
46                                 if (extended)
47                                 {
48                                         evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
49
50                                         if(wx)
51                                         {
52                                            if (mnw != -1 && (w - cw) >= mnw)
53                                                    ww = w - cw;
54                                            else
55                                                    ww = w;
56                                         }
57                                         else
58                                                 ww = mnw;
59
60                                         if ((cw + mnw) > w)
61                                         {
62                                                 minh += cmaxh;
63
64                                                 cw = 0;
65                                                 cmaxh = 0;
66                                         }
67                                         cw += ww;
68                                         if (cmaxh < mnh) cmaxh = mnh;
69                                 }
70                                 else
71                                 {
72                                         if (minh < mnh) minh = mnh;
73                                         minw += mnw;
74                                 }
75                         }
76                         else
77                         {
78                                 if (minw < mnw) minw = mnw;
79                                 minh += mnh;
80                         }
81                 }
82
83                 if(horizontal && extended)
84                 {
85                         minh += cmaxh;
86                 }
87
88         }
89         evas_object_size_hint_min_set(box, minw, minh);
90 }
91
92
93 static Evas_Coord
94 _smart_extents_calculate_max_height(Evas_Object *box, Evas_Object_Box_Data *priv, int obj_index)
95 {
96         Evas_Coord mnw, mnh, cw = 0, cmaxh = 0, w, ww;
97         const Eina_List *l;
98         Evas_Object_Box_Option *opt;
99         int index = 0;
100     double wx;
101
102         evas_object_geometry_get(box, NULL, NULL, &w, NULL);
103
104         EINA_LIST_FOREACH(priv->children, l, opt)
105         {
106                 evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
107                 evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
108
109                 if(wx)
110                 {
111                         if (mnw != -1 && (w - cw) >= mnw)
112                                 ww = w - cw;
113                         else
114                                 ww = w;
115                 }
116                 else
117                         ww = mnw;
118
119                 if ((cw + ww) > w)
120                 {
121                         if (index > obj_index )
122                         {
123                                 return cmaxh;
124                         }
125                         cw = 0;
126                         cmaxh = 0;
127                 }
128
129                 cw += ww;
130                 if (cmaxh < mnh) cmaxh = mnh;
131
132                 index++;
133         }
134         
135         return cmaxh;
136 }
137
138
139 void
140 _els_box_layout(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous)
141 {
142         _els_box_layout_ex(o, priv, horizontal, homogeneous, 0);
143 }
144
145 void
146 _els_box_layout_ex(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous, int extended)
147 {
148    Evas_Coord x, y, w, h, xx, yy;
149    const Eina_List *l;
150    Evas_Object *obj;
151    Evas_Coord minw, minh, wdif, hdif;
152    int count = 0, expand = 0;
153    double ax, ay;
154    Evas_Object_Box_Option *opt;
155
156    _smart_extents_calculate(o, priv, horizontal, homogeneous, extended);
157
158    evas_object_geometry_get(o, &x, &y, &w, &h);
159
160    evas_object_size_hint_min_get(o, &minw, &minh);
161    evas_object_size_hint_align_get(o, &ax, &ay);
162    count = eina_list_count(priv->children);
163    if (w < minw)
164      {
165         x = x + ((w - minw) * (1.0 - ax));
166         w = minw;
167      }
168    if (h < minh)
169      {
170         y = y + ((h - minh) * (1.0 - ay));
171         h = minh;
172      }
173    EINA_LIST_FOREACH(priv->children, l, opt)
174      {
175         double wx, wy;
176
177         evas_object_size_hint_weight_get(opt->obj, &wx, &wy);
178         if (horizontal)
179           {
180              if (wx > 0.0) expand++;
181           }
182         else
183           {
184              if (wy > 0.0) expand++;
185           }
186      }
187    if (expand == 0 && (!extended))
188      {
189         evas_object_size_hint_align_get(o, &ax, &ay);
190         if (horizontal)
191           {
192              x += (double)(w - minw) * ax;
193              w = minw;
194           }
195         else
196           {
197              y += (double)(h - minh) * ay;
198              h = minh;
199           }
200      }
201    wdif = w - minw;
202    hdif = h - minh;
203    xx = x;
204    yy = y;
205
206    Evas_Coord cw = 0, ch = 0, cmaxh = 0, obj_index = 0;
207
208    EINA_LIST_FOREACH(priv->children, l, opt)
209      {
210         Evas_Coord mnw, mnh, mxw, mxh;
211         double wx, wy;
212         int fw, fh, xw, xh;
213
214         obj = opt->obj;
215         evas_object_size_hint_align_get(obj, &ax, &ay);
216         evas_object_size_hint_weight_get(obj, &wx, &wy);
217         evas_object_size_hint_min_get(obj, &mnw, &mnh);
218         evas_object_size_hint_max_get(obj, &mxw, &mxh);
219         fw = fh = 0;
220         xw = xh = 0;
221         if (ax == -1.0) {fw = 1; ax = 0.5;}
222         if (ay == -1.0) {fh = 1; ay = 0.5;}
223         if (wx > 0.0) xw = 1;
224         if (wy > 0.0) xh = 1;
225         if (horizontal)
226           {
227              if (homogeneous)
228                {
229                   Evas_Coord ww, hh, ow, oh;
230
231                   ww = (w / (Evas_Coord)count);
232                   hh = h;
233                   ow = mnw;
234                   if (fw) ow = ww;
235                   if ((mxw >= 0) && (mxw < ow))
236                     ow = mxw;
237                   oh = mnh;
238                   if (fh) oh = hh;
239                   if ((mxh >= 0) && (mxh < oh))
240                     oh = mxh;
241                   evas_object_move(obj,
242                                    xx + (Evas_Coord)(((double)(ww - ow)) * ax),
243                                    yy + (Evas_Coord)(((double)(hh - oh)) * ay));
244                   evas_object_resize(obj, ow, oh);
245                   xx += ww;
246                }
247              else
248                {
249                            if (extended)
250                            {
251                                    Evas_Coord ww, hh, ow, oh;
252                                    if(wx)
253                                    {
254                                            if (mnw != -1 && (w - cw) >= mnw)
255                                                    ww = w - cw;
256                                            else
257                                                    ww = w;
258                                    }
259                                    else
260                                            ww = mnw;
261                                    hh = _smart_extents_calculate_max_height(o, priv, obj_index);
262
263                                    ow = mnw;
264                                    if (fw) ow = ww;
265                                    if ((mxw >= 0) && (mxw < ow)) ow = mxw;
266                                    oh = mnh;
267                                    if (fh) oh = hh;
268                                    if ((mxh >= 0) && (mxh < oh)) oh = mxh;
269
270                                    if ((cw + ww) > w)
271                                    {
272                                            ch += cmaxh;
273
274                                            cw = 0;
275                                            cmaxh = 0;
276                                    }
277
278                                    evas_object_move(obj,
279                                                    xx + cw + (Evas_Coord)(((double)(ww - ow)) * ax),
280                                                    yy + ch + (Evas_Coord)(((double)(hh - oh)) * ay));
281                                    evas_object_resize(obj, ow, oh);
282
283                                    cw += ww;
284                                    if (cmaxh < hh) cmaxh = hh;
285                            }
286                            else
287                            {
288                                   Evas_Coord ww, hh, ow, oh;
289
290                                   ww = mnw;
291                                   if ((expand > 0) && (xw))
292                                         {
293                                            if (expand == 1) ow = wdif;
294                                            else ow = (w - minw) / expand;
295                                            wdif -= ow;
296                                            ww += ow;
297                                         }
298                                   hh = h;
299                                   ow = mnw;
300                                   if (fw) ow = ww;
301                                   if ((mxw >= 0) && (mxw < ow)) ow = mxw;
302                                   oh = mnh;
303                                   if (fh) oh = hh;
304                                   if ((mxh >= 0) && (mxh < oh)) oh = mxh;
305                                   evas_object_move(obj,
306                                                    xx + (Evas_Coord)(((double)(ww - ow)) * ax),
307                                                    yy + (Evas_Coord)(((double)(hh - oh)) * ay));
308                                   evas_object_resize(obj, ow, oh);
309                                   xx += ww;
310                            }
311                }
312           }
313         else
314           {
315              if (homogeneous)
316                {
317                   Evas_Coord ww, hh, ow, oh;
318
319                   ww = w;
320                   hh = (h / (Evas_Coord)count);
321                   ow = mnw;
322                   if (fw) ow = ww;
323                   if ((mxw >= 0) && (mxw < ow)) ow = mxw;
324                   oh = mnh;
325                   if (fh) oh = hh;
326                   if ((mxh >= 0) && (mxh < oh)) oh = mxh;
327                   evas_object_move(obj,
328                                    xx + (Evas_Coord)(((double)(ww - ow)) * ax),
329                                    yy + (Evas_Coord)(((double)(hh - oh)) * ay));
330                   evas_object_resize(obj, ow, oh);
331                   yy += hh;
332                }
333              else
334                {
335                   Evas_Coord ww, hh, ow, oh;
336
337                   ww = w;
338                   hh = mnh;
339                   if ((expand > 0) && (xh))
340                     {
341                        if (expand == 1) oh = hdif;
342                        else oh = (h - minh) / expand;
343                        hdif -= oh;
344                        hh += oh;
345                     }
346                   ow = mnw;
347                   if (fw) ow = ww;
348                   if ((mxw >= 0) && (mxw < ow)) ow = mxw;
349                   oh = mnh;
350                   if (fh) oh = hh;
351                   if ((mxh >= 0) && (mxh < oh)) oh = mxh;
352                   evas_object_move(obj,
353                                    xx + (Evas_Coord)(((double)(ww - ow)) * ax),
354                                    yy + (Evas_Coord)(((double)(hh - oh)) * ay));
355                   evas_object_resize(obj, ow, oh);
356                   yy += hh;
357                }
358           }
359
360                 obj_index++;
361      }
362 }
363