Merge upstream with r75974
[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;
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    xx = x;
168    yy = y;
169    EINA_LIST_FOREACH(priv->children, l, opt)
170      {
171         Evas_Coord mnw, mnh, mxw, mxh;
172         double wx, wy;
173         int fw, fh, xw, xh;
174
175         obj = opt->obj;
176         evas_object_size_hint_align_get(obj, &ax, &ay);
177         evas_object_size_hint_weight_get(obj, &wx, &wy);
178         evas_object_size_hint_min_get(obj, &mnw, &mnh);
179         evas_object_size_hint_max_get(obj, &mxw, &mxh);
180         fw = fh = 0;
181         xw = xh = 0;
182         if (ax == -1.0) {fw = 1; ax = 0.5;}
183         if (ay == -1.0) {fh = 1; ay = 0.5;}
184         if (rtl) ax = 1.0 - ax;
185         if (wx > 0.0) xw = 1;
186         if (wy > 0.0) xh = 1;
187         if (horizontal)
188           {
189              Evas_Coord ww, hh, ow, oh;
190
191              if (homogeneous)
192                {
193                   ww = (w / (Evas_Coord)count);
194                }
195              else
196                {
197                   ww = mnw;
198                   if ((expand > 0) && (xw))
199                     {
200                        ow = ((w - minw) * wx) / expand;
201                        ww += ow;
202                     }
203                }
204              hh = h;
205              ow = mnw;
206              if (fw) ow = ww;
207              if ((mxw >= 0) && (mxw < ow)) ow = mxw;
208              oh = mnh;
209              if (fh) oh = hh;
210              if ((mxh >= 0) && (mxh < oh)) oh = mxh;
211              evas_object_move(obj,
212                               ((!rtl) ? (xx) : (x + (w - (xx - x) - ww)))
213                               + (Evas_Coord)(((double)(ww - ow)) * ax),
214                               yy + (Evas_Coord)(((double)(hh - oh)) * ay));
215              evas_object_resize(obj, ow, oh);
216              xx += ww;
217              xx += priv->pad.h;
218           }
219         else
220           {
221              Evas_Coord ww, hh, ow, oh;
222
223              if (homogeneous)
224                {
225                   hh = (h / (Evas_Coord)count);
226                }
227              else
228                {
229                   hh = mnh;
230                   if ((expand > 0) && (xh))
231                     {
232                        oh = ((h - minh) * wy) / expand;
233                        hh += oh;
234                     }
235                }
236              ww = w;
237              ow = mnw;
238              if (fw) ow = ww;
239              if ((mxw >= 0) && (mxw < ow)) ow = mxw;
240              oh = mnh;
241              if (fh) oh = hh;
242              if ((mxh >= 0) && (mxh < oh)) oh = mxh;
243              evas_object_move(obj,
244                               xx + (Evas_Coord)(((double)(ww - ow)) * ax),
245                               yy + (Evas_Coord)(((double)(hh - oh)) * ay));
246              evas_object_resize(obj, ow, oh);
247              yy += hh;
248              yy += priv->pad.v;
249           }
250      }
251 }
252