2 #include "evas_common.h"
4 typedef struct _Evas_Object_Table_Data Evas_Object_Table_Data;
5 typedef struct _Evas_Object_Table_Option Evas_Object_Table_Option;
6 typedef struct _Evas_Object_Table_Cache Evas_Object_Table_Cache;
7 typedef struct _Evas_Object_Table_Iterator Evas_Object_Table_Iterator;
8 typedef struct _Evas_Object_Table_Accessor Evas_Object_Table_Accessor;
10 struct _Evas_Object_Table_Option
13 unsigned short col, row, colspan, rowspan, end_col, end_row;
21 Evas_Coord l, r, t, b;
23 Eina_Bool expand_h : 1; /* XXX required? */
24 Eina_Bool expand_v : 1; /* XXX required? */
29 struct _Evas_Object_Table_Cache
47 struct _Evas_Object_Table_Data
49 Evas_Object_Smart_Clipped_Data base;
60 Evas_Object_Table_Cache *cache;
61 Evas_Object_Table_Homogeneous_Mode homogeneous;
62 Eina_Bool hints_changed : 1;
63 Eina_Bool expand_h : 1;
64 Eina_Bool expand_v : 1;
65 Eina_Bool is_mirrored : 1;
68 struct _Evas_Object_Table_Iterator
70 Eina_Iterator iterator;
72 Eina_Iterator *real_iterator;
73 const Evas_Object *table;
76 struct _Evas_Object_Table_Accessor
78 Eina_Accessor accessor;
80 Eina_Accessor *real_accessor;
81 const Evas_Object *table;
85 * @addtogroup Evas_Object_Table
89 #define EVAS_OBJECT_TABLE_DATA_GET(o, ptr) \
90 Evas_Object_Table_Data *ptr = evas_object_smart_data_get(o)
92 #define EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, ptr) \
93 EVAS_OBJECT_TABLE_DATA_GET(o, ptr); \
96 CRIT("no widget data for object %p (%s)", \
97 o, evas_object_type_get(o)); \
102 #define EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
103 EVAS_OBJECT_TABLE_DATA_GET(o, ptr); \
106 CRIT("No widget data for object %p (%s)", \
107 o, evas_object_type_get(o)); \
112 static const char EVAS_OBJECT_TABLE_OPTION_KEY[] = "Evas_Object_Table_Option";
115 _evas_object_table_iterator_next(Evas_Object_Table_Iterator *it, void **data)
117 Evas_Object_Table_Option *opt;
119 if (!eina_iterator_next(it->real_iterator, (void **)&opt))
121 if (data) *data = opt->obj;
126 _evas_object_table_iterator_get_container(Evas_Object_Table_Iterator *it)
128 return (Evas_Object *)it->table;
132 _evas_object_table_iterator_free(Evas_Object_Table_Iterator *it)
134 eina_iterator_free(it->real_iterator);
139 _evas_object_table_accessor_get_at(Evas_Object_Table_Accessor *it, unsigned int index, void **data)
141 Evas_Object_Table_Option *opt = NULL;
143 if (!eina_accessor_data_get(it->real_accessor, index, (void **)&opt))
145 if (data) *data = opt->obj;
150 _evas_object_table_accessor_get_container(Evas_Object_Table_Accessor *it)
152 return (Evas_Object *)it->table;
156 _evas_object_table_accessor_free(Evas_Object_Table_Accessor *it)
158 eina_accessor_free(it->real_accessor);
162 static Evas_Object_Table_Cache *
163 _evas_object_table_cache_alloc(int cols, int rows)
165 Evas_Object_Table_Cache *cache;
168 size = (sizeof(Evas_Object_Table_Cache) +
169 (cols + rows) * (sizeof(Eina_Bool) + sizeof(Evas_Coord)));
170 cache = malloc(size);
173 ERR("Could not allocate table cache %dx%d (%d bytes): %s",
174 cols, rows, size, strerror(errno));
178 cache->sizes.h = (Evas_Coord *)(cache + 1);
179 cache->sizes.v = (Evas_Coord *)(cache->sizes.h + cols);
180 cache->expands.h = (Eina_Bool *)(cache->sizes.v + rows);
181 cache->expands.v = (Eina_Bool *)(cache->expands.h + cols);
187 _evas_object_table_cache_free(Evas_Object_Table_Cache *cache)
193 _evas_object_table_cache_reset(Evas_Object_Table_Data *priv)
195 Evas_Object_Table_Cache *c = priv->cache;
198 c->total.expands.v = 0;
199 c->total.expands.h = 0;
203 size = ((priv->size.rows + priv->size.cols) *
204 (sizeof(Eina_Bool) + sizeof(Evas_Coord)));
205 memset(c + 1, 0, size);
209 _evas_object_table_cache_invalidate(Evas_Object_Table_Data *priv)
211 priv->hints_changed = 1;
214 _evas_object_table_cache_free(priv->cache);
219 static Evas_Object_Table_Option *
220 _evas_object_table_option_get(Evas_Object *o)
222 return evas_object_data_get(o, EVAS_OBJECT_TABLE_OPTION_KEY);
226 _evas_object_table_option_set(Evas_Object *o, const Evas_Object_Table_Option *opt)
228 evas_object_data_set(o, EVAS_OBJECT_TABLE_OPTION_KEY, opt);
231 static Evas_Object_Table_Option *
232 _evas_object_table_option_del(Evas_Object *o)
234 return evas_object_data_del(o, EVAS_OBJECT_TABLE_OPTION_KEY);
238 _on_child_del(void *data, Evas *evas __UNUSED__, Evas_Object *child, void *einfo __UNUSED__)
240 Evas_Object *table = data;
241 evas_object_table_unpack(table, child);
245 _on_child_hints_changed(void *data, Evas *evas __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__)
247 Evas_Object *table = data;
248 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(table, priv);
249 _evas_object_table_cache_invalidate(priv);
250 evas_object_smart_changed(table);
254 _evas_object_table_child_connect(Evas_Object *o, Evas_Object *child)
256 evas_object_event_callback_add
257 (child, EVAS_CALLBACK_DEL, _on_child_del, o);
258 evas_object_event_callback_add
259 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_child_hints_changed, o);
263 _evas_object_table_child_disconnect(Evas_Object *o, Evas_Object *child)
265 evas_object_event_callback_del_full
266 (child, EVAS_CALLBACK_DEL, _on_child_del, o);
267 evas_object_event_callback_del_full
268 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_child_hints_changed, o);
272 _evas_object_table_calculate_cell(const Evas_Object_Table_Option *opt, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
276 *w -= opt->pad.l + opt->pad.r;
279 else if ((opt->max.w > -1) && (*w > opt->max.w))
281 else if (opt->fill_h)
286 *h -= opt->pad.t + opt->pad.b;
289 else if ((opt->max.h > -1) && (*h > opt->max.h))
291 else if (opt->fill_v)
299 *x += (*w - cw) * opt->align.h;
306 *y += (*h - ch) * opt->align.v;
311 /* static Eina_Bool */
312 /* _evas_object_table_check_hints_homogeneous_table(Evas_Object *child, double *align, Evas_Coord min, const char *axis_name) */
314 /* if (*align < 0.0) */
316 /* /\* assume expand and align to the center. */
317 /* * this is compatible with evas_object_box behavior and is the */
318 /* * same as weight > 0.0. */
323 /* else if (min < 1) */
325 /* WRN("Child %p [%s, %s] has no minimum width " */
326 /* "and no %s expand (weight is not > 0.0). " */
327 /* "Assuming weight > 0.0\n", */
328 /* child, evas_object_type_get(child), evas_object_name_get(child), */
337 _evas_object_table_calculate_hints_homogeneous(Evas_Object *o, Evas_Object_Table_Data *priv)
340 Evas_Object_Table_Option *opt;
341 Evas_Coord minw, minh, o_minw, o_minh;
342 Eina_Bool expand_h, expand_v;
351 EINA_LIST_FOREACH(priv->children, l, opt)
353 Evas_Object *child = opt->obj;
354 Evas_Coord child_minw, child_minh, cell_minw, cell_minh;
355 double weightw, weighth;
357 evas_object_size_hint_min_get(child, &opt->min.w, &opt->min.h);
358 evas_object_size_hint_max_get(child, &opt->max.w, &opt->max.h);
359 evas_object_size_hint_padding_get
360 (child, &opt->pad.l, &opt->pad.r, &opt->pad.t, &opt->pad.b);
361 evas_object_size_hint_align_get(child, &opt->align.h, &opt->align.v);
362 evas_object_size_hint_weight_get(child, &weightw, &weighth);
364 child_minw = opt->min.w + opt->pad.l + opt->pad.r;
365 child_minh = opt->min.h + opt->pad.t + opt->pad.b;
367 cell_minw = (child_minw + opt->colspan - 1) / opt->colspan;
368 cell_minh = (child_minh + opt->rowspan - 1) / opt->rowspan;
371 if ((weightw > 0.0) &&
373 ((opt->max.w > -1) && (opt->min.w < opt->max.w))))
378 /* else if ((priv->homogeneous == EVAS_OBJECT_TABLE_HOMOGENEOUS_TABLE) && */
379 /* (!_evas_object_table_check_hints_homogeneous_table */
380 /* (child, &opt->align.h, opt->min.w, "horizontal"))) */
382 /* opt->expand_h = 1; */
388 if ((weighth > 0.0) &&
390 ((opt->max.h > -1) && (opt->min.h < opt->max.h))))
395 /* else if ((priv->homogeneous == EVAS_OBJECT_TABLE_HOMOGENEOUS_TABLE) && */
396 /* (!_evas_object_table_check_hints_homogeneous_table */
397 /* (child, &opt->align.v, opt->min.h, "vertical"))) */
399 /* opt->expand_v = 1; */
404 if (opt->align.h < 0.0)
410 if (opt->align.v < 0.0)
416 /* greatest mininum values, with paddings */
417 if (minw < cell_minw)
419 if (minh < cell_minh)
421 /* greatest mininum values, without paddings */
422 if (o_minw < opt->min.w)
424 if (o_minh < opt->min.h)
428 if (priv->homogeneous == EVAS_OBJECT_TABLE_HOMOGENEOUS_ITEM)
432 ERR("homogeneous table based on item size but no "
433 "horizontal mininum size specified! Using expand.");
438 ERR("homogeneous table based on item size but no "
439 "vertical mininum size specified! Using expand.");
444 minw = priv->size.cols * (minw + priv->pad.h) - priv->pad.h;
445 minh = priv->size.rows * (minh + priv->pad.v) - priv->pad.v;
447 priv->hints_changed = 0;
448 priv->expand_h = expand_h;
449 priv->expand_v = expand_v;
451 if ((minw > 0 ) || (minh > 0))
452 evas_object_size_hint_min_set(o, minw, minh);
458 _evas_object_table_calculate_layout_homogeneous_sizes_item(const Evas_Object *o, const Evas_Object_Table_Data *priv, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
460 Evas_Coord minw, minh;
461 Eina_Bool expand_h, expand_v;
463 evas_object_size_hint_min_get(o, &minw, &minh);
464 expand_h = priv->expand_h;
465 expand_v = priv->expand_v;
471 *x += (*w - minw) * priv->align.h;
479 *y += (*h - minh) * priv->align.v;
485 _evas_object_table_calculate_layout_homogeneous_sizes(const Evas_Object *o, const Evas_Object_Table_Data *priv, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h, Evas_Coord *cellw, Evas_Coord *cellh)
487 evas_object_geometry_get(o, x, y, w, h);
488 if (priv->homogeneous == EVAS_OBJECT_TABLE_HOMOGENEOUS_ITEM)
489 _evas_object_table_calculate_layout_homogeneous_sizes_item
490 (o, priv, x, y, w, h);
492 *cellw = (*w + priv->size.cols - 1) / priv->size.cols;
493 *cellh = (*h + priv->size.rows - 1) / priv->size.rows;
497 _evas_object_table_calculate_layout_homogeneous(Evas_Object *o, Evas_Object_Table_Data *priv)
499 Evas_Coord x, y, w, h, cellw, cellh;
501 Evas_Object_Table_Option *opt;
503 _evas_object_table_calculate_layout_homogeneous_sizes
504 (o, priv, &x, &y, &w, &h, &cellw, &cellh);
506 EINA_LIST_FOREACH(priv->children, l, opt)
508 Evas_Object *child = opt->obj;
509 Evas_Coord cx, cy, cw, ch;
511 cx = x + opt->col * (cellw + priv->pad.h);
512 cy = y + opt->row * (cellh + priv->pad.v);
514 cw = opt->colspan * cellw - priv->pad.h;
515 ch = opt->rowspan * cellh - priv->pad.v;
517 _evas_object_table_calculate_cell(opt, &cx, &cy, &cw, &ch);
519 if (priv->is_mirrored)
521 evas_object_move(opt->obj, x + w - (cx - x + cw), cy);
525 evas_object_move(child, cx, cy);
527 evas_object_resize(child, cw, ch);
532 _evas_object_table_smart_calculate_homogeneous(Evas_Object *o, Evas_Object_Table_Data *priv)
534 if (priv->hints_changed)
535 _evas_object_table_calculate_hints_homogeneous(o, priv);
536 _evas_object_table_calculate_layout_homogeneous(o, priv);
540 _evas_object_table_count_expands(const Eina_Bool *expands, int start, int end)
542 const Eina_Bool *itr = expands + start, *itr_end = expands + end;
545 for (; itr < itr_end; itr++)
553 _evas_object_table_sum_sizes(const Evas_Coord *sizes, int start, int end)
555 const Evas_Coord *itr = sizes + start, *itr_end = sizes + end;
558 for (; itr < itr_end; itr++)
565 _evas_object_table_sizes_calc_noexpand(Evas_Coord *sizes, int start, int end, Evas_Coord space)
567 Evas_Coord *itr = sizes + start, *itr_end = sizes + end - 1;
571 /* XXX move to fixed point math and spread errors among cells */
573 step = space / units;
574 for (; itr < itr_end; itr++)
577 *itr += space - step * (units - 1);
581 _evas_object_table_sizes_calc_expand(Evas_Coord *sizes, int start, int end, Evas_Coord space, const Eina_Bool *expands, int expand_count)
583 Evas_Coord *itr = sizes + start, *itr_end = sizes + end;
584 const Eina_Bool *itr_expand = expands + start;
585 Evas_Coord step, last_space;
587 /* XXX move to fixed point math and spread errors among cells */
588 step = space / expand_count;
589 last_space = space - step * (expand_count - 1);
591 for (; itr < itr_end; itr++, itr_expand++)
595 if (expand_count > 0)
606 _evas_object_table_calculate_hints_regular(Evas_Object *o, Evas_Object_Table_Data *priv)
608 Evas_Object_Table_Option *opt;
609 Evas_Object_Table_Cache *c;
614 priv->cache = _evas_object_table_cache_alloc
615 (priv->size.cols, priv->size.rows);
620 _evas_object_table_cache_reset(priv);
622 /* cache interesting data */
623 EINA_LIST_FOREACH(priv->children, l, opt)
625 Evas_Object *child = opt->obj;
626 double weightw, weighth;
628 evas_object_size_hint_min_get(child, &opt->min.w, &opt->min.h);
629 evas_object_size_hint_max_get(child, &opt->max.w, &opt->max.h);
630 evas_object_size_hint_padding_get
631 (child, &opt->pad.l, &opt->pad.r, &opt->pad.t, &opt->pad.b);
632 evas_object_size_hint_align_get(child, &opt->align.h, &opt->align.v);
633 evas_object_size_hint_weight_get(child, &weightw, &weighth);
636 if ((weightw > 0.0) &&
638 ((opt->max.w > -1) && (opt->min.w < opt->max.w))))
642 if ((weighth > 0.0) &&
644 ((opt->max.h > -1) && (opt->min.h < opt->max.h))))
648 if (opt->align.h < 0.0)
654 if (opt->align.v < 0.0)
661 memset(c->expands.h + opt->col, 1, opt->colspan);
663 memset(c->expands.v + opt->row, 1, opt->rowspan);
666 /* calculate sizes for each row and column */
667 EINA_LIST_FOREACH(priv->children, l, opt)
669 Evas_Coord tot, need;
671 /* handle horizontal */
672 tot = _evas_object_table_sum_sizes(c->sizes.h, opt->col, opt->end_col);
673 need = opt->min.w + opt->pad.l + opt->pad.r;
676 Evas_Coord space = need - tot;
679 count = _evas_object_table_count_expands
680 (c->expands.h, opt->col, opt->end_col);
683 _evas_object_table_sizes_calc_expand
684 (c->sizes.h, opt->col, opt->end_col, space,
685 c->expands.h, count);
687 _evas_object_table_sizes_calc_noexpand
688 (c->sizes.h, opt->col, opt->end_col, space);
691 /* handle vertical */
692 tot = _evas_object_table_sum_sizes(c->sizes.v, opt->row, opt->end_row);
693 need = opt->min.h + opt->pad.t + opt->pad.b;
694 if (tot < opt->min.h)
696 Evas_Coord space = need - tot;
699 count = _evas_object_table_count_expands
700 (c->expands.v, opt->row, opt->end_row);
703 _evas_object_table_sizes_calc_expand
704 (c->sizes.v, opt->row, opt->end_row, space,
705 c->expands.v, count);
707 _evas_object_table_sizes_calc_noexpand
708 (c->sizes.v, opt->row, opt->end_row, space);
712 c->total.expands.h = _evas_object_table_count_expands
713 (c->expands.h, 0, priv->size.cols);
714 c->total.expands.v = _evas_object_table_count_expands
715 (c->expands.v, 0, priv->size.rows);
717 c->total.min.w = _evas_object_table_sum_sizes
718 (c->sizes.h, 0, priv->size.cols);
719 c->total.min.h = _evas_object_table_sum_sizes
720 (c->sizes.v, 0, priv->size.rows);
722 c->total.min.w += priv->pad.h * (priv->size.cols - 1);
723 c->total.min.h += priv->pad.v * (priv->size.rows - 1);
725 if ((c->total.min.w > 0) || (c->total.min.h > 0))
726 evas_object_size_hint_min_set(o, c->total.min.w, c->total.min.h);
732 _evas_object_table_calculate_layout_regular(Evas_Object *o, Evas_Object_Table_Data *priv)
734 Evas_Object_Table_Option *opt;
735 Evas_Object_Table_Cache *c;
737 Evas_Coord *cols = NULL, *rows = NULL;
738 Evas_Coord x, y, w, h;
740 evas_object_geometry_get(o, &x, &y, &w, &h);
743 /* handle horizontal */
744 if ((c->total.expands.h <= 0) || (c->total.min.w >= w))
746 x += (w - c->total.min.w) * priv->align.h;
752 int size = priv->size.cols * sizeof(Evas_Coord);
756 ERR("Could not allocate temp columns (%d bytes): %s",
757 size, strerror(errno));
760 memcpy(cols, c->sizes.h, size);
761 _evas_object_table_sizes_calc_expand
762 (cols, 0, priv->size.cols, w - c->total.min.w,
763 c->expands.h, c->total.expands.h);
766 /* handle vertical */
767 if ((c->total.expands.v <= 0) || (c->total.min.h >= h))
769 y += (h - c->total.min.h) * priv->align.v;
775 int size = priv->size.rows * sizeof(Evas_Coord);
779 ERR("could not allocate temp rows (%d bytes): %s",
780 size, strerror(errno));
783 memcpy(rows, c->sizes.v, size);
784 _evas_object_table_sizes_calc_expand
785 (rows, 0, priv->size.rows, h - c->total.min.h,
786 c->expands.v, c->total.expands.v);
789 EINA_LIST_FOREACH(priv->children, l, opt)
791 Evas_Object *child = opt->obj;
792 Evas_Coord cx, cy, cw, ch;
794 cx = x + opt->col * (priv->pad.h);
795 cx += _evas_object_table_sum_sizes(cols, 0, opt->col);
796 cw = _evas_object_table_sum_sizes(cols, opt->col, opt->end_col);
798 cy = y + opt->row * (priv->pad.v);
799 cy += _evas_object_table_sum_sizes(rows, 0, opt->row);
800 ch = _evas_object_table_sum_sizes(rows, opt->row, opt->end_row);
802 _evas_object_table_calculate_cell(opt, &cx, &cy, &cw, &ch);
804 if (priv->is_mirrored)
806 evas_object_move(opt->obj, x + w - (cx - x + cw), cy);
810 evas_object_move(child, cx, cy);
812 evas_object_resize(child, cw, ch);
816 if (cols != c->sizes.h)
818 if (cols) free(cols);
820 if (rows != c->sizes.v)
822 if (rows) free(rows);
827 _evas_object_table_smart_calculate_regular(Evas_Object *o, Evas_Object_Table_Data *priv)
829 if (priv->hints_changed)
830 _evas_object_table_calculate_hints_regular(o, priv);
831 _evas_object_table_calculate_layout_regular(o, priv);
834 EVAS_SMART_SUBCLASS_NEW("Evas_Object_Table", _evas_object_table,
835 Evas_Smart_Class, Evas_Smart_Class,
836 evas_object_smart_clipped_class_get, NULL)
839 _evas_object_table_smart_add(Evas_Object *o)
841 EVAS_SMART_DATA_ALLOC(o, Evas_Object_Table_Data)
850 priv->homogeneous = EVAS_OBJECT_TABLE_HOMOGENEOUS_NONE;
851 priv->hints_changed = 1;
855 _evas_object_table_parent_sc->add(o);
859 _evas_object_table_smart_del(Evas_Object *o)
861 EVAS_OBJECT_TABLE_DATA_GET(o, priv);
867 Evas_Object_Table_Option *opt = l->data;
868 _evas_object_table_child_disconnect(o, opt->obj);
869 _evas_object_table_option_del(opt->obj);
871 l = eina_list_remove_list(l, l);
876 _evas_object_table_cache_free(priv->cache);
880 _evas_object_table_parent_sc->del(o);
884 _evas_object_table_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
887 evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
888 if ((ow == w) && (oh == h)) return;
889 evas_object_smart_changed(o);
893 _evas_object_table_smart_calculate(Evas_Object *o)
895 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
897 if ((priv->size.cols < 1) || (priv->size.rows < 1))
899 DBG("Nothing to do: cols=%d, rows=%d",
900 priv->size.cols, priv->size.rows);
904 if (priv->homogeneous)
905 _evas_object_table_smart_calculate_homogeneous(o, priv);
907 _evas_object_table_smart_calculate_regular(o, priv);
911 _evas_object_table_smart_set_user(Evas_Smart_Class *sc)
913 sc->add = _evas_object_table_smart_add;
914 sc->del = _evas_object_table_smart_del;
915 sc->resize = _evas_object_table_smart_resize;
916 sc->calculate = _evas_object_table_smart_calculate;
920 * Create a new table.
922 * It's set to non-homogeneous by default, add children with
923 * evas_object_table_pack().
926 evas_object_table_add(Evas *evas)
928 return evas_object_smart_add(evas, _evas_object_table_smart_class_new());
932 * Create a table that is child of a given element @a parent.
934 * @see evas_object_table_add()
937 evas_object_table_add_to(Evas_Object *parent)
942 evas = evas_object_evas_get(parent);
943 o = evas_object_table_add(evas);
944 evas_object_smart_member_add(o, parent);
949 * Set how this table should layout children.
951 * @todo consider aspect hint and respect it.
953 * @par EVAS_OBJECT_TABLE_HOMOGENEOUS_NONE
954 * If table does not use homogeneous mode then columns and rows will
955 * be calculated based on hints of individual cells. This operation
956 * mode is more flexible, but more complex and heavy to calculate as
957 * well. @b Weight properties are handled as a boolean
958 * expand. Negative alignment will be considered as 0.5.
960 * @todo @c EVAS_OBJECT_TABLE_HOMOGENEOUS_NONE should balance weight.
962 * @par EVAS_OBJECT_TABLE_HOMOGENEOUS_TABLE
963 * When homogeneous is relative to table the own table size is divided
964 * equally among children, filling the whole table area. That is, if
965 * table has @c WIDTH and @c COLUMNS, each cell will get <tt>WIDTH /
966 * COLUMNS</tt> pixels. If children have minimum size that is larger
967 * than this amount (including padding), then it will overflow and be
968 * aligned respecting the alignment hint, possible overlapping sibling
969 * cells. @b Weight hint is used as a boolean, if greater than zero it
970 * will make the child expand in that axis, taking as much space as
971 * possible (bounded to maximum size hint). Negative alignment will be
974 * @par EVAS_OBJECT_TABLE_HOMOGENEOUS_ITEM
975 * When homogeneous is relative to item it means the greatest minimum
976 * cell size will be used. That is, if no element is set to expand,
977 * the table will have its contents to a minimum size, the bounding
978 * box of all these children will be aligned relatively to the table
979 * object using evas_object_table_align_get(). If the table area is
980 * too small to hold this minimum bounding box, then the objects will
981 * keep their size and the bounding box will overflow the box area,
982 * still respecting the alignment. @b Weight hint is used as a
983 * boolean, if greater than zero it will make that cell expand in that
984 * axis, toggling the <b>expand mode</b>, which makes the table behave
985 * much like @b EVAS_OBJECT_TABLE_HOMOGENEOUS_TABLE, except that the
986 * bounding box will overflow and items will not overlap siblings. If
987 * no minimum size is provided at all then the table will fallback to
988 * expand mode as well.
991 evas_object_table_homogeneous_set(Evas_Object *o, Evas_Object_Table_Homogeneous_Mode homogeneous)
993 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
994 if (priv->homogeneous == homogeneous)
996 priv->homogeneous = homogeneous;
997 _evas_object_table_cache_invalidate(priv);
998 evas_object_smart_changed(o);
1002 * Get the current layout homogeneous mode.
1004 * @see evas_object_table_homogeneous_set()
1006 EAPI Evas_Object_Table_Homogeneous_Mode
1007 evas_object_table_homogeneous_get(const Evas_Object *o)
1009 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1010 return priv->homogeneous;
1014 * Set the alignment of the whole bounding box of contents.
1017 evas_object_table_align_set(Evas_Object *o, double horizontal, double vertical)
1019 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
1020 if (priv->align.h == horizontal && priv->align.v == vertical)
1022 priv->align.h = horizontal;
1023 priv->align.v = vertical;
1024 evas_object_smart_changed(o);
1028 * Get alignment of the whole bounding box of contents.
1031 evas_object_table_align_get(const Evas_Object *o, double *horizontal, double *vertical)
1033 EVAS_OBJECT_TABLE_DATA_GET(o, priv);
1036 if (horizontal) *horizontal = priv->align.h;
1037 if (vertical) *vertical = priv->align.v;
1041 if (horizontal) *horizontal = 0.5;
1042 if (vertical) *vertical = 0.5;
1047 * Set padding between cells.
1050 evas_object_table_padding_set(Evas_Object *o, Evas_Coord horizontal, Evas_Coord vertical)
1052 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
1053 if (priv->pad.h == horizontal && priv->pad.v == vertical)
1055 priv->pad.h = horizontal;
1056 priv->pad.v = vertical;
1057 _evas_object_table_cache_invalidate(priv);
1058 evas_object_smart_changed(o);
1062 * Get padding between cells.
1065 evas_object_table_padding_get(const Evas_Object *o, Evas_Coord *horizontal, Evas_Coord *vertical)
1067 EVAS_OBJECT_TABLE_DATA_GET(o, priv);
1070 if (horizontal) *horizontal = priv->pad.h;
1071 if (vertical) *vertical = priv->pad.v;
1075 if (horizontal) *horizontal = 0;
1076 if (vertical) *vertical = 0;
1081 * Add a new child to a table object.
1083 * @param o The given table object.
1084 * @param child The child object to add.
1085 * @param col relative-horizontal position to place child.
1086 * @param row relative-vertical position to place child.
1087 * @param colspan how many relative-horizontal position to use for this child.
1088 * @param rowspan how many relative-vertical position to use for this child.
1090 * @return 1 on success, 0 on failure.
1093 evas_object_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
1095 Evas_Object_Table_Option *opt;
1097 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1110 opt = _evas_object_table_option_get(child);
1113 ERR("cannot add object that is already part of a table!");
1117 opt = malloc(sizeof(*opt));
1120 ERR("could not allocate table option data.");
1127 opt->colspan = colspan;
1128 opt->rowspan = rowspan;
1129 opt->end_col = col + colspan;
1130 opt->end_row = row + rowspan;
1144 priv->children = eina_list_append(priv->children, opt);
1146 if (priv->size.cols < opt->end_col)
1147 priv->size.cols = opt->end_col;
1148 if (priv->size.rows < opt->end_row)
1149 priv->size.rows = opt->end_row;
1151 _evas_object_table_option_set(child, opt);
1152 evas_object_smart_member_add(child, o);
1153 _evas_object_table_child_connect(o, child);
1154 _evas_object_table_cache_invalidate(priv);
1155 evas_object_smart_changed(o);
1161 _evas_object_table_remove_opt(Evas_Object_Table_Data *priv, Evas_Object_Table_Option *opt)
1164 int max_row, max_col, was_greatest;
1172 Evas_Object_Table_Option *cur_opt = l->data;
1176 if (max_col < cur_opt->end_col)
1177 max_col = cur_opt->end_col;
1178 if (max_row < cur_opt->end_row)
1179 max_row = cur_opt->end_row;
1185 Eina_List *tmp = l->next;
1186 priv->children = eina_list_remove_list(priv->children, l);
1188 if ((priv->size.cols > opt->end_col) &&
1189 (priv->size.rows > opt->end_row))
1201 priv->size.cols = max_col;
1202 priv->size.rows = max_row;
1207 * Remove child from table.
1209 * @note removing a child will immediately call a walk over children in order
1210 * to recalculate numbers of columns and rows. If you plan to remove
1211 * all children, use evas_object_table_clear() instead.
1213 * @return 1 on success, 0 on failure.
1216 evas_object_table_unpack(Evas_Object *o, Evas_Object *child)
1218 Evas_Object_Table_Option *opt;
1220 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1222 if (o != evas_object_smart_parent_get(child))
1224 ERR("cannot unpack child from incorrect table!");
1228 opt = _evas_object_table_option_del(child);
1231 ERR("cannot unpack child with no packing option!");
1235 _evas_object_table_child_disconnect(o, child);
1236 _evas_object_table_remove_opt(priv, opt);
1237 evas_object_smart_member_del(child);
1239 _evas_object_table_cache_invalidate(priv);
1240 evas_object_smart_changed(o);
1246 * Faster way to remove all child objects from a table object.
1248 * @param o The given table object.
1249 * @param clear if true, it will delete just removed children.
1252 evas_object_table_clear(Evas_Object *o, Eina_Bool clear)
1254 Evas_Object_Table_Option *opt;
1256 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
1258 EINA_LIST_FREE(priv->children, opt)
1260 _evas_object_table_child_disconnect(o, opt->obj);
1261 _evas_object_table_option_del(opt->obj);
1262 evas_object_smart_member_del(opt->obj);
1264 evas_object_del(opt->obj);
1267 priv->size.cols = 0;
1268 priv->size.rows = 0;
1269 _evas_object_table_cache_invalidate(priv);
1270 evas_object_smart_changed(o);
1274 * Get the number of columns and rows this table takes.
1276 * @note columns and rows are virtual entities, one can specify a table
1277 * with a single object that takes 4 columns and 5 rows. The only
1278 * difference for a single cell table is that paddings will be
1279 * accounted proportionally.
1282 evas_object_table_col_row_size_get(const Evas_Object *o, int *cols, int *rows)
1284 EVAS_OBJECT_TABLE_DATA_GET(o, priv);
1287 if (cols) *cols = priv->size.cols;
1288 if (rows) *rows = priv->size.rows;
1292 if (cols) *cols = -1;
1293 if (rows) *rows = -1;
1298 * Get an iterator to walk the list of children for the table.
1300 * @note Do not remove or delete objects while walking the list.
1302 EAPI Eina_Iterator *
1303 evas_object_table_iterator_new(const Evas_Object *o)
1305 Evas_Object_Table_Iterator *it;
1307 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1309 if (!priv->children) return NULL;
1311 it = calloc(1, sizeof(Evas_Object_Table_Iterator));
1312 if (!it) return NULL;
1314 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1316 it->real_iterator = eina_list_iterator_new(priv->children);
1319 it->iterator.next = FUNC_ITERATOR_NEXT(_evas_object_table_iterator_next);
1320 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_evas_object_table_iterator_get_container);
1321 it->iterator.free = FUNC_ITERATOR_FREE(_evas_object_table_iterator_free);
1323 return &it->iterator;
1327 * Get an accessor to get random access to the list of children for the table.
1329 * @note Do not remove or delete objects while walking the list.
1331 EAPI Eina_Accessor *
1332 evas_object_table_accessor_new(const Evas_Object *o)
1334 Evas_Object_Table_Accessor *it;
1336 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1338 if (!priv->children) return NULL;
1340 it = calloc(1, sizeof(Evas_Object_Table_Accessor));
1341 if (!it) return NULL;
1343 EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
1345 it->real_accessor = eina_list_accessor_new(priv->children);
1348 it->accessor.get_at = FUNC_ACCESSOR_GET_AT(_evas_object_table_accessor_get_at);
1349 it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(_evas_object_table_accessor_get_container);
1350 it->accessor.free = FUNC_ACCESSOR_FREE(_evas_object_table_accessor_free);
1352 return &it->accessor;
1356 * Get the list of children for the table.
1358 * @note This is a duplicate of the list kept by the table internally.
1359 * It's up to the user to destroy it when it no longer needs it.
1360 * It's possible to remove objects from the table when walking this
1361 * list, but these removals won't be reflected on it.
1364 evas_object_table_children_get(const Evas_Object *o)
1366 Eina_List *new_list = NULL, *l;
1367 Evas_Object_Table_Option *opt;
1369 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1371 EINA_LIST_FOREACH(priv->children, l, opt)
1372 new_list = eina_list_append(new_list, opt->obj);
1378 * Get a child from the table using its coordinates
1380 * @note This does not take into account col/row spanning
1383 evas_object_table_child_get(const Evas_Object *o, unsigned short col, unsigned short row)
1386 Evas_Object_Table_Option *opt;
1388 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1390 EINA_LIST_FOREACH(priv->children, l, opt)
1391 if (opt->col == col && opt->row == row)
1397 * Gets the mirrored mode of the table. In mirrored mode the table items go
1398 * from right to left instead of left to right. That is, 1,1 is top right, not
1401 * @param obj The table object.
1402 * @return EINA_TRUE if it's a mirrored table, EINA_FALSE otherwise.
1406 evas_object_table_mirrored_get(const Evas_Object *obj)
1408 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(obj, priv, EINA_FALSE);
1410 return priv->is_mirrored;
1414 * Sets the mirrored mode of the table. In mirrored mode the table items go
1415 * from right to left instead of left to right. That is, 1,1 is top right, not
1418 * @param obj The table object.
1419 * @param mirrored the mirrored mode to set
1423 evas_object_table_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
1425 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(obj, priv);
1426 if (priv->is_mirrored != mirrored)
1428 priv->is_mirrored = mirrored;
1429 _evas_object_table_smart_calculate_regular(obj, priv);