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