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