50810a6e57c2665f3bc116c869eeaa8c933949b4
[framework/uifw/elementary.git] / src / lib / els_box.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "els_box.h"
4
5 static void
6 _smart_extents_calculate(Evas_Object *box, Evas_Object_Box_Data *priv, int horizontal, int homogeneous)
7 {
8    Evas_Coord minw, minh, mnw, mnh, maxw, maxh;
9    const Eina_List *l;
10    Evas_Object_Box_Option *opt;
11    int c;
12
13    minw = 0;
14    minh = 0;
15    maxw = -1;
16    maxh = -1;
17    if (homogeneous)
18      {
19         EINA_LIST_FOREACH(priv->children, l, opt)
20           {
21              evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
22              if (minh < mnh) minh = mnh;
23              if (minw < mnw) minw = mnw;
24
25              evas_object_size_hint_max_get(opt->obj, &mnw, &mnh);
26              if (mnh >= 0)
27                {
28                   if (maxw == -1) maxh = mnh;
29                   else if (maxh > mnh) maxh = mnh;
30                }
31              if (mnw >= 0)
32                {
33                   if (maxw == -1) maxw = mnw;
34                   else if (maxw > mnw) maxw = mnw;
35                }
36           }
37         if (horizontal)
38           {
39              minw *= eina_list_count(priv->children);
40              if (maxw != -1)
41                 maxw *= eina_list_count(priv->children);
42              else maxw = -1;
43           }
44         else
45           {
46              minh *= eina_list_count(priv->children);
47              if (maxh != -1)
48                 maxh *= eina_list_count(priv->children);
49              else maxh = -1;
50           }
51      }
52    else
53      {
54         EINA_LIST_FOREACH(priv->children, l, opt)
55           {
56              evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
57              if (horizontal)
58                {
59                   if (minh < mnh) minh = mnh;
60                   minw += mnw;
61                }
62              else
63                {
64                   if (minw < mnw) minw = mnw;
65                   minh += mnh;
66                }
67              evas_object_size_hint_max_get(opt->obj, &mnw, &mnh);
68              if (horizontal)
69                {
70                   if (mnw < 0) maxw = -1;
71                   if (maxw != -1)
72                     {
73                        if (maxw > mnw) maxw = mnw;
74                        maxw += mnw;
75                     }
76                }
77              else
78                {
79                   if (mnh < 0) maxh = -1;
80                   if (maxh != -1)
81                     {
82                        if (maxh > mnh) maxh = mnh;
83                        maxh += mnh;
84                     }
85                }
86           }
87      }
88    c = eina_list_count(priv->children) - 1;
89    if (c > 0)
90      {
91         if (horizontal)
92           {
93              minw += priv->pad.h * c;
94              if (maxw != -1) maxw += priv->pad.h * c;
95           }
96         else
97           {
98              minh += priv->pad.v * c;
99              if (maxh != -1) maxh += priv->pad.v * c;
100           }
101      }
102    evas_object_size_hint_min_set(box, minw, minh);
103    evas_object_size_hint_max_set(box, maxw, maxh);
104 }
105
106 void
107 _els_box_layout(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous, int rtl)
108 {
109    Evas_Coord x, y, w, h, xx, yy;
110    const Eina_List *l;
111    Evas_Object *obj;
112    Evas_Coord minw, minh, wdif, hdif;
113    int count = 0;
114    double expand = 0.0;
115    double ax, ay;
116    Evas_Object_Box_Option *opt;
117
118    _smart_extents_calculate(o, priv, horizontal, homogeneous);
119
120    evas_object_geometry_get(o, &x, &y, &w, &h);
121
122    evas_object_size_hint_min_get(o, &minw, &minh);
123    evas_object_size_hint_align_get(o, &ax, &ay);
124    if ((w < minw) || (h < minh)) return;
125    count = eina_list_count(priv->children);
126    if (rtl) ax = 1.0 - ax;
127
128    if (w < minw)
129      {
130         x = x + ((w - minw) * (1.0 - ax));
131         w = minw;
132      }
133    if (h < minh)
134      {
135         y = y + ((h - minh) * (1.0 - ay));
136         h = minh;
137      }
138    EINA_LIST_FOREACH(priv->children, l, opt)
139      {
140         double wx, wy;
141
142         evas_object_size_hint_weight_get(opt->obj, &wx, &wy);
143         if (horizontal)
144           {
145              if (wx > 0.0) expand += wx;
146           }
147         else
148           {
149              if (wy > 0.0) expand += wy;
150           }
151      }
152    if (!expand)
153      {
154         evas_object_size_hint_align_get(o, &ax, &ay);
155         if (rtl) ax = 1.0 - ax;
156         if (horizontal)
157           {
158              x += (double)(w - minw) * ax;
159              w = minw;
160           }
161         else
162           {
163              y += (double)(h - minh) * ay;
164              h = minh;
165           }
166      }
167    wdif = w - minw;
168    hdif = h - minh;
169    xx = x;
170    yy = y;
171    EINA_LIST_FOREACH(priv->children, l, opt)
172      {
173         Evas_Coord mnw, mnh, mxw, mxh;
174         double wx, wy;
175         int fw, fh, xw, xh;
176
177         obj = opt->obj;
178         evas_object_size_hint_align_get(obj, &ax, &ay);
179         evas_object_size_hint_weight_get(obj, &wx, &wy);
180         evas_object_size_hint_min_get(obj, &mnw, &mnh);
181         evas_object_size_hint_max_get(obj, &mxw, &mxh);
182         fw = fh = 0;
183         xw = xh = 0;
184         if (ax == -1.0) {fw = 1; ax = 0.5;}
185         if (ay == -1.0) {fh = 1; ay = 0.5;}
186         if (rtl) ax = 1.0 - ax;
187         if (wx > 0.0) xw = 1;
188         if (wy > 0.0) xh = 1;
189         if (horizontal)
190           {
191              Evas_Coord ww, hh, ow, oh;
192
193              if (homogeneous)
194                {
195                   ww = (w / (Evas_Coord)count);
196                }
197              else
198                {
199                   ww = mnw;
200                   if ((expand > 0) && (xw))
201                     {
202                        ow = ((w - minw) * wx) / expand;
203                        wdif -= ow;
204                        ww += ow;
205                     }
206                }
207              hh = h;
208              ow = mnw;
209              if (fw) ow = ww;
210              if ((mxw >= 0) && (mxw < ow)) ow = mxw;
211              oh = mnh;
212              if (fh) oh = hh;
213              if ((mxh >= 0) && (mxh < oh)) oh = mxh;
214              evas_object_move(obj,
215                               ((!rtl) ? (xx) : (x + (w - (xx - x) - ww)))
216                               + (Evas_Coord)(((double)(ww - ow)) * ax),
217                               yy + (Evas_Coord)(((double)(hh - oh)) * ay));
218              evas_object_resize(obj, ow, oh);
219              xx += ww;
220              xx += priv->pad.h;
221           }
222         else
223           {
224              Evas_Coord ww, hh, ow, oh;
225
226              if (homogeneous)
227                {
228                   hh = (h / (Evas_Coord)count);
229                }
230              else
231                {
232                   hh = mnh;
233                   if ((expand > 0) && (xh))
234                     {
235                        oh = ((h - minh) * wy) / expand;
236                        hdif -= oh;
237                        hh += oh;
238                     }
239                }
240              ww = w;
241              ow = mnw;
242              if (fw) ow = ww;
243              if ((mxw >= 0) && (mxw < ow)) ow = mxw;
244              oh = mnh;
245              if (fh) oh = hh;
246              if ((mxh >= 0) && (mxh < oh)) oh = mxh;
247              evas_object_move(obj,
248                               xx + (Evas_Coord)(((double)(ww - ow)) * ax),
249                               yy + (Evas_Coord)(((double)(hh - oh)) * ay));
250              evas_object_resize(obj, ow, oh);
251              yy += hh;
252              yy += priv->pad.v;
253           }
254      }
255 }
256