================================================================
[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 static Evas_Coord
93 _smart_extents_calculate_max_height(Evas_Object *box, Evas_Object_Box_Data *priv, int obj_index)
94 {
95    Evas_Coord mnw, mnh, cw = 0, cmaxh = 0, w, ww;
96    const Eina_List *l;
97    Evas_Object_Box_Option *opt;
98    int index = 0;
99    double wx;
100
101    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
102
103    EINA_LIST_FOREACH(priv->children, l, opt)
104      {
105         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
106         evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
107
108         if(wx)
109           {
110              if (mnw != -1 && (w - cw) >= mnw)
111                 ww = w - cw;
112              else
113                 ww = w;
114           }
115         else
116            ww = mnw;
117
118         if ((cw + ww) > w)
119           {
120              if (index > obj_index )
121                {
122                   return cmaxh;
123                }
124              cw = 0;
125              cmaxh = 0;
126           }
127
128         cw += ww;
129         if (cmaxh < mnh) cmaxh = mnh;
130
131         index++;
132      }
133
134    return cmaxh;
135 }
136
137 void
138 _els_box_layout(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous)
139 {
140    _els_box_layout_ex(o, priv, horizontal, homogeneous, 0);
141 }
142
143 void
144 _els_box_layout_ex(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous, int extended)
145 {
146    Evas_Coord x, y, w, h, xx, yy;
147    const Eina_List *l;
148    Evas_Object *obj;
149    Evas_Coord minw, minh, wdif, hdif;
150    int count = 0, expand = 0;
151    double ax, ay;
152    Evas_Object_Box_Option *opt;
153
154    _smart_extents_calculate(o, priv, horizontal, homogeneous, extended);
155
156    evas_object_geometry_get(o, &x, &y, &w, &h);
157
158    evas_object_size_hint_min_get(o, &minw, &minh);
159    evas_object_size_hint_align_get(o, &ax, &ay);
160    count = eina_list_count(priv->children);
161    if (w < minw)
162      {
163         x = x + ((w - minw) * (1.0 - ax));
164         w = minw;
165      }
166    if (h < minh)
167      {
168         y = y + ((h - minh) * (1.0 - ay));
169         h = minh;
170      }
171    EINA_LIST_FOREACH(priv->children, l, opt)
172      {
173         double wx, wy;
174
175         evas_object_size_hint_weight_get(opt->obj, &wx, &wy);
176         if (horizontal)
177           {
178              if (wx > 0.0) expand++;
179           }
180         else
181           {
182              if (wy > 0.0) expand++;
183           }
184      }
185    if ((!expand) && (!extended))
186      {
187         evas_object_size_hint_align_get(o, &ax, &ay);
188         if (horizontal)
189           {
190              x += (double)(w - minw) * ax;
191              w = minw;
192           }
193         else
194           {
195              y += (double)(h - minh) * ay;
196              h = minh;
197           }
198      }
199    wdif = w - minw;
200    hdif = h - minh;
201    xx = x;
202    yy = y;
203
204    Evas_Coord cw = 0, ch = 0, cmaxh = 0, obj_index = 0;
205
206    EINA_LIST_FOREACH(priv->children, l, opt)
207      {
208         Evas_Coord mnw, mnh, mxw, mxh;
209         double wx, wy;
210         int fw, fh, xw, xh;
211
212         obj = opt->obj;
213         evas_object_size_hint_align_get(obj, &ax, &ay);
214         evas_object_size_hint_weight_get(obj, &wx, &wy);
215         evas_object_size_hint_min_get(obj, &mnw, &mnh);
216         evas_object_size_hint_max_get(obj, &mxw, &mxh);
217         fw = fh = 0;
218         xw = xh = 0;
219         if (ax == -1.0) {fw = 1; ax = 0.5;}
220         if (ay == -1.0) {fh = 1; ay = 0.5;}
221         if (wx > 0.0) xw = 1;
222         if (wy > 0.0) xh = 1;
223         if (horizontal)
224           {
225              if (homogeneous)
226                {
227                   Evas_Coord ww, hh, ow, oh;
228
229                   ww = (w / (Evas_Coord)count);
230                   hh = h;
231                   ow = mnw;
232                   if (fw) ow = ww;
233                   if ((mxw >= 0) && (mxw < ow))
234                     ow = mxw;
235                   oh = mnh;
236                   if (fh) oh = hh;
237                   if ((mxh >= 0) && (mxh < oh))
238                     oh = mxh;
239                   evas_object_move(obj,
240                                    xx + (Evas_Coord)(((double)(ww - ow)) * ax),
241                                    yy + (Evas_Coord)(((double)(hh - oh)) * ay));
242                   evas_object_resize(obj, ow, oh);
243                   xx += ww;
244                }
245              else
246                {
247                   if (extended)
248                     {
249                        Evas_Coord ww, hh, ow, oh;
250                        if(wx)
251                          {
252                             if (mnw != -1 && (w - cw) >= mnw)
253                                ww = w - cw;
254                             else
255                                ww = w;
256                          }
257                        else
258                           ww = mnw;
259                        hh = _smart_extents_calculate_max_height(o, priv, obj_index);
260
261                        ow = mnw;
262                        if (fw) ow = ww;
263                        if ((mxw >= 0) && (mxw < ow)) ow = mxw;
264                        oh = mnh;
265                        if (fh) oh = hh;
266                        if ((mxh >= 0) && (mxh < oh)) oh = mxh;
267
268                        if ((cw + ww) > w)
269                          {
270                             ch += cmaxh;
271
272                             cw = 0;
273                             cmaxh = 0;
274                          }
275
276                        evas_object_move(obj,
277                                         xx + cw + (Evas_Coord)(((double)(ww - ow)) * ax),
278                                         yy + ch + (Evas_Coord)(((double)(hh - oh)) * ay));
279                        evas_object_resize(obj, ow, oh);
280
281                        cw += ww;
282                        if (cmaxh < hh) cmaxh = hh;
283                     }
284                   else
285                     {
286                        Evas_Coord ww, hh, ow, oh;
287
288                        ww = mnw;
289                        if ((expand > 0) && (xw))
290                          {
291                             if (expand == 1) ow = wdif;
292                             else ow = (w - minw) / expand;
293                             wdif -= ow;
294                             ww += ow;
295                          }
296                        hh = h;
297                        ow = mnw;
298                        if (fw) ow = ww;
299                        if ((mxw >= 0) && (mxw < ow)) ow = mxw;
300                        oh = mnh;
301                        if (fh) oh = hh;
302                        if ((mxh >= 0) && (mxh < oh)) oh = mxh;
303                        evas_object_move(obj,
304                                         xx + (Evas_Coord)(((double)(ww - ow)) * ax),
305                                         yy + (Evas_Coord)(((double)(hh - oh)) * ay));
306                        evas_object_resize(obj, ow, oh);
307                        xx += ww;
308                     }
309                }
310           }
311         else
312           {
313              if (homogeneous)
314                {
315                   Evas_Coord ww, hh, ow, oh;
316
317                   ww = w;
318                   hh = (h / (Evas_Coord)count);
319                   ow = mnw;
320                   if (fw) ow = ww;
321                   if ((mxw >= 0) && (mxw < ow)) ow = mxw;
322                   oh = mnh;
323                   if (fh) oh = hh;
324                   if ((mxh >= 0) && (mxh < oh)) oh = mxh;
325                   evas_object_move(obj,
326                                    xx + (Evas_Coord)(((double)(ww - ow)) * ax),
327                                    yy + (Evas_Coord)(((double)(hh - oh)) * ay));
328                   evas_object_resize(obj, ow, oh);
329                   yy += hh;
330                }
331              else
332                {
333                   Evas_Coord ww, hh, ow, oh;
334
335                   ww = w;
336                   hh = mnh;
337                   if ((expand > 0) && (xh))
338                     {
339                        if (expand == 1) oh = hdif;
340                        else oh = (h - minh) / expand;
341                        hdif -= oh;
342                        hh += oh;
343                     }
344                   ow = mnw;
345                   if (fw) ow = ww;
346                   if ((mxw >= 0) && (mxw < ow)) ow = mxw;
347                   oh = mnh;
348                   if (fh) oh = hh;
349                   if ((mxh >= 0) && (mxh < oh)) oh = mxh;
350                   evas_object_move(obj,
351                                    xx + (Evas_Coord)(((double)(ww - ow)) * ax),
352                                    yy + (Evas_Coord)(((double)(hh - oh)) * ay));
353                   evas_object_resize(obj, ow, oh);
354                   yy += hh;
355                }
356           }
357
358         obj_index++;
359      }
360 }
361