bcf0b382acad58131a23aafe06b827f8c26d08af
[framework/uifw/elementary.git] / src / lib / elm_box.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "els_box.h"
4
5 static const char SIG_CHILD_ADDED[] = "child,added";
6 static const char SIG_CHILD_REMOVED[] = "child,removed";
7
8 static const Evas_Smart_Cb_Description _signals[] = {
9   {SIG_CHILD_ADDED, ""},
10   {SIG_CHILD_REMOVED, ""},
11   {NULL, NULL}
12 };
13
14
15 typedef struct _Widget_Data Widget_Data;
16 typedef struct _Transition_Animation_Data Transition_Animation_Data;
17
18 struct _Widget_Data
19 {
20    Evas_Object *box;
21    Eina_Bool horizontal:1;
22    Eina_Bool homogeneous:1;
23    Eina_Bool recalc:1;
24 };
25
26 struct _Elm_Box_Transition
27 {
28    double initial_time;
29    double duration;
30    Eina_Bool animation_ended:1;
31    Eina_Bool recalculate:1;
32    Ecore_Animator *animator;
33
34    struct
35      {
36         Evas_Object_Box_Layout layout;
37         void *data;
38         void(*free_data)(void *data);
39      } start, end;
40
41    void(*transition_end_cb)(void *data);
42    void *transition_end_data;
43    void (*transition_end_free_data)(void *data);
44    Eina_List *objs;
45    Evas_Object *box;
46 };
47
48 struct _Transition_Animation_Data
49 {
50    Evas_Object *obj;
51    struct
52      {
53         Evas_Coord x, y, w, h;
54      } start, end;
55 };
56
57 static const char *widtype = NULL;
58 static void _del_hook(Evas_Object *obj);
59 static void _sizing_eval(Evas_Object *obj);
60 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
61 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
62
63 static void
64 _del_pre_hook(Evas_Object *obj)
65 {
66    Widget_Data *wd = elm_widget_data_get(obj);
67    if (!wd) return;
68    evas_object_event_callback_del_full
69       (wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
70    evas_object_box_remove_all(wd->box, EINA_FALSE);
71 }
72
73 static void
74 _del_hook(Evas_Object *obj)
75 {
76    Widget_Data *wd = elm_widget_data_get(obj);
77    if (!wd) return;
78    free(wd);
79 }
80
81 static void *
82 _elm_box_list_data_get(const Eina_List *list)
83 {
84    Evas_Object_Box_Option *opt = eina_list_data_get(list);
85    return opt->obj;
86 }
87
88 static void
89 _cb_proxy_child_added(void *data, Evas_Object *o __UNUSED__, void *event_info)
90 {
91    Evas_Object *box = data;
92    Evas_Object_Box_Option *opt = event_info;
93    evas_object_smart_callback_call(box, SIG_CHILD_ADDED, opt->obj);
94 }
95
96 static void
97 _cb_proxy_child_removed(void *data, Evas_Object *o __UNUSED__, void *event_info)
98 {
99    Evas_Object *box = data;
100    Evas_Object *child = event_info;
101    evas_object_smart_callback_call(box, SIG_CHILD_REMOVED, child);
102 }
103
104 static Eina_Bool
105 _elm_box_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
106 {
107    Widget_Data *wd = elm_widget_data_get(obj);
108    const Eina_List *items;
109    void *(*list_data_get) (const Eina_List *list);
110
111    if ((!wd) || (!wd->box))
112      return EINA_FALSE;
113
114    /* Focus chain */
115    /* TODO: Change this to use other chain */
116    if ((items = elm_widget_focus_custom_chain_get(obj)))
117      list_data_get = eina_list_data_get;
118    else
119      {
120         Evas_Object_Box_Data *bd = evas_object_smart_data_get(wd->box);
121         items = bd->children;
122         list_data_get = _elm_box_list_data_get;
123
124         if (!items) return EINA_FALSE;
125      }
126
127    return elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
128 }
129
130 static void
131 _theme_hook(Evas_Object *obj)
132 {
133    Widget_Data *wd = elm_widget_data_get(obj);
134    if (!wd) return;
135    _elm_widget_mirrored_reload(obj);
136    evas_object_smart_calculate(wd->box);
137 }
138
139 static void
140 _sizing_eval(Evas_Object *obj)
141 {
142    Widget_Data *wd = elm_widget_data_get(obj);
143    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
144    Evas_Coord w, h;
145    if (!wd) return;
146    evas_object_size_hint_min_get(wd->box, &minw, &minh);
147    evas_object_size_hint_max_get(wd->box, &maxw, &maxh);
148    evas_object_size_hint_min_set(obj, minw, minh);
149    evas_object_size_hint_max_set(obj, maxw, maxh);
150    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
151    if (w < minw) w = minw;
152    if (h < minh) h = minh;
153    if ((maxw >= 0) && (w > maxw)) w = maxw;
154    if ((maxh >= 0) && (h > maxh)) h = maxh;
155    evas_object_resize(obj, w, h);
156 }
157
158 static void
159 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
160 {
161    _sizing_eval(data);
162 }
163
164 static void
165 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
166 {
167    _sizing_eval(obj);
168 }
169
170 static void
171 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
172 {
173    Evas_Object *obj = (Evas_Object *) data;
174    Widget_Data *wd = elm_widget_data_get(obj);
175    if (!wd) return;
176    _els_box_layout(o, priv, wd->horizontal, wd->homogeneous,
177                    elm_widget_mirrored_get(obj));
178 }
179
180 static Eina_Bool
181 _transition_animation(void *data)
182 {
183    evas_object_smart_changed(data);
184    return ECORE_CALLBACK_RENEW;
185 }
186
187 static void
188 _transition_layout_child_added(void *data, Evas_Object *obj __UNUSED__, void *event_info)
189 {
190    Transition_Animation_Data *tad;
191    Evas_Object_Box_Option *opt = event_info;
192    Elm_Box_Transition *layout_data = data;
193
194    tad = calloc(1, sizeof(Transition_Animation_Data));
195    if (!tad) return;
196    tad->obj = opt->obj;
197    layout_data->objs = eina_list_append(layout_data->objs, tad);
198    layout_data->recalculate = EINA_TRUE;
199 }
200
201 static void
202 _transition_layout_child_removed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
203 {
204    Eina_List *l;
205    Transition_Animation_Data *tad;
206    Elm_Box_Transition *layout_data = data;
207
208    EINA_LIST_FOREACH(layout_data->objs, l, tad)
209      {
210         if (tad->obj == event_info)
211           {
212              free(eina_list_data_get(l));
213              layout_data->objs = eina_list_remove_list(layout_data->objs, l);
214              layout_data->recalculate = EINA_TRUE;
215              break;
216           }
217      }
218 }
219
220 static void
221 _transition_layout_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
222 {
223    Elm_Box_Transition *layout_data = data;
224    layout_data->recalculate = EINA_TRUE;
225 }
226
227 static void
228 _transition_layout_calculate_coords(Evas_Object *obj, Evas_Object_Box_Data *priv,
229                                     Elm_Box_Transition *layout_data)
230 {
231    Eina_List *l;
232    Transition_Animation_Data *tad;
233    Evas_Coord x, y, w, h;
234    const double curtime = ecore_loop_time_get();
235
236    layout_data->duration =
237       layout_data->duration - (curtime - layout_data->initial_time);
238    layout_data->initial_time = curtime;
239
240    evas_object_geometry_get(obj, &x, &y, &w, &h);
241    EINA_LIST_FOREACH(layout_data->objs, l, tad)
242      {
243         evas_object_geometry_get(tad->obj, &tad->start.x, &tad->start.y,
244                                  &tad->start.w, &tad->start.h);
245         tad->start.x = tad->start.x - x;
246         tad->start.y = tad->start.y - y;
247      }
248    layout_data->end.layout(obj, priv, layout_data->end.data);
249    EINA_LIST_FOREACH(layout_data->objs, l, tad)
250      {
251         evas_object_geometry_get(tad->obj, &tad->end.x, &tad->end.y,
252                                  &tad->end.w, &tad->end.h);
253         tad->end.x = tad->end.x - x;
254         tad->end.y = tad->end.y - y;
255      }
256 }
257
258 static Eina_Bool
259 _transition_layout_load_children_list(Evas_Object_Box_Data *priv,
260                                       Elm_Box_Transition *layout_data)
261 {
262    Eina_List *l;
263    Evas_Object_Box_Option *opt;
264    Transition_Animation_Data *tad;
265
266    EINA_LIST_FREE(layout_data->objs, tad)
267       free(tad);
268
269    EINA_LIST_FOREACH(priv->children, l, opt)
270      {
271         tad = calloc(1, sizeof(Transition_Animation_Data));
272         if (!tad)
273           {
274              EINA_LIST_FREE(layout_data->objs, tad)
275                 free(tad);
276              layout_data->objs = NULL;
277              return EINA_FALSE;
278           }
279         tad->obj = opt->obj;
280         layout_data->objs = eina_list_append(layout_data->objs, tad);
281      }
282    return EINA_TRUE;
283 }
284
285 static Eina_Bool
286 _transition_layout_animation_start(Evas_Object *obj, Evas_Object_Box_Data *priv,
287                                    Elm_Box_Transition *layout_data, Eina_Bool(*transition_animation_cb)(void *data))
288 {
289    layout_data->start.layout(obj, priv, layout_data->start.data);
290    layout_data->box = obj;
291    layout_data->initial_time = ecore_loop_time_get();
292
293    if (!_transition_layout_load_children_list(priv, layout_data))
294      return EINA_FALSE;
295    _transition_layout_calculate_coords(obj, priv, layout_data);
296
297    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
298                                   _transition_layout_obj_resize_cb, layout_data);
299    evas_object_smart_callback_add(obj, SIG_CHILD_ADDED,
300                                   _transition_layout_child_added, layout_data);
301    evas_object_smart_callback_add(obj, SIG_CHILD_REMOVED,
302                                   _transition_layout_child_removed, layout_data);
303    if (!layout_data->animator)
304      layout_data->animator = ecore_animator_add(transition_animation_cb, obj);
305    layout_data->animation_ended = EINA_FALSE;
306    return EINA_TRUE;
307 }
308
309 static void
310 _transition_layout_animation_stop(Elm_Box_Transition *layout_data)
311 {
312    layout_data->animation_ended = EINA_TRUE;
313    if (layout_data->animator)
314      {
315         ecore_animator_del(layout_data->animator);
316         layout_data->animator = NULL;
317      }
318
319    if (layout_data->transition_end_cb)
320      layout_data->transition_end_cb(layout_data->transition_end_data);
321 }
322
323 static void
324 _transition_layout_animation_exec(Evas_Object *obj, Evas_Object_Box_Data *priv __UNUSED__,
325                                   Elm_Box_Transition *layout_data, const double curtime)
326 {
327    Eina_List *l;
328    Transition_Animation_Data *tad;
329    Evas_Coord x, y, w, h;
330    Evas_Coord cur_x, cur_y, cur_w, cur_h;
331    double progress = 0.0;
332
333    progress = (curtime - layout_data->initial_time) / layout_data->duration;
334    evas_object_geometry_get(obj, &x, &y, &w, &h);
335
336    EINA_LIST_FOREACH(layout_data->objs, l, tad)
337      {
338         cur_x = x + tad->start.x + ((tad->end.x - tad->start.x) * progress);
339         cur_y = y + tad->start.y + ((tad->end.y - tad->start.y) * progress);
340         cur_w = tad->start.w + ((tad->end.w - tad->start.w) * progress);
341         cur_h = tad->start.h + ((tad->end.h - tad->start.h) * progress);
342         evas_object_move(tad->obj, cur_x, cur_y);
343         evas_object_resize(tad->obj, cur_w, cur_h);
344      }
345 }
346
347 EAPI Evas_Object *
348 elm_box_add(Evas_Object *parent)
349 {
350    Evas_Object *obj;
351    Evas *e;
352    Widget_Data *wd;
353
354    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
355
356    ELM_SET_WIDTYPE(widtype, "box");
357    elm_widget_type_set(obj, "box");
358    elm_widget_sub_object_add(parent, obj);
359    elm_widget_data_set(obj, wd);
360    elm_widget_del_hook_set(obj, _del_hook);
361    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
362    elm_widget_focus_next_hook_set(obj, _elm_box_focus_next_hook);
363    elm_widget_can_focus_set(obj, EINA_FALSE);
364    elm_widget_highlight_ignore_set(obj, EINA_TRUE);
365    elm_widget_theme_hook_set(obj, _theme_hook);
366
367    wd->box = evas_object_box_add(e);
368    /*evas_object_box_layout_set(wd->box, evas_object_box_layout_vertical,
369      NULL, NULL);*/
370    evas_object_box_layout_set(wd->box, _layout, obj, NULL);
371
372    evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
373                                   _changed_size_hints, obj);
374    elm_widget_resize_object_set(obj, wd->box);
375
376    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
377
378    evas_object_smart_callbacks_descriptions_set(obj, _signals);
379    evas_object_smart_callback_add
380      (wd->box, SIG_CHILD_ADDED, _cb_proxy_child_added, obj);
381    evas_object_smart_callback_add
382      (wd->box, SIG_CHILD_REMOVED, _cb_proxy_child_removed, obj);
383
384    return obj;
385 }
386
387 EAPI void
388 elm_box_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
389 {
390    ELM_CHECK_WIDTYPE(obj, widtype);
391    Widget_Data *wd = elm_widget_data_get(obj);
392    if (!wd) return;
393    wd->horizontal = !!horizontal;
394    evas_object_smart_calculate(wd->box);
395  /*if (wd->horizontal)
396      {
397         if (wd->homogeneous)
398           evas_object_box_layout_set(wd->box,
399                                      evas_object_box_layout_homogeneous_horizontal, NULL, NULL);
400         else
401           evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
402                                      NULL, NULL);
403      }
404    else
405      {
406         if (wd->homogeneous)
407           evas_object_box_layout_set(wd->box,
408                                      evas_object_box_layout_homogeneous_vertical, NULL, NULL);
409         else
410           evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
411                                      NULL, NULL);
412      } */
413 }
414
415 EAPI Eina_Bool
416 elm_box_horizontal_get(const Evas_Object *obj)
417 {
418    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
419    Widget_Data *wd = elm_widget_data_get(obj);
420    if (!wd) return EINA_FALSE;
421    return wd->horizontal;
422 }
423
424 EAPI void
425 elm_box_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous)
426 {
427    ELM_CHECK_WIDTYPE(obj, widtype);
428    Widget_Data *wd = elm_widget_data_get(obj);
429    if (!wd) return;
430    wd->homogeneous = !!homogeneous;
431    evas_object_smart_calculate(wd->box);
432  /*if (wd->horizontal)
433      {
434         if (wd->homogeneous)
435           evas_object_box_layout_set(wd->box,
436                                      evas_object_box_layout_homogeneous_horizontal, NULL, NULL);
437         else
438           evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
439                                      NULL, NULL);
440      }
441    else
442      {
443         if (wd->homogeneous)
444           evas_object_box_layout_set(wd->box,
445                                      evas_object_box_layout_homogeneous_vertical, NULL, NULL);
446         else
447           evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
448                                      NULL, NULL);
449      } */
450 }
451
452 EAPI Eina_Bool
453 elm_box_homogeneous_get(const Evas_Object *obj)
454 {
455    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
456    Widget_Data *wd = elm_widget_data_get(obj);
457    if (!wd) return EINA_FALSE;
458    return wd->homogeneous;
459 }
460
461 EAPI void
462 elm_box_pack_start(Evas_Object *obj, Evas_Object *subobj)
463 {
464    ELM_CHECK_WIDTYPE(obj, widtype);
465    Widget_Data *wd = elm_widget_data_get(obj);
466    if (!wd) return;
467    elm_widget_sub_object_add(obj, subobj);
468    evas_object_box_prepend(wd->box, subobj);
469 }
470
471 EAPI void
472 elm_box_pack_end(Evas_Object *obj, Evas_Object *subobj)
473 {
474    ELM_CHECK_WIDTYPE(obj, widtype);
475    Widget_Data *wd = elm_widget_data_get(obj);
476    if (!wd) return;
477    elm_widget_sub_object_add(obj, subobj);
478    evas_object_box_append(wd->box, subobj);
479 }
480
481 EAPI void
482 elm_box_pack_before(Evas_Object *obj, Evas_Object *subobj, Evas_Object *before)
483 {
484    ELM_CHECK_WIDTYPE(obj, widtype);
485    Widget_Data *wd = elm_widget_data_get(obj);
486    if (!wd) return;
487    elm_widget_sub_object_add(obj, subobj);
488    evas_object_box_insert_before(wd->box, subobj, before);
489 }
490
491 EAPI void
492 elm_box_pack_after(Evas_Object *obj, Evas_Object *subobj, Evas_Object *after)
493 {
494    ELM_CHECK_WIDTYPE(obj, widtype);
495    Widget_Data *wd = elm_widget_data_get(obj);
496    if (!wd) return;
497    elm_widget_sub_object_add(obj, subobj);
498    evas_object_box_insert_after(wd->box, subobj, after);
499 }
500
501 EAPI void
502 elm_box_clear(Evas_Object *obj)
503 {
504    ELM_CHECK_WIDTYPE(obj, widtype);
505    Widget_Data *wd = elm_widget_data_get(obj);
506    if (!wd) return;
507    evas_object_box_remove_all(wd->box, EINA_TRUE);
508 }
509
510 EAPI void
511 elm_box_unpack(Evas_Object *obj, Evas_Object *subobj)
512 {
513    ELM_CHECK_WIDTYPE(obj, widtype);
514    Widget_Data *wd = elm_widget_data_get(obj);
515    if (!wd) return;
516    evas_object_box_remove(wd->box, subobj);
517 }
518
519 EAPI void
520 elm_box_unpack_all(Evas_Object *obj)
521 {
522    ELM_CHECK_WIDTYPE(obj, widtype);
523    Widget_Data *wd = elm_widget_data_get(obj);
524    if (!wd) return;
525    evas_object_box_remove_all(wd->box, EINA_FALSE);
526 }
527
528 EAPI void
529 elm_box_layout_set(Evas_Object *obj, Evas_Object_Box_Layout cb, const void *data, Ecore_Cb free_data)
530 {
531    ELM_CHECK_WIDTYPE(obj, widtype);
532    Widget_Data *wd = elm_widget_data_get(obj);
533    if (!wd) return;
534
535    if (cb)
536      evas_object_box_layout_set(wd->box, cb, data, free_data);
537    else
538      evas_object_box_layout_set(wd->box, _layout, obj, NULL);
539 }
540
541 EAPI void
542 elm_box_layout_transition(Evas_Object *obj, Evas_Object_Box_Data *priv, void *data)
543 {
544    Elm_Box_Transition *box_data = data;
545    const double curtime = ecore_loop_time_get();
546
547    if (box_data->animation_ended)
548      {
549         box_data->end.layout(obj, priv, box_data->end.data);
550         return;
551      }
552
553    if (!box_data->animator)
554      {
555         if (!_transition_layout_animation_start(obj, priv, box_data,
556                                                 _transition_animation))
557           return;
558      }
559    else
560      {
561         if (box_data->recalculate)
562           {
563              _transition_layout_calculate_coords(obj, priv, box_data);
564              box_data->recalculate = EINA_FALSE;
565           }
566      }
567
568    if ((curtime >= box_data->duration + box_data->initial_time))
569      _transition_layout_animation_stop(box_data);
570    else
571      _transition_layout_animation_exec(obj, priv, box_data, curtime);
572 }
573
574 EAPI Elm_Box_Transition *
575 elm_box_transition_new(const double duration,
576                        Evas_Object_Box_Layout start_layout, void *start_layout_data,
577                        Ecore_Cb start_layout_free_data,
578                        Evas_Object_Box_Layout end_layout, void *end_layout_data,
579                        Ecore_Cb end_layout_free_data,
580                        Ecore_Cb transition_end_cb,
581                        void *transition_end_data)
582 {
583    Elm_Box_Transition *box_data;
584
585    EINA_SAFETY_ON_NULL_RETURN_VAL(start_layout, NULL);
586    EINA_SAFETY_ON_NULL_RETURN_VAL(end_layout, NULL);
587
588    box_data = calloc(1, sizeof(Elm_Box_Transition));
589    if (!box_data)
590      return NULL;
591
592    box_data->start.layout = start_layout;
593    box_data->start.data = start_layout_data;
594    box_data->start.free_data = start_layout_free_data;
595    box_data->end.layout = end_layout;
596    box_data->end.data = end_layout_data;
597    box_data->end.free_data = end_layout_free_data;
598    box_data->duration = duration;
599    box_data->transition_end_cb = transition_end_cb;
600    box_data->transition_end_data = transition_end_data;
601    return box_data;
602 }
603
604 EAPI void
605 elm_box_transition_free(void *data)
606 {
607    EINA_SAFETY_ON_NULL_RETURN(data);
608
609    Transition_Animation_Data *tad;
610    Elm_Box_Transition *box_data = data;
611    if ((box_data->start.free_data) && (box_data->start.data))
612      box_data->start.free_data(box_data->start.data);
613    if ((box_data->end.free_data) && (box_data->end.data))
614      box_data->end.free_data(box_data->end.data);
615    EINA_LIST_FREE(box_data->objs, tad)
616       free(tad);
617    evas_object_event_callback_del(box_data->box, EVAS_CALLBACK_RESIZE, _transition_layout_obj_resize_cb);
618    evas_object_smart_callback_del(box_data->box, SIG_CHILD_ADDED, _transition_layout_child_added);
619    evas_object_smart_callback_del(box_data->box, SIG_CHILD_REMOVED, _transition_layout_child_removed);
620    if (box_data->animator)
621      {
622         ecore_animator_del(box_data->animator);
623         box_data->animator = NULL;
624      }
625    free(data);
626 }
627
628 EAPI Eina_List *
629 elm_box_children_get(const Evas_Object *obj)
630 {
631    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
632    Widget_Data *wd = elm_widget_data_get(obj);
633    if (!wd) return NULL;
634    return evas_object_box_children_get(wd->box);
635 }
636
637 EAPI void
638 elm_box_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical)
639 {
640    ELM_CHECK_WIDTYPE(obj, widtype);
641    Widget_Data *wd = elm_widget_data_get(obj);
642    if (!wd) return;
643    evas_object_box_padding_set(wd->box, horizontal, vertical);
644 }
645
646 EAPI void
647 elm_box_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical)
648 {
649    ELM_CHECK_WIDTYPE(obj, widtype);
650    Widget_Data *wd = elm_widget_data_get(obj);
651    if (!wd) return;
652    evas_object_box_padding_get(wd->box, horizontal, vertical);
653 }
654
655 EAPI void
656 elm_box_align_set(Evas_Object *obj, double horizontal, double vertical)
657 {
658    ELM_CHECK_WIDTYPE(obj, widtype);
659    Widget_Data *wd = elm_widget_data_get(obj);
660    if (!wd) return;
661    evas_object_size_hint_align_set(wd->box, horizontal, vertical);
662 }
663
664 EAPI void
665 elm_box_align_get(const Evas_Object *obj, double *horizontal, double *vertical)
666 {
667    ELM_CHECK_WIDTYPE(obj, widtype);
668    Widget_Data *wd = elm_widget_data_get(obj);
669    if (!wd) return;
670    evas_object_size_hint_align_get(wd->box, horizontal, vertical);
671 }
672
673 EAPI void
674 elm_box_recalculate(Evas_Object *obj)
675 {
676    ELM_CHECK_WIDTYPE(obj, widtype);
677    Widget_Data *wd = elm_widget_data_get(obj);
678    if ((!wd) || (wd->recalc)) return;
679    evas_object_smart_need_recalculate_set(wd->box, EINA_TRUE);
680    wd->recalc++;
681    evas_object_smart_calculate(wd->box);
682    wd->recalc--;
683 }