1 #define EFL_CANVAS_GROUP_PROTECTED
2 
3 #include "evas_common_private.h"
4 #include "evas_private.h"
5 
6 #define MY_CLASS_NAME "Evas_Box"
7 #define MY_CLASS_NAME_LEGACY "Evas_Object_Box"
8 
9 #define MY_CLASS EVAS_BOX_CLASS
10 
11 typedef struct _Evas_Object_Box_Iterator Evas_Object_Box_Iterator;
12 typedef struct _Evas_Object_Box_Accessor Evas_Object_Box_Accessor;
13 
14 struct _Evas_Object_Box_Iterator
15 {
16    Eina_Iterator iterator;
17 
18    Eina_Iterator *real_iterator;
19    const Evas_Object *box;
20 };
21 
22 struct _Evas_Object_Box_Accessor
23 {
24    Eina_Accessor accessor;
25 
26    Eina_Accessor *real_accessor;
27    const Evas_Object *box;
28 };
29 
30 #define SIG_CHILD_ADDED "child,added"
31 #define SIG_CHILD_REMOVED "child,removed"
32 
33 static const Evas_Smart_Cb_Description _signals[] =
34 {
35    {SIG_CHILD_ADDED, ""},
36    {SIG_CHILD_REMOVED, ""},
37    {NULL, NULL}
38 };
39 
40 
41 static void _sizing_eval(Evas_Object *obj);
42 
43 #define EVAS_OBJECT_BOX_DATA_GET(o, ptr) \
44    Evas_Object_Box_Data *ptr = efl_data_scope_get(o, MY_CLASS)
45 
46 #define EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, ptr)                      \
47    EVAS_OBJECT_BOX_DATA_GET(o, ptr);                                    \
48 if (!ptr)                                                               \
49 {                                                                       \
50    ERR("No widget data for object %p (%s)",                            \
51         o, evas_object_type_get(o));                                    \
52    fflush(stderr);                                                      \
53    return;                                                              \
54 }
55 
56 #define EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, ptr, val)             \
57    EVAS_OBJECT_BOX_DATA_GET(o, ptr);                                    \
58 if (!ptr)                                                               \
59 {                                                                       \
60    ERR("No widget data for object %p (%s)",                            \
61         o, evas_object_type_get(o));                                    \
62    fflush(stderr);                                                      \
63    return val;                                                          \
64 }
65 
66 static Eina_Bool
_evas_object_box_iterator_next(Evas_Object_Box_Iterator * it,void ** data)67 _evas_object_box_iterator_next(Evas_Object_Box_Iterator *it, void **data)
68 {
69    Evas_Object_Box_Option *opt;
70 
71    if (!eina_iterator_next(it->real_iterator, (void **)&opt))
72      return EINA_FALSE;
73    if (data) *data = opt->obj;
74    return EINA_TRUE;
75 }
76 
77 static Evas_Object *
_evas_object_box_iterator_get_container(Evas_Object_Box_Iterator * it)78 _evas_object_box_iterator_get_container(Evas_Object_Box_Iterator *it)
79 {
80    return (Evas_Object *)it->box;
81 }
82 
83 static void
_evas_object_box_iterator_free(Evas_Object_Box_Iterator * it)84 _evas_object_box_iterator_free(Evas_Object_Box_Iterator *it)
85 {
86    eina_iterator_free(it->real_iterator);
87    free(it);
88 }
89 
90 static Eina_Bool
_evas_object_box_accessor_get_at(Evas_Object_Box_Accessor * it,unsigned int idx,void ** data)91 _evas_object_box_accessor_get_at(Evas_Object_Box_Accessor *it, unsigned int idx, void **data)
92 {
93    Evas_Object_Box_Option *opt = NULL;
94 
95    if (!eina_accessor_data_get(it->real_accessor, idx, (void *)&opt))
96      return EINA_FALSE;
97    if (data) *data = opt->obj;
98    return EINA_TRUE;
99 }
100 
101 static Evas_Object *
_evas_object_box_accessor_get_container(Evas_Object_Box_Accessor * it)102 _evas_object_box_accessor_get_container(Evas_Object_Box_Accessor *it)
103 {
104    return (Evas_Object *)it->box;
105 }
106 
107 static void
_evas_object_box_accessor_free(Evas_Object_Box_Accessor * it)108 _evas_object_box_accessor_free(Evas_Object_Box_Accessor *it)
109 {
110    eina_accessor_free(it->real_accessor);
111    free(it);
112 }
113 
114 static void
_on_child_resize(void * data,const Efl_Event * event EINA_UNUSED)115 _on_child_resize(void *data, const Efl_Event *event EINA_UNUSED)
116 {
117    Evas_Object *box = data;
118    EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(box, priv);
119    if (!priv->layouting) evas_object_smart_changed(box);
120 }
121 
122 static void
_on_child_invalidate(void * data,const Efl_Event * event)123 _on_child_invalidate(void *data, const Efl_Event *event)
124 {
125    Evas_Object *box = data;
126 
127    Evas_Object *ret = NULL;
128    ret = evas_obj_box_internal_remove(box, event->object);
129    if (!ret)
130      ERR("child removal failed");
131    evas_object_smart_changed(box);
132 }
133 
134 static void
_on_child_hints_changed(void * data,const Efl_Event * event EINA_UNUSED)135 _on_child_hints_changed(void *data, const Efl_Event *event EINA_UNUSED)
136 {
137    Evas_Object *box = data;
138    EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(box, priv);
139 // XXX: this breaks box repacking in elementary. widgets DEPEND on being able
140 // to change their hints evenr WHILE being laid out. so comment this out.
141 //   if (!priv->layouting)
142      evas_object_smart_changed(box);
143 }
144 
145 static void
_on_hints_changed(void * data EINA_UNUSED,Evas * evas EINA_UNUSED,Evas_Object * o,void * einfo EINA_UNUSED)146 _on_hints_changed(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *o , void *einfo EINA_UNUSED)
147 {
148    _sizing_eval(o);
149 }
150 
151 static Evas_Object_Box_Option *
_evas_object_box_option_new(Evas_Object * o,Evas_Object_Box_Data * priv EINA_UNUSED,Evas_Object * child)152 _evas_object_box_option_new(Evas_Object *o, Evas_Object_Box_Data *priv EINA_UNUSED, Evas_Object *child)
153 {
154    Evas_Object_Box_Option *opt = NULL;
155 
156    opt = evas_obj_box_internal_option_new(o, child);
157    if (!opt)
158      {
159         ERR("option_new failed");
160         return NULL;
161      }
162 
163    return opt;
164 }
165 
166 EFL_CALLBACKS_ARRAY_DEFINE(evas_object_box_callbacks,
167   { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _on_child_resize },
168   { EFL_EVENT_INVALIDATE, _on_child_invalidate },
169   { EFL_GFX_ENTITY_EVENT_HINTS_CHANGED, _on_child_hints_changed }
170 );
171 
172 static void
_evas_object_box_child_callbacks_unregister(Evas_Object * obj,Evas_Object * parent)173 _evas_object_box_child_callbacks_unregister(Evas_Object *obj, Evas_Object *parent)
174 {
175    efl_event_callback_array_del(obj, evas_object_box_callbacks(), parent);
176 }
177 
178 static Evas_Object_Box_Option *
_evas_object_box_option_callbacks_register(Evas_Object * o,Evas_Object_Box_Data * priv EINA_UNUSED,Evas_Object_Box_Option * opt)179 _evas_object_box_option_callbacks_register(Evas_Object *o, Evas_Object_Box_Data *priv EINA_UNUSED, Evas_Object_Box_Option *opt)
180 {
181    Evas_Object *obj = opt->obj;
182 
183    efl_event_callback_array_add(obj, evas_object_box_callbacks(), o);
184 
185    return opt;
186 }
187 
188 EOLIAN static Evas_Object_Box_Option *
_evas_box_internal_option_new(Eo * o EINA_UNUSED,Evas_Object_Box_Data * _pd EINA_UNUSED,Evas_Object * child)189 _evas_box_internal_option_new(Eo *o EINA_UNUSED, Evas_Object_Box_Data *_pd EINA_UNUSED, Evas_Object *child)
190 {
191    Evas_Object_Box_Option *opt;
192    Evas_Object *parent;
193 
194    parent = evas_object_smart_parent_get(child);
195    if (parent && efl_isa(parent, MY_CLASS))
196      CRI("Adding object to box which currently belongs to different box");
197 
198    opt = (Evas_Object_Box_Option *)malloc(sizeof(*opt));
199    if (!opt)
200      return NULL;
201 
202    opt->obj = child;
203 
204    return opt;
205 }
206 
207 EOLIAN static void
_evas_box_internal_option_free(Eo * o EINA_UNUSED,Evas_Object_Box_Data * _pd EINA_UNUSED,Evas_Object_Box_Option * opt)208 _evas_box_internal_option_free(Eo *o EINA_UNUSED, Evas_Object_Box_Data *_pd EINA_UNUSED, Evas_Object_Box_Option *opt)
209 {
210    free(opt);
211 }
212 
213 EOLIAN static Evas_Object_Box_Option*
_evas_box_internal_append(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child)214 _evas_box_internal_append(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child)
215 {
216    Evas_Object_Box_Option *opt;
217 
218    opt = _evas_object_box_option_new(o, priv, child);
219    if (!opt)
220      return NULL;
221 
222    priv->children = eina_list_append(priv->children, opt);
223    priv->children_changed = EINA_TRUE;
224    efl_event_callback_legacy_call(o, EVAS_BOX_EVENT_CHILD_ADDED, opt);
225 
226    return opt;
227 }
228 
229 EOLIAN static Evas_Object_Box_Option *
_evas_box_internal_prepend(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child)230 _evas_box_internal_prepend(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child)
231 {
232    Evas_Object_Box_Option *opt;
233 
234    opt = _evas_object_box_option_new(o, priv, child);
235    if (!opt)
236      return NULL;
237 
238    priv->children = eina_list_prepend(priv->children, opt);
239    priv->children_changed = EINA_TRUE;
240    efl_event_callback_legacy_call(o, EVAS_BOX_EVENT_CHILD_ADDED, opt);
241 
242    return opt;
243 }
244 
245 EOLIAN static Evas_Object_Box_Option *
_evas_box_internal_insert_before(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child,const Evas_Object * reference)246 _evas_box_internal_insert_before(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child, const Evas_Object *reference)
247 {
248    Eina_List *l;
249    Evas_Object_Box_Option *opt;
250 
251    EINA_LIST_FOREACH(priv->children, l, opt)
252      {
253         if (opt->obj == reference)
254           {
255              Evas_Object_Box_Option *new_opt;
256 
257              new_opt = _evas_object_box_option_new(o, priv, child);
258              if (!new_opt)
259                 return NULL;
260 
261              priv->children = eina_list_prepend_relative
262                 (priv->children, new_opt, opt);
263              priv->children_changed = EINA_TRUE;
264              efl_event_callback_legacy_call(o, EVAS_BOX_EVENT_CHILD_ADDED, new_opt);
265              return new_opt;
266           }
267      }
268 
269    return opt;
270 }
271 
272 EOLIAN static Evas_Object_Box_Option *
_evas_box_internal_insert_after(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child,const Evas_Object * reference)273 _evas_box_internal_insert_after(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child, const Evas_Object *reference)
274 {
275    Eina_List *l;
276    Evas_Object_Box_Option *opt;
277 
278    EINA_LIST_FOREACH(priv->children, l, opt)
279      {
280         if (opt->obj == reference)
281           {
282              Evas_Object_Box_Option *new_opt;
283 
284              new_opt = _evas_object_box_option_new(o, priv, child);
285              if (!new_opt)
286                 return NULL;
287 
288              priv->children = eina_list_append_relative
289                 (priv->children, new_opt, opt);
290              priv->children_changed = EINA_TRUE;
291              efl_event_callback_legacy_call(o, EVAS_BOX_EVENT_CHILD_ADDED, new_opt);
292              return new_opt;
293           }
294      }
295    return opt;
296 }
297 
298 EOLIAN static Evas_Object_Box_Option *
_evas_box_internal_insert_at(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child,unsigned int pos)299 _evas_box_internal_insert_at(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child, unsigned int pos)
300 {
301    Eina_List *l;
302    unsigned int i;
303 
304    if ((pos == 0) && (eina_list_count(priv->children) == 0))
305      {
306         Evas_Object_Box_Option *new_opt;
307 
308         new_opt = _evas_object_box_option_new(o, priv, child);
309         if (!new_opt)
310            return NULL;
311 
312         priv->children = eina_list_prepend(priv->children, new_opt);
313         priv->children_changed = EINA_TRUE;
314         efl_event_callback_legacy_call(o, EVAS_BOX_EVENT_CHILD_ADDED, new_opt);
315         return new_opt;
316      }
317 
318    for (l = priv->children, i = 0; l; l = l->next, i++)
319      {
320         Evas_Object_Box_Option *opt = l->data;
321 
322         if (i == pos)
323           {
324              Evas_Object_Box_Option *new_opt;
325 
326              new_opt = _evas_object_box_option_new(o, priv, child);
327              if (!new_opt)
328                 return NULL;
329 
330              priv->children = eina_list_prepend_relative
331                 (priv->children, new_opt, opt);
332              priv->children_changed = EINA_TRUE;
333              efl_event_callback_legacy_call(o, EVAS_BOX_EVENT_CHILD_ADDED, new_opt);
334              return new_opt;
335           }
336      }
337    return NULL;
338 }
339 
340 EOLIAN static Evas_Object *
_evas_box_internal_remove(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child)341 _evas_box_internal_remove(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child)
342 {
343    Evas_Object_Box_Option *opt;
344    Eina_List *l;
345 
346    EINA_LIST_FOREACH(priv->children, l, opt)
347      {
348         Evas_Object *obj = opt->obj;
349 
350         if (obj == child)
351           {
352              priv->children = eina_list_remove(priv->children, opt);
353              evas_obj_box_internal_option_free(o, opt);
354              priv->children_changed = EINA_TRUE;
355              efl_event_callback_legacy_call(o, EVAS_BOX_EVENT_CHILD_REMOVED, obj);
356 
357              return obj;
358           }
359      }
360    return NULL;
361 }
362 
363 EOLIAN static Evas_Object *
_evas_box_internal_remove_at(Eo * o,Evas_Object_Box_Data * priv,unsigned int pos)364 _evas_box_internal_remove_at(Eo *o, Evas_Object_Box_Data *priv, unsigned int pos)
365 {
366    Eina_List *node;
367    Evas_Object_Box_Option *opt;
368    Evas_Object *obj;
369 
370    node = eina_list_nth_list(priv->children, pos);
371    if (!node)
372      {
373         ERR("No item to be removed at position %d", pos);
374         return NULL;
375      }
376 
377    opt = node->data;
378    obj = opt->obj;
379 
380    priv->children = eina_list_remove_list(priv->children, node);
381    evas_obj_box_internal_option_free(o, opt);
382    priv->children_changed = EINA_TRUE;
383    efl_event_callback_legacy_call(o, EVAS_BOX_EVENT_CHILD_REMOVED, obj);
384    return obj;
385 }
386 
387 EOLIAN static void
_evas_box_efl_canvas_group_group_add(Eo * eo_obj,Evas_Object_Box_Data * priv)388 _evas_box_efl_canvas_group_group_add(Eo *eo_obj, Evas_Object_Box_Data *priv)
389 {
390    Evas_Object_Smart_Clipped_Data *cso;
391 
392    efl_canvas_group_add(efl_super(eo_obj, MY_CLASS));
393 
394    evas_object_event_callback_add
395      (eo_obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_hints_changed, eo_obj);
396    priv->children = NULL;
397    priv->align.h = 0.5;
398    priv->align.v = 0.5;
399    priv->pad.h = 0;
400    priv->pad.v = 0;
401    priv->layout.cb = evas_object_box_layout_horizontal;
402    priv->layout.data = NULL;
403    priv->layout.free_data = NULL;
404 
405    // make sure evas box smart data is fully initialized and set (for legacy)
406    // this assumes only box and smart clipped access the smart data
407    cso = evas_object_smart_data_get(eo_obj);
408    priv->base = *cso;
409    evas_object_smart_data_set(eo_obj, priv);
410 }
411 
412 EOLIAN static void
_evas_box_efl_canvas_group_group_del(Eo * o,Evas_Object_Box_Data * priv)413 _evas_box_efl_canvas_group_group_del(Eo *o, Evas_Object_Box_Data *priv)
414 {
415    while (priv->children)
416      {
417         Evas_Object_Box_Option *opt = eina_list_data_get(priv->children);
418 
419         _evas_object_box_child_callbacks_unregister(opt->obj, o);
420         evas_obj_box_internal_option_free(o, opt);
421         priv->children = eina_list_remove_list(priv->children, priv->children);
422      }
423 
424 
425    if (priv->layout.data && priv->layout.free_data)
426      priv->layout.free_data(priv->layout.data);
427 
428    efl_canvas_group_del(efl_super(o, MY_CLASS));
429 }
430 
431 EOLIAN static void
_evas_box_efl_gfx_entity_size_set(Eo * o,Evas_Object_Box_Data * _pd EINA_UNUSED,Eina_Size2D sz)432 _evas_box_efl_gfx_entity_size_set(Eo *o, Evas_Object_Box_Data *_pd EINA_UNUSED, Eina_Size2D sz)
433 {
434    if (_evas_object_intercept_call(o, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
435      return;
436 
437    efl_gfx_entity_size_set(efl_super(o, MY_CLASS), sz);
438    evas_object_smart_changed(o);
439 }
440 
441 EOLIAN static void
_evas_box_efl_gfx_entity_position_set(Eo * o,Evas_Object_Box_Data * _pd EINA_UNUSED,Eina_Position2D pos)442 _evas_box_efl_gfx_entity_position_set(Eo *o, Evas_Object_Box_Data *_pd EINA_UNUSED, Eina_Position2D pos)
443 {
444    Evas_Object_Smart_Clipped_Data *cso = evas_object_smart_data_get(o);
445    if (_evas_object_intercept_call(o, EVAS_OBJECT_INTERCEPT_CB_MOVE , 0, pos.x, pos.y))
446      return;
447 
448    if (!evas_object_static_clip_get(cso->clipper))
449      efl_gfx_entity_position_set(cso->clipper, pos);
450 
451    /* this skips the call to _evas_object_smart_clipped_smart_move_internal
452     * since box internals will automatically recalc all the child positions
453     * at a later point
454     */
455    efl_gfx_entity_position_set(efl_super(o, EFL_CANVAS_GROUP_CLASS), pos);
456    evas_object_smart_changed(o);
457 }
458 
459 EOLIAN static void
_evas_box_efl_canvas_group_group_calculate(Eo * o,Evas_Object_Box_Data * priv)460 _evas_box_efl_canvas_group_group_calculate(Eo *o, Evas_Object_Box_Data *priv)
461 {
462    if (priv->layout.cb)
463        {
464            Evas *e;
465 
466            e = evas_object_evas_get(o);
467            evas_event_freeze(e);
468 
469            priv->layouting = 1;
470            priv->layout.cb(o, priv, priv->layout.data);
471            priv->layouting = 0;
472            priv->children_changed = EINA_FALSE;
473 
474            evas_event_thaw(e);
475        }
476    else
477      ERR("No layout function set for %p box.", o);
478 }
479 
480 EAPI Evas_Object *
evas_object_box_add(Evas * evas)481 evas_object_box_add(Evas *evas)
482 {
483    evas = evas_find(evas);
484    EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(evas, EVAS_CANVAS_CLASS), NULL);
485    return efl_add(MY_CLASS, evas, efl_canvas_object_legacy_ctor(efl_added));
486 }
487 
488 EOLIAN static Eo *
_evas_box_efl_object_constructor(Eo * obj,Evas_Object_Box_Data * class_data EINA_UNUSED)489 _evas_box_efl_object_constructor(Eo *obj, Evas_Object_Box_Data *class_data EINA_UNUSED)
490 {
491    efl_canvas_group_clipped_set(obj, EINA_TRUE);
492    obj = efl_constructor(efl_super(obj, MY_CLASS));
493    evas_object_smart_callbacks_descriptions_set(obj, _signals);
494    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
495 
496    return obj;
497 }
498 
499 EOLIAN static Evas_Object*
_evas_box_add_to(Eo * parent,Evas_Object_Box_Data * _pd EINA_UNUSED)500 _evas_box_add_to(Eo *parent, Evas_Object_Box_Data *_pd EINA_UNUSED)
501 {
502    Evas *evas;
503    Evas_Object *o;
504 
505    evas = evas_object_evas_get(parent);
506    o = evas_object_box_add(evas);
507    evas_object_smart_member_add(o, parent);
508 
509    return o;
510 }
511 
512 EAPI void
evas_object_box_smart_set(Evas_Object_Box_Api * api EINA_UNUSED)513 evas_object_box_smart_set(Evas_Object_Box_Api *api EINA_UNUSED)
514 {
515    return;
516 }
517 
518 EAPI const Evas_Object_Box_Api *
evas_object_box_smart_class_get(void)519 evas_object_box_smart_class_get(void)
520 {
521    return NULL;
522 }
523 
524 EOLIAN static void
_evas_box_layout_set(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Layout cb,const void * data,void (* free_data)(void * data))525 _evas_box_layout_set(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Layout cb, const void *data, void (*free_data)(void *data))
526 {
527    if ((priv->layout.cb == cb) && (priv->layout.data == data) &&
528        (priv->layout.free_data == free_data))
529      return;
530 
531    if (priv->layout.data && priv->layout.free_data)
532      priv->layout.free_data(priv->layout.data);
533 
534    priv->layout.cb = cb;
535    priv->layout.data = (void *)data;
536    priv->layout.free_data = free_data;
537    evas_object_smart_changed(o);
538 }
539 
540 static void
_fixed_point_divide_and_decompose_integer(int dividend,int divisor,int * int_part,int * frac_part)541 _fixed_point_divide_and_decompose_integer(int dividend, int divisor, int *int_part, int *frac_part)
542 {
543    int quotient = ((long long)dividend << 16) / divisor;
544    *frac_part = quotient & 0xffff;
545    *int_part = quotient >> 16;
546 }
547 
548 static void
_layout_dimension_change_min_max_cell_bound(int dim,int * new_dim,int min_d,int max_d,int cell_sz)549 _layout_dimension_change_min_max_cell_bound(int dim, int *new_dim, int min_d, int max_d, int cell_sz)
550 {
551    if (dim > cell_sz)
552      {
553         if ((min_d != 0) && (cell_sz < min_d))
554           *new_dim = min_d;
555         else
556           *new_dim = cell_sz;
557      }
558    else
559      {
560         if ((max_d != -1) && (cell_sz > max_d))
561           *new_dim = max_d;
562         else
563           *new_dim = cell_sz;
564      }
565 }
566 
567 static void
_layout_set_offset_and_expand_dimension_space_max_bounded(int dim,int * new_dim,int space_sz,int max_dim,int * offset,double align,int pad_before,int pad_after)568 _layout_set_offset_and_expand_dimension_space_max_bounded(int dim, int *new_dim, int space_sz, int max_dim, int *offset, double align, int pad_before, int pad_after)
569 {
570    if (align >= 0.0)
571      {
572         *new_dim = dim;
573         *offset = (space_sz - (dim + pad_before + pad_after)) * align
574            + pad_before;
575      }
576    else
577      {
578         if ((max_dim != -1) && (space_sz > max_dim))
579           {
580              *new_dim = max_dim;
581              *offset = (space_sz - (max_dim + pad_before + pad_after)) * 0.5
582                 + pad_before;
583           }
584         else
585           {
586              *new_dim = space_sz;
587              *offset = 0;
588           }
589      }
590 }
591 
592 static void
_layout_set_offset_and_change_dimension_min_max_cell_bounded(int dim,int * new_dim,int min_dim,int max_dim,int cell_sz,int * offset,double align,int pad_before,int pad_after)593 _layout_set_offset_and_change_dimension_min_max_cell_bounded(int dim, int *new_dim, int min_dim, int max_dim, int cell_sz, int *offset, double align, int pad_before, int pad_after)
594 {
595    if (align >= 0.0)
596      {
597         *new_dim = dim;
598         *offset =
599            (cell_sz - (dim + pad_before + pad_after)) * align + pad_before;
600      }
601    else
602      {
603         *offset = pad_before;
604         _layout_dimension_change_min_max_cell_bound
605            (dim, new_dim, min_dim, max_dim, cell_sz - pad_before - pad_after);
606      }
607 }
608 
609 static void
_sizing_eval(Evas_Object * obj)610 _sizing_eval(Evas_Object *obj)
611 {
612    Evas_Coord minw, minh, maxw, maxh;
613    Evas_Coord w, h;
614 
615    evas_object_size_hint_combined_min_get(obj, &minw, &minh);
616    evas_object_size_hint_max_get(obj, &maxw, &maxh);
617    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
618 
619    if (w < minw) w = minw;
620    if (h < minh) h = minh;
621    if ((maxw >= 0) && (w > maxw)) w = maxw;
622    if ((maxh >= 0) && (h > maxh)) h = maxh;
623 
624    evas_object_resize(obj, w, h);
625 }
626 
627 static int
_evas_object_box_layout_horizontal_weight_apply(Evas_Object_Box_Data * priv,Evas_Object_Box_Option ** objects,int n_objects,int remaining,double weight_total)628 _evas_object_box_layout_horizontal_weight_apply(Evas_Object_Box_Data *priv, Evas_Object_Box_Option **objects, int n_objects, int remaining, double weight_total)
629 {
630    int rem_diff = 0;
631    int i;
632 
633    for (i = 0; i < n_objects; i++)
634      {
635         Evas_Object_Box_Option *opt = objects[i];
636         Evas_Object *o = opt->obj;
637         int h;
638 
639         evas_object_geometry_get(o, NULL, NULL, NULL, &h);
640 
641         if (remaining <= 0)
642           {
643              int min_w;
644 
645              evas_object_size_hint_combined_min_get(o, &min_w, NULL);
646              evas_object_resize(o, min_w, h);
647           }
648         else
649           {
650              double normal_weight, weight_x;
651              int target_size;
652              int max_w;
653 
654              evas_object_size_hint_weight_get(o, &weight_x, NULL);
655              normal_weight = weight_x / weight_total;
656              target_size = (int)((double)remaining * normal_weight);
657 
658              evas_object_size_hint_max_get(o, &max_w, NULL);
659              if ((max_w != -1) && (target_size > max_w))
660                {
661                   evas_object_resize(o, max_w, h);
662                   rem_diff += max_w;
663                   objects[i] = objects[n_objects - 1];
664                   weight_total -= weight_x;
665                   n_objects--;
666                   return _evas_object_box_layout_horizontal_weight_apply
667                      (priv, objects, n_objects, remaining - rem_diff,
668                       weight_total);
669                }
670              else
671                {
672                   evas_object_resize(o, target_size, h);
673                   rem_diff += target_size;
674                }
675           }
676      }
677 
678    return remaining - rem_diff;
679 }
680 
681 EOLIAN static void
_evas_box_layout_horizontal(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)682 _evas_box_layout_horizontal(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
683 {
684    int pad_inc = 0, sub_pixel = 0;
685    int req_w, global_pad, remaining, top_h = 0, totalminw = 0;
686    double weight_total = 0.0;
687    int weight_use = 0;
688    int x, y, w, h;
689    int n_children;
690    Evas_Object_Box_Option *opt;
691    Evas_Object_Box_Option **objects;
692    Eina_List *l;
693 
694    n_children = eina_list_count(priv->children);
695    if (!n_children)
696      {
697         evas_object_size_hint_min_set(o, 0, 0);
698         return;
699      }
700 
701    objects = (Evas_Object_Box_Option **)alloca(sizeof(Evas_Object_Box_Option *) * n_children);
702    if (!objects)
703      {
704         evas_object_size_hint_min_set(o, 0, 0);
705         return;
706      }
707 
708    evas_object_geometry_get(o, &x, &y, &w, &h);
709    global_pad = priv->pad.h;
710    req_w = global_pad * (n_children - 1);
711    totalminw = req_w;
712 
713    EINA_LIST_FOREACH(priv->children, l, opt)
714      {
715         int padding_l, padding_r;
716         double weight_x;
717         int minw;
718 
719         _sizing_eval(opt->obj);
720         evas_object_size_hint_weight_get(opt->obj, &weight_x, NULL);
721         evas_object_size_hint_padding_get
722            (opt->obj, &padding_l, &padding_r, NULL, NULL);
723         req_w += padding_l + padding_r;
724 
725         evas_object_size_hint_combined_min_get(opt->obj, &minw, NULL);
726         if (minw > 0) totalminw += minw + padding_l + padding_r;
727         if (EINA_DBL_EQ(weight_x, 0.0))
728           {
729              if (minw > 0) req_w += minw;
730           }
731         else
732           {
733              objects[weight_use] = opt;
734              weight_use++;
735              weight_total += weight_x;
736           }
737      }
738 
739    remaining = w - req_w;
740 
741    if (weight_use)
742      remaining = _evas_object_box_layout_horizontal_weight_apply
743        (priv, objects, weight_use, remaining, weight_total);
744 
745    if (priv->align.h >= 0.0)
746      x += remaining * priv->align.h;
747    else if (n_children == 1)
748      x += remaining / 2;
749    else
750      { /* justified */
751         _fixed_point_divide_and_decompose_integer
752             (remaining, n_children - 1, &global_pad, &pad_inc);
753         global_pad += priv->pad.h;
754      }
755 
756    EINA_LIST_FOREACH(priv->children, l, opt)
757      {
758         int child_w, child_h, max_h, new_h, off_x, off_y, minw, minh;
759         int padding_l, padding_r, padding_t, padding_b;
760         double align_y;
761 
762         evas_object_size_hint_align_get(opt->obj, NULL, &align_y);
763         evas_object_size_hint_padding_get
764            (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
765         evas_object_size_hint_max_get(opt->obj, NULL, &max_h);
766 
767         evas_object_size_hint_combined_min_get(opt->obj, &minw, &minh);
768         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
769 
770         off_x = padding_l;
771         new_h = minh;
772         if (new_h > top_h) top_h = new_h;
773 
774         _layout_set_offset_and_expand_dimension_space_max_bounded
775            (child_h, &new_h, h, max_h, &off_y, align_y, padding_t, padding_b);
776 
777         if (new_h != child_h)
778           evas_object_resize(opt->obj, child_w, new_h);
779         evas_object_move(opt->obj, x + off_x, y + off_y);
780 
781         x += child_w + padding_l + padding_r + global_pad;
782         sub_pixel += pad_inc;
783         if (sub_pixel >= 1 << 16)
784           {
785              x++;
786              sub_pixel -= 1 << 16;
787           }
788      }
789 
790    evas_object_size_hint_min_set(o, totalminw, top_h);
791 }
792 
793 static int
_evas_object_box_layout_vertical_weight_apply(Evas_Object_Box_Data * priv,Evas_Object_Box_Option ** objects,int n_objects,int remaining,double weight_total)794 _evas_object_box_layout_vertical_weight_apply(Evas_Object_Box_Data *priv, Evas_Object_Box_Option **objects, int n_objects, int remaining, double weight_total)
795 {
796    int rem_diff = 0;
797    int i;
798 
799    for (i = 0; i < n_objects; i++)
800      {
801         Evas_Object_Box_Option *opt = objects[i];
802         Evas_Object *o = opt->obj;
803         int w;
804 
805         evas_object_geometry_get(o, NULL, NULL, &w, NULL);
806 
807         if (remaining <= 0)
808           {
809              int min_h;
810 
811              evas_object_size_hint_combined_min_get(o, NULL, &min_h);
812              evas_object_resize(o, w, min_h);
813           }
814         else
815           {
816              double normal_weight, weight_y;
817              int target_size;
818              int max_h;
819 
820              evas_object_size_hint_weight_get(o, NULL, &weight_y);
821              normal_weight = weight_y / weight_total;
822              target_size = (int)((double)remaining * normal_weight);
823 
824              evas_object_size_hint_max_get(o, NULL, &max_h);
825              if ((max_h != -1) && (target_size > max_h))
826                {
827                   evas_object_resize(o, w, max_h);
828                   rem_diff += max_h;
829                   objects[i] = objects[n_objects - 1];
830                   weight_total -= weight_y;
831                   n_objects--;
832                   return _evas_object_box_layout_vertical_weight_apply
833                      (priv, objects, n_objects, remaining - rem_diff,
834                       weight_total);
835                }
836              else
837                {
838                   evas_object_resize(o, w, target_size);
839                   rem_diff += target_size;
840                }
841           }
842      }
843 
844    return remaining - rem_diff;
845 }
846 
847 EOLIAN static void
_evas_box_layout_vertical(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)848 _evas_box_layout_vertical(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
849 {
850    int pad_inc = 0, sub_pixel = 0;
851    int req_h, global_pad, remaining, top_w = 0, totalminh = 0;
852    double weight_total = 0.0;
853    int weight_use = 0;
854    int x, y, w, h;
855    int n_children;
856    Evas_Object_Box_Option *opt;
857    Evas_Object_Box_Option **objects;
858    Eina_List *l;
859 
860    n_children = eina_list_count(priv->children);
861    if (!n_children)
862      {
863         evas_object_size_hint_min_set(o, 0, 0);
864         return;
865      }
866 
867    objects = (Evas_Object_Box_Option **)alloca(sizeof(Evas_Object_Box_Option *) * n_children);
868    if (!objects)
869      {
870         evas_object_size_hint_min_set(o, 0, 0);
871         return;
872      }
873 
874    evas_object_geometry_get(o, &x, &y, &w, &h);
875    global_pad = priv->pad.v;
876    req_h = global_pad * (n_children - 1);
877    totalminh = req_h;
878 
879    EINA_LIST_FOREACH(priv->children, l, opt)
880      {
881         int padding_t, padding_b;
882         double weight_y;
883         int minh;
884 
885         _sizing_eval(opt->obj);
886         evas_object_size_hint_weight_get(opt->obj, NULL, &weight_y);
887         evas_object_size_hint_padding_get
888            (opt->obj, NULL, NULL, &padding_t, &padding_b);
889         req_h += padding_t + padding_b;
890 
891         evas_object_size_hint_combined_min_get(opt->obj, NULL, &minh);
892         if (minh > 0) totalminh += minh + padding_t + padding_b;
893         if (EINA_DBL_EQ(weight_y, 0.0))
894           {
895              if (minh > 0) req_h += minh;
896           }
897         else
898           {
899              objects[weight_use] = opt;
900              weight_use++;
901              weight_total += weight_y;
902           }
903      }
904 
905    remaining = h - req_h;
906 
907    if (weight_use)
908      remaining = _evas_object_box_layout_vertical_weight_apply
909        (priv, objects, weight_use, remaining, weight_total);
910 
911    if (priv->align.v >= 0.0)
912      y += remaining * priv->align.v;
913    else if (n_children == 1)
914      y += remaining / 2;
915    else
916      { /* justified */
917         _fixed_point_divide_and_decompose_integer
918            (remaining, n_children - 1, &global_pad, &pad_inc);
919         global_pad += priv->pad.v;
920      }
921 
922    EINA_LIST_FOREACH(priv->children, l, opt)
923      {
924         int child_w, child_h, max_w, new_w, off_x, off_y, minw, minh;
925         int padding_l, padding_r, padding_t, padding_b;
926         double align_x;
927 
928         evas_object_size_hint_align_get(opt->obj, &align_x, NULL);
929         evas_object_size_hint_padding_get
930            (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
931         evas_object_size_hint_max_get(opt->obj, &max_w, NULL);
932 
933         evas_object_size_hint_combined_min_get(opt->obj, &minw, &minh);
934         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
935 
936         off_y = padding_t;
937         new_w = minw;
938 
939         _layout_set_offset_and_expand_dimension_space_max_bounded
940            (child_w, &new_w, w, max_w, &off_x, align_x, padding_l, padding_r);
941 
942         if (new_w > top_w) top_w = new_w;
943 
944         if (new_w != child_w)
945           evas_object_resize(opt->obj, new_w, child_h);
946         evas_object_move(opt->obj, x + off_x, y + off_y);
947 
948         y += child_h + padding_t + padding_b + global_pad;
949         sub_pixel += pad_inc;
950         if (sub_pixel >= 1 << 16)
951           {
952              y++;
953              sub_pixel -= 1 << 16;
954           }
955      }
956 
957    evas_object_size_hint_min_set(o, top_w, totalminh);
958 }
959 
960 EOLIAN static void
_evas_box_layout_homogeneous_horizontal(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)961 _evas_box_layout_homogeneous_horizontal(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
962 {
963    int cell_sz, share, inc;
964    int sub_pixel = 0;
965    int x, y, w, h;
966    int n_children;
967    Evas_Object_Box_Option *opt;
968    Eina_List *l;
969 
970    n_children = eina_list_count(priv->children);
971    if (!n_children)
972      {
973         evas_object_size_hint_min_set(o, 0, 0);
974         return;
975      }
976 
977    evas_object_geometry_get(o, &x, &y, &w, &h);
978 
979    share = w - priv->pad.h * (n_children - 1);
980    _fixed_point_divide_and_decompose_integer
981      (share, n_children, &cell_sz, &inc);
982 
983    EINA_LIST_FOREACH(priv->children, l, opt)
984      {
985         int child_w, child_h, max_h, min_w, max_w, new_w, new_h, off_x, off_y;
986         int padding_l, padding_r, padding_t, padding_b;
987         double align_x, align_y;
988 
989         evas_object_size_hint_align_get(opt->obj, &align_x, &align_y);
990         evas_object_size_hint_padding_get
991            (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
992         evas_object_size_hint_max_get(opt->obj, &max_w, &max_h);
993         evas_object_size_hint_combined_min_get(opt->obj, &min_w, NULL);
994 
995         _sizing_eval(opt->obj);
996         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
997 
998         new_w = child_w;
999         new_h = child_h;
1000 
1001         _layout_set_offset_and_expand_dimension_space_max_bounded
1002            (child_h, &new_h, h, max_h, &off_y, align_y, padding_t, padding_b);
1003 
1004         _layout_set_offset_and_change_dimension_min_max_cell_bounded
1005            (child_w, &new_w, min_w, max_w, cell_sz, &off_x, align_x,
1006             padding_l, padding_r);
1007 
1008         if ((new_w != child_w) || (new_h != child_h))
1009           evas_object_resize(opt->obj, new_w, new_h);
1010         evas_object_move(opt->obj, x + off_x, y + off_y);
1011 
1012         x += cell_sz + priv->pad.h;
1013         sub_pixel += inc;
1014         if (sub_pixel >= 1 << 16)
1015           {
1016              x++;
1017              sub_pixel -= 1 << 16;
1018           }
1019      }
1020 
1021    evas_object_size_hint_min_set(o, w, h);
1022 }
1023 
1024 EOLIAN static void
_evas_box_layout_homogeneous_vertical(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)1025 _evas_box_layout_homogeneous_vertical(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
1026 {
1027    int cell_sz, share, inc;
1028    int sub_pixel = 0;
1029    int x, y, w, h;
1030    int n_children;
1031    Evas_Object_Box_Option *opt;
1032    Eina_List *l;
1033 
1034    n_children = eina_list_count(priv->children);
1035    if (!n_children)
1036      {
1037         evas_object_size_hint_min_set(o, 0, 0);
1038         return;
1039      }
1040 
1041    evas_object_geometry_get(o, &x, &y, &w, &h);
1042 
1043    share = h - priv->pad.v * (n_children - 1);
1044    _fixed_point_divide_and_decompose_integer
1045      (share, n_children, &cell_sz, &inc);
1046 
1047    EINA_LIST_FOREACH(priv->children, l, opt)
1048      {
1049         int child_w, child_h, max_w, min_h, max_h, new_w, new_h, off_x, off_y;
1050         int padding_l, padding_r, padding_t, padding_b;
1051         double align_x, align_y;
1052 
1053         evas_object_size_hint_align_get(opt->obj, &align_x, &align_y);
1054         evas_object_size_hint_padding_get
1055            (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1056         evas_object_size_hint_max_get(opt->obj, &max_w, &max_h);
1057         evas_object_size_hint_combined_min_get(opt->obj, NULL, &min_h);
1058 
1059         _sizing_eval(opt->obj);
1060         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1061         new_w = child_w;
1062         new_h = child_h;
1063 
1064         _layout_set_offset_and_expand_dimension_space_max_bounded
1065            (child_w, &new_w, w, max_w, &off_x, align_x, padding_l, padding_r);
1066 
1067         _layout_set_offset_and_change_dimension_min_max_cell_bounded
1068            (child_h, &new_h, min_h, max_h, cell_sz, &off_y, align_y,
1069             padding_t, padding_b);
1070 
1071         if ((new_w != child_w) || (new_h != child_h))
1072           evas_object_resize(opt->obj, new_w, new_h);
1073         evas_object_move(opt->obj, x + off_x, y + off_y);
1074 
1075         y += cell_sz + priv->pad.v;
1076         sub_pixel += inc;
1077         if (sub_pixel >= 1 << 16)
1078           {
1079              y++;
1080              sub_pixel -= 1 << 16;
1081           }
1082      }
1083 
1084    evas_object_size_hint_min_set(o, w, h);
1085 }
1086 
1087 EOLIAN static void
_evas_box_layout_homogeneous_max_size_horizontal(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)1088 _evas_box_layout_homogeneous_max_size_horizontal(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
1089 {
1090    int remaining, global_pad, pad_inc = 0, sub_pixel = 0;
1091    int cell_sz = 0;
1092    int x, y, w, h;
1093    int top_h = 0;
1094    int n_children;
1095    Evas_Object_Box_Option *opt;
1096    Eina_List *l;
1097 
1098    n_children = eina_list_count(priv->children);
1099    if (!n_children)
1100      {
1101         evas_object_size_hint_min_set(o, 0, 0);
1102         return;
1103      }
1104 
1105    evas_object_geometry_get(o, &x, &y, &w, &h);
1106 
1107    EINA_LIST_FOREACH(priv->children, l, opt)
1108      {
1109         int child_w, padding_l, padding_r;
1110 
1111         _sizing_eval(opt->obj);
1112         evas_object_size_hint_padding_get
1113            (opt->obj, &padding_l, &padding_r, NULL, NULL);
1114         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, NULL);
1115         if (child_w + padding_l + padding_r > cell_sz)
1116           cell_sz = child_w + padding_l + padding_r;
1117      }
1118 
1119    global_pad = priv->pad.h;
1120    remaining = w - n_children * cell_sz - global_pad * (n_children - 1);
1121 
1122    if (priv->align.h >= 0.0)
1123      x += remaining * priv->align.h;
1124    else if (n_children == 1)
1125      x += remaining / 2;
1126    else
1127      { /* justified */
1128         _fixed_point_divide_and_decompose_integer
1129            (remaining, n_children - 1, &global_pad, &pad_inc);
1130         global_pad += priv->pad.h;
1131      }
1132 
1133    EINA_LIST_FOREACH(priv->children, l, opt)
1134      {
1135         int child_w, child_h, min_w, max_w, max_h, new_w, new_h, off_x, off_y;
1136         int padding_l, padding_r, padding_t, padding_b;
1137         double align_x, align_y;
1138 
1139         evas_object_size_hint_align_get(opt->obj, &align_x, &align_y);
1140         evas_object_size_hint_padding_get
1141            (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1142         evas_object_size_hint_max_get(opt->obj, &max_w, &max_h);
1143         evas_object_size_hint_combined_min_get(opt->obj, &min_w, NULL);
1144 
1145         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1146 
1147         new_w = child_w;
1148         new_h = child_h;
1149         if (new_h > top_h) top_h = new_h;
1150 
1151         _layout_set_offset_and_expand_dimension_space_max_bounded
1152            (child_h, &new_h, h, max_h, &off_y, align_y, padding_t, padding_b);
1153 
1154         _layout_set_offset_and_change_dimension_min_max_cell_bounded
1155            (child_w, &new_w, min_w, max_w, cell_sz, &off_x, align_x,
1156             padding_l, padding_r);
1157 
1158         if ((new_w != child_w) || (new_h != child_h))
1159           evas_object_resize(opt->obj, new_w, new_h);
1160         evas_object_move(opt->obj, x + off_x, y + off_y);
1161 
1162         x += cell_sz + global_pad;
1163         sub_pixel += pad_inc;
1164         if (sub_pixel >= 1 << 16)
1165           {
1166              x++;
1167              sub_pixel -= 1 << 16;
1168           }
1169      }
1170 
1171    evas_object_size_hint_min_set(o, x, top_h);
1172 }
1173 
1174 EOLIAN static void
_evas_box_layout_homogeneous_max_size_vertical(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)1175 _evas_box_layout_homogeneous_max_size_vertical(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
1176 {
1177    int remaining, global_pad, pad_inc = 0, sub_pixel = 0;
1178    int cell_sz = 0;
1179    int x, y, w, h;
1180    int top_w = 0;
1181    int n_children;
1182    Evas_Object_Box_Option *opt;
1183    Eina_List *l;
1184 
1185    n_children = eina_list_count(priv->children);
1186    if (!n_children)
1187      {
1188         evas_object_size_hint_min_set(o, 0, 0);
1189         return;
1190      }
1191 
1192    evas_object_geometry_get(o, &x, &y, &w, &h);
1193 
1194    EINA_LIST_FOREACH(priv->children, l, opt)
1195      {
1196         int child_h, padding_t, padding_b;
1197 
1198         _sizing_eval(opt->obj);
1199         evas_object_size_hint_padding_get
1200            (opt->obj, NULL, NULL, &padding_t, &padding_b);
1201         evas_object_geometry_get(opt->obj, NULL, NULL, NULL, &child_h);
1202         if (child_h + padding_t + padding_b > cell_sz)
1203           cell_sz = child_h + padding_t + padding_b;
1204      }
1205 
1206    global_pad = priv->pad.v;
1207    remaining = h - n_children * cell_sz - global_pad * (n_children - 1);
1208 
1209    if (priv->align.v >= 0.0)
1210      y += remaining * priv->align.v;
1211    else if (n_children == 1)
1212      y += remaining / 2;
1213    else
1214      { /* justified */
1215         _fixed_point_divide_and_decompose_integer
1216            (remaining, n_children - 1, &global_pad, &pad_inc);
1217         global_pad += priv->pad.v;
1218      }
1219 
1220    EINA_LIST_FOREACH(priv->children, l, opt)
1221      {
1222         int child_w, child_h, max_h, min_h, max_w, new_w, new_h, off_x, off_y;
1223         int padding_l, padding_r, padding_t, padding_b;
1224         double align_x, align_y;
1225 
1226         evas_object_size_hint_align_get(opt->obj, &align_x, &align_y);
1227         evas_object_size_hint_padding_get
1228            (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1229         evas_object_size_hint_max_get(opt->obj, &max_w, &max_h);
1230         evas_object_size_hint_combined_min_get(opt->obj, NULL, &min_h);
1231 
1232         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1233 
1234         new_w = child_w;
1235         new_h = child_h;
1236         if (new_w > top_w) top_w = new_w;
1237 
1238         _layout_set_offset_and_expand_dimension_space_max_bounded
1239            (child_w, &new_w, w, max_w, &off_x, align_x, padding_l, padding_r);
1240 
1241         _layout_set_offset_and_change_dimension_min_max_cell_bounded
1242            (child_h, &new_h, min_h, max_h, cell_sz, &off_y, align_y,
1243             padding_t, padding_b);
1244 
1245         if ((new_w != child_w) || (new_h != child_h))
1246           evas_object_resize(opt->obj, new_w, new_h);
1247         evas_object_move(opt->obj, x + off_x, y + off_y);
1248 
1249         y += cell_sz + global_pad;
1250         sub_pixel += pad_inc;
1251         if (sub_pixel >= 1 << 16)
1252           {
1253              y++;
1254              sub_pixel -= 1 << 16;
1255           }
1256      }
1257 
1258    evas_object_size_hint_min_set(o, top_w, y);
1259 }
1260 
1261 static void
_evas_object_box_layout_flow_horizontal_row_info_collect(Evas_Object_Box_Data * priv,int box_w,int * row_count,int * row_max_h,int * row_break,int * row_width,int * off_y_ret,int * max_w_ret,int * max_h_ret)1262 _evas_object_box_layout_flow_horizontal_row_info_collect(Evas_Object_Box_Data *priv, int box_w, int *row_count, int *row_max_h, int *row_break, int *row_width, int *off_y_ret, int *max_w_ret, int *max_h_ret)
1263 {
1264    int i, remain_w = box_w, start_i = 0;
1265    int off_y = 0, max_w = 0, max_h = 0, n_rows = 0;
1266    Eina_List *l;
1267 
1268    for (i = 0, l = priv->children; l; i++, l = l->next)
1269      {
1270         Evas_Object_Box_Option *opt = l->data;
1271         int padding_l, padding_r, padding_t, padding_b;
1272         int child_w, child_h, off_x = 0;
1273 
1274         evas_object_size_hint_padding_get
1275            (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1276 
1277         _sizing_eval(opt->obj);
1278         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1279 
1280         child_w += padding_l + padding_r + priv->pad.h;
1281         child_h += padding_t + padding_b;
1282         if (child_w > max_w)
1283           max_w = child_w;
1284 
1285         remain_w -= child_w;
1286         if (remain_w + priv->pad.h >= 0)
1287           { /* continue "line" */
1288              if (child_h > max_h)
1289                max_h = child_h;
1290 
1291              off_x += child_w;
1292              row_width[n_rows] += child_w;
1293           }
1294         else
1295           { /* break line */
1296              if (i == start_i)
1297                { /* obj goes to actual line */
1298                   max_h = child_h;
1299                   row_width[n_rows] = child_w;
1300                }
1301              else
1302                { /* obj goes to next line */
1303                   row_max_h[n_rows] = max_h;
1304                   row_break[n_rows] = i - 1;
1305                   n_rows++;
1306 
1307                   off_x = child_w;
1308                   off_y += max_h;
1309                   max_h = child_h;
1310 
1311                   row_width[n_rows] = child_w;
1312                   start_i = i;
1313 
1314                   remain_w = box_w - off_x;
1315                }
1316           }
1317      }
1318 
1319    row_break[n_rows] = i - 1;
1320    row_max_h[n_rows] = max_h;
1321 
1322    *row_count = n_rows;
1323    *off_y_ret = off_y;
1324    *max_w_ret = max_w;
1325    *max_h_ret = max_h;
1326 }
1327 
1328 EOLIAN static void
_evas_box_layout_flow_horizontal(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)1329 _evas_box_layout_flow_horizontal(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
1330 {
1331    int n_children;
1332    int r, row_count = 0;
1333    int min_w = 0, min_h = 0;
1334    int max_h, inc_y;
1335    int remain_y, i;
1336    int x, y, w, h;
1337    Eina_List *l;
1338    int *row_max_h;
1339    int *row_break;
1340    int *row_width;
1341    int offset_y;
1342 
1343    n_children = eina_list_count(priv->children);
1344    if (!n_children)
1345      {
1346         evas_object_size_hint_min_set(o, 0, 0);
1347         return;
1348      }
1349 
1350    /* *per row* arrays */
1351    row_max_h = (int *)alloca(sizeof(int) * n_children);
1352    row_break = (int *)alloca(sizeof(int) * n_children);
1353    row_width = (int *)alloca(sizeof(int) * n_children);
1354 
1355    memset(row_width, 0, sizeof(int) * n_children);
1356 
1357    evas_object_geometry_get(o, &x, &y, &w, &h);
1358 
1359    _evas_object_box_layout_flow_horizontal_row_info_collect
1360      (priv, w, &row_count, row_max_h, row_break, row_width, &offset_y, &min_w, &max_h);
1361 
1362    inc_y = 0;
1363    remain_y = h - (priv->pad.v * row_count -1) - (offset_y + max_h);
1364 
1365    if (remain_y > 0)
1366      {
1367         if (priv->align.v >= 0.0)
1368           inc_y = priv->align.v * remain_y;
1369         else if (row_count == 0)
1370           y += remain_y / 2;
1371         else /* y-justified */
1372           inc_y = remain_y / row_count;
1373      }
1374 
1375    inc_y += priv->pad.v;
1376 
1377    for (i = 0, r = 0, l = priv->children; r <= row_count; r++)
1378      {
1379         int row_justify = 0, just_inc = 0, sub_pixel = 0;
1380         int row_size, remain_x;
1381 
1382         row_size = row_break[r] - i;
1383         remain_x = (w - (row_width[r] - priv->pad.h));
1384 
1385         if (priv->align.h < 0.0)
1386           {
1387              if (row_size == 0)
1388                x += remain_x / 2;
1389              else
1390                _fixed_point_divide_and_decompose_integer
1391                   (remain_x, row_size, &row_justify, &just_inc);
1392           }
1393 
1394         row_justify += priv->pad.h;
1395 
1396         for (; i <= row_break[r]; i++, l = l->next)
1397           {
1398              Evas_Object_Box_Option *opt = l->data;
1399              int off_x, off_y, y_remain;
1400              int padding_l, padding_r;
1401              int child_w, child_h;
1402              double align_y;
1403 
1404              evas_object_size_hint_align_get(opt->obj, NULL, &align_y);
1405              evas_object_size_hint_padding_get
1406                 (opt->obj, &padding_l, &padding_r, NULL, NULL);
1407 
1408              evas_object_geometry_get
1409                 (opt->obj, NULL, NULL, &child_w, &child_h);
1410 
1411              y_remain = row_max_h[r] - child_h;
1412 
1413              off_x = padding_l;
1414              if (priv->align.h >= 0.0)
1415                off_x += remain_x * priv->align.h;
1416              off_y = y_remain * align_y;
1417 
1418              evas_object_move(opt->obj, x + off_x, y + off_y);
1419 
1420              x += child_w + padding_l + padding_r + row_justify;
1421 
1422              sub_pixel += just_inc;
1423              if (sub_pixel >= 1 << 16)
1424                {
1425                   x++;
1426                   sub_pixel -= 1 << 16;
1427                }
1428           }
1429 
1430         evas_object_geometry_get(o, &x, NULL, NULL, NULL);
1431         min_h += row_max_h[r];
1432         y += row_max_h[r] + inc_y;
1433 
1434         if (r > 0)
1435           min_h += priv->pad.v;
1436      }
1437 
1438    evas_object_size_hint_min_set(o, min_w, min_h);
1439 }
1440 
1441 static void
_evas_object_box_layout_flow_vertical_col_info_collect(Evas_Object_Box_Data * priv,int box_h,int * col_count,int * col_max_w,int * col_break,int * col_height,int * off_x_ret,int * max_w_ret,int * max_h_ret)1442 _evas_object_box_layout_flow_vertical_col_info_collect(Evas_Object_Box_Data *priv, int box_h, int *col_count, int *col_max_w, int *col_break, int *col_height, int *off_x_ret, int *max_w_ret, int *max_h_ret)
1443 {
1444    int i, remain_h = box_h, start_i = 0;
1445    int off_x = 0, max_w = 0, max_h = 0, n_cols = 0;
1446    Eina_List *l;
1447 
1448    for (i = 0, l = priv->children; l; i++, l = l->next)
1449      {
1450         Evas_Object_Box_Option *opt = l->data;
1451         int padding_l, padding_r, padding_t, padding_b;
1452         int child_w, child_h, off_y = 0;
1453 
1454         evas_object_size_hint_padding_get
1455            (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1456 
1457         _sizing_eval(opt->obj);
1458         evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1459 
1460         child_w += padding_l + padding_r;
1461         child_h += padding_t + padding_b + priv->pad.v;
1462         if (child_h > max_h)
1463           max_h = child_h;
1464 
1465         remain_h -= child_h;
1466         if (remain_h + priv->pad.v >= 0)
1467           { /* continue "col" */
1468              if (child_w > max_w)
1469                max_w = child_w;
1470 
1471              off_y += child_h;
1472              col_height[n_cols] += child_h;
1473           }
1474         else
1475           {
1476              /* break col */
1477              if (i == start_i)
1478                { /* obj goes to actual col */
1479                   max_w = child_w;
1480                   col_height[n_cols] = child_h;
1481                }
1482              else
1483                { /* obj goes to next col */
1484                   col_max_w[n_cols] = max_w;
1485                   col_break[n_cols] = i - 1;
1486                   n_cols++;
1487 
1488                   off_x += max_w;
1489                   off_y = child_h;
1490                   max_w = child_w;
1491 
1492                   col_height[n_cols] = child_h;
1493                   start_i = i;
1494 
1495                   remain_h = box_h - off_y;
1496                }
1497           }
1498      }
1499 
1500    col_break[n_cols] = i - 1;
1501    col_max_w[n_cols] = max_w;
1502 
1503    *col_count = n_cols;
1504    *off_x_ret = off_x;
1505    *max_w_ret = max_w;
1506    *max_h_ret = max_h;
1507 }
1508 
1509 EOLIAN static void
_evas_box_layout_flow_vertical(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)1510 _evas_box_layout_flow_vertical(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
1511 {
1512    int n_children;
1513    int c, col_count;
1514    int min_w = 0, min_h = 0;
1515    int max_w, inc_x;
1516    int remain_x, i;
1517    int x, y, w, h;
1518    Eina_List *l;
1519    int *col_max_w;
1520    int *col_break;
1521    int *col_height;
1522    int offset_x;
1523 
1524    n_children = eina_list_count(priv->children);
1525    if (!n_children)
1526      {
1527         evas_object_size_hint_min_set(o, 0, 0);
1528         return;
1529      }
1530 
1531    /* *per col* arrays */
1532    col_max_w = (int *)alloca(sizeof(int) * n_children);
1533    col_break = (int *)alloca(sizeof(int) * n_children);
1534    col_height = (int *)alloca(sizeof(int) * n_children);
1535 
1536    memset(col_height, 0, sizeof(int) * n_children);
1537 
1538    evas_object_geometry_get(o, &x, &y, &w, &h);
1539 
1540    _evas_object_box_layout_flow_vertical_col_info_collect
1541      (priv, h, &col_count, col_max_w, col_break, col_height, &offset_x, &max_w, &min_h);
1542 
1543    inc_x = 0;
1544    remain_x = w - (offset_x + max_w);
1545 
1546    if (remain_x > 0)
1547      {
1548         if (priv->align.h >= 0)
1549           inc_x = priv->align.h * remain_x;
1550         else if (col_count == 0)
1551           x += remain_x / 2;
1552         else /* x-justified */
1553           inc_x = remain_x / col_count;
1554      }
1555 
1556    inc_x += priv->pad.h;
1557 
1558    for (i = 0, c = 0, l = priv->children; c <= col_count; c++)
1559      {
1560         int col_justify = 0, just_inc = 0, sub_pixel = 0;
1561         int col_size, remain_y;
1562 
1563         col_size = col_break[c] - i;
1564         remain_y = (h - col_height[c]);
1565 
1566         if (priv->align.v < 0.0)
1567           {
1568              if (col_size == 0)
1569                y += remain_y / 2;
1570              else
1571                _fixed_point_divide_and_decompose_integer
1572                   (remain_y, col_size, &col_justify, &just_inc);
1573           }
1574 
1575         col_justify += priv->pad.v;
1576 
1577         for (; i <= col_break[c]; i++, l = l->next)
1578           {
1579              Evas_Object_Box_Option *opt = l->data;
1580              int off_x, off_y, x_remain;
1581              int padding_t, padding_b;
1582              int child_w, child_h;
1583              double align_x;
1584 
1585              evas_object_size_hint_align_get(opt->obj, &align_x, NULL);
1586              evas_object_size_hint_padding_get
1587                 (opt->obj, NULL, NULL, &padding_t, &padding_b);
1588 
1589              evas_object_geometry_get
1590                 (opt->obj, NULL, NULL, &child_w, &child_h);
1591 
1592              x_remain = col_max_w[c] - child_w;
1593 
1594              off_x = x_remain * align_x;
1595              off_y = padding_t;
1596              if (priv->align.v >= 0.0)
1597                off_y += remain_y * priv->align.v;
1598 
1599              evas_object_move(opt->obj, x + off_x, y + off_y);
1600 
1601              y += child_h + padding_t + padding_b + col_justify;
1602 
1603              sub_pixel += just_inc;
1604              if (sub_pixel >= 1 << 16)
1605                {
1606                   y++;
1607                   sub_pixel -= 1 << 16;
1608                }
1609           }
1610 
1611         evas_object_geometry_get(o, NULL, &y, NULL, NULL);
1612         min_w += col_max_w[c];
1613         x += col_max_w[c] + inc_x;
1614      }
1615 
1616    evas_object_size_hint_min_set(o, min_w, min_h);
1617 }
1618 
1619 EOLIAN static void
_evas_box_layout_stack(Eo * o,Evas_Object_Box_Data * priv,Evas_Object_Box_Data * boxdata EINA_UNUSED,void * data EINA_UNUSED)1620 _evas_box_layout_stack(Eo *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Data *boxdata EINA_UNUSED, void *data EINA_UNUSED)
1621 {
1622    Eina_List *l;
1623    Evas_Coord ox, oy, ow, oh;
1624    Evas_Coord top_w = 0, top_h = 0;
1625    Evas_Object_Box_Option *opt;
1626    Evas_Object *old_child = NULL;
1627 
1628    evas_object_geometry_get(o, &ox, &oy, &ow, &oh);
1629 
1630    EINA_LIST_FOREACH(priv->children, l, opt)
1631      {
1632         Evas_Object *child = opt->obj;
1633         Evas_Coord max_w, max_h, min_w, min_h, pad_l, pad_r, pad_t, pad_b,
1634                    child_w, child_h, new_w, new_h, off_x, off_y;
1635         double align_x, align_y;
1636 
1637         evas_object_size_hint_align_get(child, &align_x, &align_y);
1638         evas_object_size_hint_padding_get
1639            (child, &pad_l, &pad_r, &pad_t, &pad_b);
1640         evas_object_size_hint_max_get(child, &max_w, &max_h);
1641         evas_object_size_hint_combined_min_get(child, &min_w, &min_h);
1642 
1643         _sizing_eval(opt->obj);
1644         evas_object_geometry_get(child, NULL, NULL, &child_w, &child_h);
1645         new_w = child_w;
1646         new_h = child_h;
1647 
1648         _layout_set_offset_and_change_dimension_min_max_cell_bounded
1649            (child_w, &new_w, min_w, max_w, ow, &off_x, align_x, pad_l, pad_r);
1650         _layout_set_offset_and_change_dimension_min_max_cell_bounded
1651            (child_h, &new_h, min_h, max_h, oh, &off_y, align_y, pad_t, pad_b);
1652 
1653         if (new_w > top_w) top_w = new_w;
1654         if (new_h > top_h) top_h = new_h;
1655 
1656         if ((new_w != child_w) || (new_h != child_h))
1657           evas_object_resize(child, new_w, new_h);
1658 
1659         if ((align_x < 0) && (priv->align.h >= 0.0))
1660           off_x += (ow - new_w) * priv->align.h;
1661         if ((align_y < 0) && (priv->align.v >= 0.0))
1662           off_y += (oh - new_h) * priv->align.v;
1663         evas_object_move(child, ox + off_x, oy + off_y);
1664 
1665         if (old_child)
1666           evas_object_stack_above(child, old_child);
1667         old_child = child;
1668      }
1669 
1670    evas_object_size_hint_min_set(o, top_w, top_h);
1671 }
1672 
1673 EOLIAN static void
_evas_box_align_set(Eo * o,Evas_Object_Box_Data * priv,double horizontal,double vertical)1674 _evas_box_align_set(Eo *o, Evas_Object_Box_Data *priv, double horizontal, double vertical)
1675 {
1676    if ((EINA_DBL_EQ(priv->align.h, horizontal)) &&
1677        (EINA_DBL_EQ(priv->align.v, vertical)))
1678      return;
1679    priv->align.h = horizontal;
1680    priv->align.v = vertical;
1681    evas_object_smart_changed(o);
1682 }
1683 
1684 EOLIAN static void
_evas_box_align_get(const Eo * o EINA_UNUSED,Evas_Object_Box_Data * priv,double * horizontal,double * vertical)1685 _evas_box_align_get(const Eo *o EINA_UNUSED, Evas_Object_Box_Data *priv, double *horizontal, double *vertical)
1686 {
1687    if (priv)
1688      {
1689         if (horizontal) *horizontal = priv->align.h;
1690         if (vertical) *vertical = priv->align.v;
1691      }
1692    else
1693      {
1694         if (horizontal) *horizontal = 0.5;
1695         if (vertical) *vertical = 0.5;
1696      }
1697 }
1698 
1699 EOLIAN static void
_evas_box_padding_set(Eo * o,Evas_Object_Box_Data * priv,Evas_Coord horizontal,Evas_Coord vertical)1700 _evas_box_padding_set(Eo *o, Evas_Object_Box_Data *priv, Evas_Coord horizontal, Evas_Coord vertical)
1701 {
1702    if (priv->pad.h == horizontal && priv->pad.v == vertical)
1703      return;
1704    priv->pad.h = horizontal;
1705    priv->pad.v = vertical;
1706    evas_object_smart_changed(o);
1707 }
1708 
1709 EOLIAN static void
_evas_box_padding_get(const Eo * o EINA_UNUSED,Evas_Object_Box_Data * priv,Evas_Coord * horizontal,Evas_Coord * vertical)1710 _evas_box_padding_get(const Eo *o EINA_UNUSED, Evas_Object_Box_Data *priv, Evas_Coord *horizontal, Evas_Coord *vertical)
1711 {
1712    if (priv)
1713      {
1714         if (horizontal) *horizontal = priv->pad.h;
1715         if (vertical) *vertical = priv->pad.v;
1716      }
1717    else
1718      {
1719         if (horizontal) *horizontal = 0;
1720         if (vertical) *vertical = 0;
1721      }
1722 }
1723 
1724 EOLIAN static Evas_Object_Box_Option*
_evas_box_append(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child)1725 _evas_box_append(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child)
1726 {
1727    Evas_Object_Box_Option *opt = NULL;
1728 
1729    if (!child || (evas_object_smart_parent_get(child) == o))
1730      return NULL;
1731 
1732    opt = evas_obj_box_internal_append(o, child);
1733 
1734    if (opt)
1735      {
1736         evas_object_smart_member_add(child, o);
1737         evas_object_smart_changed(o);
1738         return _evas_object_box_option_callbacks_register(o, priv, opt);
1739      }
1740 
1741    return NULL;
1742 }
1743 
1744 EOLIAN static Evas_Object_Box_Option*
_evas_box_prepend(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child)1745 _evas_box_prepend(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child)
1746 {
1747    Evas_Object_Box_Option *opt = NULL;
1748    if (!child)
1749      return NULL;
1750 
1751    opt = evas_obj_box_internal_prepend(o, child);
1752 
1753    if (opt)
1754      {
1755         evas_object_smart_member_add(child, o);
1756         evas_object_smart_changed(o);
1757         return _evas_object_box_option_callbacks_register(o, priv, opt);
1758      }
1759    return NULL;
1760 }
1761 
1762 EOLIAN static Evas_Object_Box_Option*
_evas_box_insert_before(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child,const Evas_Object * reference)1763 _evas_box_insert_before(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child, const Evas_Object *reference)
1764 {
1765    Evas_Object_Box_Option *opt = NULL;
1766    if (!child)
1767      return NULL;
1768 
1769    opt = evas_obj_box_internal_insert_before(o, child, reference);
1770 
1771    if (opt)
1772      {
1773         evas_object_smart_member_add(child, o);
1774         evas_object_smart_changed(o);
1775         return _evas_object_box_option_callbacks_register(o, priv, opt);
1776      }
1777 
1778    return NULL;
1779 }
1780 
1781 EOLIAN static Evas_Object_Box_Option*
_evas_box_insert_after(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child,const Evas_Object * reference)1782 _evas_box_insert_after(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child, const Evas_Object *reference)
1783 {
1784    Evas_Object_Box_Option *opt = NULL;
1785    if (!child)
1786      return NULL;
1787 
1788    opt = evas_obj_box_internal_insert_after(o, child, reference);
1789 
1790    if (opt)
1791      {
1792         evas_object_smart_member_add(child, o);
1793         evas_object_smart_changed(o);
1794         return _evas_object_box_option_callbacks_register(o, priv, opt);
1795      }
1796 
1797    return NULL;
1798 }
1799 
1800 EOLIAN static Evas_Object_Box_Option*
_evas_box_insert_at(Eo * o,Evas_Object_Box_Data * priv,Evas_Object * child,unsigned int pos)1801 _evas_box_insert_at(Eo *o, Evas_Object_Box_Data *priv, Evas_Object *child, unsigned int pos)
1802 {
1803    Evas_Object_Box_Option *opt = NULL;
1804    if (!child)
1805      return NULL;
1806 
1807    opt = evas_obj_box_internal_insert_at(o, child, pos);
1808 
1809    if (opt)
1810      {
1811         evas_object_smart_member_add(child, o);
1812         evas_object_smart_changed(o);
1813         return _evas_object_box_option_callbacks_register(o, priv, opt);
1814      }
1815 
1816    return NULL;
1817 }
1818 
1819 EOLIAN static Eina_Bool
_evas_box_remove(Eo * o,Evas_Object_Box_Data * _pd EINA_UNUSED,Evas_Object * child)1820 _evas_box_remove(Eo *o, Evas_Object_Box_Data *_pd EINA_UNUSED, Evas_Object *child)
1821 {
1822    Evas_Object *obj = NULL;
1823 
1824    obj = evas_obj_box_internal_remove(o, child);
1825 
1826    if (obj)
1827      {
1828         _evas_object_box_child_callbacks_unregister(obj, o);
1829         evas_object_smart_member_del(obj);
1830         evas_object_smart_changed(o);
1831         return EINA_TRUE;
1832      }
1833 
1834    return EINA_FALSE;
1835 }
1836 
1837 EOLIAN static Eina_Bool
_evas_box_remove_at(Eo * o,Evas_Object_Box_Data * _pd EINA_UNUSED,unsigned int pos)1838 _evas_box_remove_at(Eo *o, Evas_Object_Box_Data *_pd EINA_UNUSED, unsigned int pos)
1839 {
1840    Evas_Object *obj = NULL;
1841 
1842    obj = evas_obj_box_internal_remove_at(o, pos);
1843 
1844    if (obj)
1845      {
1846         _evas_object_box_child_callbacks_unregister(obj, o);
1847         evas_object_smart_member_del(obj);
1848         evas_object_smart_changed(o);
1849         return EINA_TRUE;
1850      }
1851 
1852    return EINA_FALSE;
1853 }
1854 
1855 EOLIAN static Eina_Bool
_evas_box_remove_all(Eo * o,Evas_Object_Box_Data * priv,Eina_Bool clear)1856 _evas_box_remove_all(Eo *o, Evas_Object_Box_Data *priv, Eina_Bool clear)
1857 {
1858    evas_object_smart_changed(o);
1859 
1860    while (priv->children)
1861      {
1862         Evas_Object_Box_Option *opt = priv->children->data;
1863         Evas_Object *obj = NULL;
1864 
1865         obj = evas_obj_box_internal_remove(o, opt->obj);
1866         if (obj)
1867           {
1868              _evas_object_box_child_callbacks_unregister(obj, o);
1869              evas_object_smart_member_del(obj);
1870              if (clear)
1871                evas_object_del(obj);
1872           }
1873         else return EINA_FALSE;
1874      }
1875 
1876    return EINA_TRUE;
1877 }
1878 
1879 EOLIAN static Eina_Iterator*
_evas_box_iterator_new(const Eo * o,Evas_Object_Box_Data * priv)1880 _evas_box_iterator_new(const Eo *o, Evas_Object_Box_Data *priv)
1881 {
1882    Evas_Object_Box_Iterator *it;
1883 
1884    if (!priv->children) return NULL;
1885 
1886    it = calloc(1, sizeof(Evas_Object_Box_Iterator));
1887    if (!it) return NULL;
1888 
1889    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1890 
1891    it->real_iterator = eina_list_iterator_new(priv->children);
1892    it->box = o;
1893 
1894    it->iterator.next = FUNC_ITERATOR_NEXT(_evas_object_box_iterator_next);
1895    it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_evas_object_box_iterator_get_container);
1896    it->iterator.free = FUNC_ITERATOR_FREE(_evas_object_box_iterator_free);
1897 
1898    return &it->iterator;
1899 }
1900 
1901 EOLIAN static Eina_Accessor*
_evas_box_accessor_new(const Eo * o,Evas_Object_Box_Data * priv)1902 _evas_box_accessor_new(const Eo *o, Evas_Object_Box_Data *priv)
1903 {
1904    Evas_Object_Box_Accessor *it;
1905 
1906    if (!priv->children) return NULL;
1907 
1908    it = calloc(1, sizeof(Evas_Object_Box_Accessor));
1909    if (!it) return NULL;
1910 
1911    EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
1912 
1913    it->real_accessor = eina_list_accessor_new(priv->children);
1914    it->box = o;
1915 
1916    it->accessor.get_at = FUNC_ACCESSOR_GET_AT(_evas_object_box_accessor_get_at);
1917    it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(_evas_object_box_accessor_get_container);
1918    it->accessor.free = FUNC_ACCESSOR_FREE(_evas_object_box_accessor_free);
1919 
1920    return &it->accessor;
1921 }
1922 
1923 EAPI Eina_List *
evas_object_box_children_get(const Evas_Object * o)1924 evas_object_box_children_get(const Evas_Object *o)
1925 {
1926    Eina_List *new_list = NULL, *l;
1927    Evas_Object_Box_Option *opt;
1928 
1929    EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1930 
1931    EINA_LIST_FOREACH(priv->children, l, opt)
1932       new_list = eina_list_append(new_list, opt->obj);
1933 
1934    return new_list;
1935 }
1936 
1937 EOLIAN static int
_evas_box_count(Eo * o,Evas_Object_Box_Data * _pd EINA_UNUSED)1938 _evas_box_count(Eo *o, Evas_Object_Box_Data *_pd EINA_UNUSED)
1939 {
1940    EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1941    return eina_list_count(priv->children);
1942 }
1943 
1944 EOLIAN static const char*
_evas_box_option_property_name_get(const Eo * o EINA_UNUSED,Evas_Object_Box_Data * _pd EINA_UNUSED,int property EINA_UNUSED)1945 _evas_box_option_property_name_get(const Eo *o EINA_UNUSED, Evas_Object_Box_Data *_pd EINA_UNUSED, int property EINA_UNUSED)
1946 {
1947    return NULL;
1948 }
1949 
1950 EOLIAN static int
_evas_box_option_property_id_get(const Eo * o EINA_UNUSED,Evas_Object_Box_Data * _pd EINA_UNUSED,const char * name EINA_UNUSED)1951 _evas_box_option_property_id_get(const Eo *o EINA_UNUSED, Evas_Object_Box_Data *_pd EINA_UNUSED, const char *name EINA_UNUSED)
1952 {
1953    return -1;
1954 }
1955 
1956 EAPI Eina_Bool
evas_object_box_option_property_set(Evas_Object * o,Evas_Object_Box_Option * opt,int property,...)1957 evas_object_box_option_property_set(Evas_Object *o, Evas_Object_Box_Option *opt, int property, ...)
1958 {
1959    Eina_Bool ret;
1960    va_list args;
1961 
1962    va_start(args, property);
1963    ret = evas_object_box_option_property_vset(o, opt, property, args);
1964    va_end(args);
1965 
1966    return ret;
1967 }
1968 
1969 
1970 EAPI Eina_Bool
evas_object_box_option_property_vset(Evas_Object * o,Evas_Object_Box_Option * opt,int property,va_list args)1971 evas_object_box_option_property_vset(Evas_Object *o, Evas_Object_Box_Option *opt, int property, va_list args)
1972 {
1973    return evas_obj_box_option_property_vset(o, opt, property, (va_list *) &args);
1974 }
1975 
1976 EOLIAN static Eina_Bool
_evas_box_option_property_vset(Eo * o EINA_UNUSED,Evas_Object_Box_Data * _pd EINA_UNUSED,Evas_Object_Box_Option * opt EINA_UNUSED,int property EINA_UNUSED,va_list * args EINA_UNUSED)1977 _evas_box_option_property_vset(Eo *o EINA_UNUSED, Evas_Object_Box_Data *_pd EINA_UNUSED, Evas_Object_Box_Option *opt EINA_UNUSED, int property EINA_UNUSED, va_list *args EINA_UNUSED)
1978 {
1979    return EINA_FALSE;
1980 }
1981 
1982 EAPI Eina_Bool
evas_object_box_option_property_get(const Evas_Object * o,Evas_Object_Box_Option * opt,int property,...)1983 evas_object_box_option_property_get(const Evas_Object *o, Evas_Object_Box_Option *opt, int property, ...)
1984 {
1985    Eina_Bool ret;
1986    va_list args;
1987 
1988    va_start(args, property);
1989    ret = evas_object_box_option_property_vget(o, opt, property, args);
1990    va_end(args);
1991 
1992    return ret;
1993 }
1994 
1995 EAPI Eina_Bool
evas_object_box_option_property_vget(const Evas_Object * o,Evas_Object_Box_Option * opt,int property,va_list args)1996 evas_object_box_option_property_vget(const Evas_Object *o, Evas_Object_Box_Option *opt, int property, va_list args)
1997 {
1998    return evas_obj_box_option_property_vget((Eo *)o, opt, property, (va_list *) &args);
1999 }
2000 
2001 EOLIAN static Eina_Bool
_evas_box_option_property_vget(const Eo * o EINA_UNUSED,Evas_Object_Box_Data * _pd EINA_UNUSED,Evas_Object_Box_Option * opt EINA_UNUSED,int property EINA_UNUSED,va_list * args EINA_UNUSED)2002 _evas_box_option_property_vget(const Eo *o EINA_UNUSED, Evas_Object_Box_Data *_pd EINA_UNUSED, Evas_Object_Box_Option *opt EINA_UNUSED, int property EINA_UNUSED, va_list *args EINA_UNUSED)
2003 {
2004    return EINA_FALSE;
2005 }
2006 
2007 EOLIAN static void
_evas_box_class_constructor(Efl_Class * klass)2008 _evas_box_class_constructor(Efl_Class *klass)
2009 {
2010    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
2011 }
2012 
2013 /* Internal EO APIs and hidden overrides */
2014 
2015 #define EVAS_BOX_EXTRA_OPS \
2016    EFL_CANVAS_GROUP_ADD_DEL_OPS(evas_box)
2017 
2018 #include "canvas/evas_box_eo.c"
2019