summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYeongjong Lee <cleanlyj@naver.com>2019-02-27 14:45:27 -0500
committerMike Blumenkrantz <zmike@samsung.com>2019-02-27 14:45:27 -0500
commit5572000f1a02ed1107d3757d7ca06727c1217813 (patch)
treecc902b9deccb83cf53bcbc1490dbb9272f6f9cfb
parent665f8877e93aa729a4d2eb8b532e69ad3580435b (diff)
efl_ui_table: refactor layout_update
Summary: There are three reasons to refactor layout_update of Efl.Ui.Table. === 1. Inconsistency of hint behavior. === Some hint property is often not respected. for example, hint_min is ignored in Table when it is used with hint_max even if hint_weight is 0. hint_aspect is always ignored in Table. The ambiguous behavior make it hard to layout widgets in container. of course, we documented 'it's just a hint that should be used whenever appropriate.' but i don't think it means that 'hint API is sometimes respected and we also don't know when that API is respected.'. at least there is rule for consistent behavior and we should be able to explain why a widget is located here and why some hint property is ignored. So, i'll suggest priority of hint property. this refactoring support following priority. 1) HintMin 2) HintMin + HintAspect 3) HintMargin 4) HintMax 5) HintAspect 6) HintWeight, HintFill 7) HintAlign ref T5487 Please check with unit test D7840 === 2. To Enhance usability. === Efl.Ui.Table is using homogeneous mode of evas_table which have same columns, rows size. but i think a table can generally change columns, rows size and we can provide homogeneous mode option.(D7892) In this patch - table columns(rows) min size is decided by maximum size among its cells width(height) min size. - table columns(rows) weight is decided by maximum weight among its cells horizontal(vertical) weight. Also, pack_align is implemented. it is used if no item has a weight. === 3. To remove internal evas_table. === This is low priority work. however, i guess is is necessary for lightweight container widget. there are two size_hint callback to adjust table size and efl_canvas_group_calculate is called twice when it is resized. This patch is first step to remove internal evas_table. Test Plan: make check elementary_test -to 'efl.ui.table' Reviewers: jpeg, Jaehyun_Cho, zmike Reviewed By: zmike Subscribers: zmike, cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T5487 Differential Revision: https://phab.enlightenment.org/D7841
-rw-r--r--src/Makefile_Elementary.am3
-rw-r--r--src/bin/elementary/test_ui_table.c26
-rw-r--r--src/lib/elementary/efl_ui_box_layout.c342
-rw-r--r--src/lib/elementary/efl_ui_container_layout.c158
-rw-r--r--src/lib/elementary/efl_ui_container_layout.h42
-rw-r--r--src/lib/elementary/efl_ui_table.c44
-rw-r--r--src/lib/elementary/efl_ui_table.eo1
-rw-r--r--src/lib/elementary/efl_ui_table_layout.c294
-rw-r--r--src/lib/elementary/efl_ui_table_private.h5
-rw-r--r--src/lib/elementary/meson.build3
10 files changed, 653 insertions, 265 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index c020b343d4..98d953df9c 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -826,6 +826,8 @@ lib_elementary_libelementary_la_SOURCES = \
826 lib/elementary/els_cursor.c \ 826 lib/elementary/els_cursor.c \
827 lib/elementary/els_tooltip.c \ 827 lib/elementary/els_tooltip.c \
828 lib/elementary/elu_ews_wm.c \ 828 lib/elementary/elu_ews_wm.c \
829 lib/elementary/efl_ui_container_layout.c \
830 lib/elementary/efl_ui_container_layout.h \
829 lib/elementary/efl_ui_box.c \ 831 lib/elementary/efl_ui_box.c \
830 lib/elementary/efl_ui_box_flow.c \ 832 lib/elementary/efl_ui_box_flow.c \
831 lib/elementary/efl_ui_box_stack.c \ 833 lib/elementary/efl_ui_box_stack.c \
@@ -838,6 +840,7 @@ lib_elementary_libelementary_la_SOURCES = \
838 lib/elementary/efl_ui_anchor_popup.c \ 840 lib/elementary/efl_ui_anchor_popup.c \
839 lib/elementary/efl_ui_table.c \ 841 lib/elementary/efl_ui_table.c \
840 lib/elementary/efl_ui_table_static.c \ 842 lib/elementary/efl_ui_table_static.c \
843 lib/elementary/efl_ui_table_layout.c \
841 lib/elementary/efl_ui_table_private.h \ 844 lib/elementary/efl_ui_table_private.h \
842 lib/elementary/efl_ui_text.c \ 845 lib/elementary/efl_ui_text.c \
843 lib/elementary/efl_ui_text_factory_images.c \ 846 lib/elementary/efl_ui_text_factory_images.c \
diff --git a/src/bin/elementary/test_ui_table.c b/src/bin/elementary/test_ui_table.c
index 098fe139b7..2f698f103c 100644
--- a/src/bin/elementary/test_ui_table.c
+++ b/src/bin/elementary/test_ui_table.c
@@ -34,31 +34,31 @@ weights_cb(void *data, const Efl_Event *event)
34 { 34 {
35 case NONE: 35 case NONE:
36 efl_gfx_hint_align_set(table, 0.5, 0.5); 36 efl_gfx_hint_align_set(table, 0.5, 0.5);
37 for (int i = 0; i < 7; i++) 37 for (int i = 1; i < 7; i++)
38 efl_gfx_hint_weight_set(objects[i], 0, 0); 38 efl_gfx_hint_weight_set(objects[i], 0, 0);
39 break; 39 break;
40 case NONE_BUT_FILL: 40 case NONE_BUT_FILL:
41 efl_gfx_hint_fill_set(table, EINA_TRUE, EINA_TRUE); 41 efl_gfx_hint_fill_set(table, EINA_TRUE, EINA_TRUE);
42 for (int i = 0; i < 7; i++) 42 for (int i = 1; i < 7; i++)
43 efl_gfx_hint_weight_set(objects[i], 0, 0); 43 efl_gfx_hint_weight_set(objects[i], 0, 0);
44 break; 44 break;
45 case EQUAL: 45 case EQUAL:
46 efl_gfx_hint_align_set(table, 0.5, 0.5); 46 efl_gfx_hint_align_set(table, 0.5, 0.5);
47 for (int i = 0; i < 7; i++) 47 for (int i = 1; i < 7; i++)
48 efl_gfx_hint_weight_set(objects[i], 1, 1); 48 efl_gfx_hint_weight_set(objects[i], 1, 1);
49 break; 49 break;
50 case ONE: 50 case ONE:
51 efl_gfx_hint_align_set(table, 0.5, 0.5); 51 efl_gfx_hint_align_set(table, 0.5, 0.5);
52 for (int i = 0; i < 6; i++) 52 for (int i = 1; i < 7; i++)
53 efl_gfx_hint_weight_set(objects[i], 0, 0); 53 efl_gfx_hint_weight_set(objects[i], 0, 0);
54 efl_gfx_hint_weight_set(objects[6], 1, 1); 54 efl_gfx_hint_weight_set(objects[2], 1, 1);
55 break; 55 break;
56 case TWO: 56 case TWO:
57 efl_gfx_hint_align_set(table, 0.5, 0.5); 57 efl_gfx_hint_align_set(table, 0.5, 0.5);
58 for (int i = 0; i < 5; i++) 58 for (int i = 1; i < 7; i++)
59 efl_gfx_hint_weight_set(objects[i], 0, 0); 59 efl_gfx_hint_weight_set(objects[i], 0, 0);
60 efl_gfx_hint_weight_set(objects[5], 1, 1); 60 efl_gfx_hint_weight_set(objects[2], 1, 1);
61 efl_gfx_hint_weight_set(objects[6], 1, 1); 61 efl_gfx_hint_weight_set(objects[3], 1, 1);
62 break; 62 break;
63 case CUSTOM: 63 case CUSTOM:
64 efl_object_override(table, &custom_layout_ops); 64 efl_object_override(table, &custom_layout_ops);
@@ -89,11 +89,11 @@ margin_slider_cb(void *data, const Efl_Event *event)
89} 89}
90 90
91static void 91static void
92btnmargins_slider_cb(void *data, const Efl_Event *event) 92btnmargins_slider_cb(void *data EINA_UNUSED, const Efl_Event *event)
93{ 93{
94 int val = elm_slider_value_get(event->object); 94 int val = elm_slider_value_get(event->object);
95 for (int i = 1; i < 7; i++) 95 for (int i = 1; i < 7; i++)
96 efl_gfx_hint_margin_set(data, val, val, val, val); 96 efl_gfx_hint_margin_set(objects[i], val, val, val, val);
97} 97}
98 98
99static void 99static void
@@ -333,7 +333,7 @@ test_ui_table(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_
333 efl_event_callback_add(o, EFL_UI_SLIDER_EVENT_CHANGED, padding_slider_cb, table); 333 efl_event_callback_add(o, EFL_UI_SLIDER_EVENT_CHANGED, padding_slider_cb, table);
334 elm_slider_min_max_set(o, 0, 40); 334 elm_slider_min_max_set(o, 0, 40);
335 elm_slider_inverted_set(o, 1); 335 elm_slider_inverted_set(o, 1);
336 elm_slider_value_set(o, 10); 336 elm_slider_value_set(o, 0);
337 efl_pack(bx, o); 337 efl_pack(bx, o);
338 efl_gfx_entity_visible_set(o, 1); 338 efl_gfx_entity_visible_set(o, 1);
339 339
@@ -359,7 +359,7 @@ test_ui_table(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_
359 efl_event_callback_add(o, EFL_UI_SLIDER_EVENT_CHANGED, margin_slider_cb, table); 359 efl_event_callback_add(o, EFL_UI_SLIDER_EVENT_CHANGED, margin_slider_cb, table);
360 elm_slider_min_max_set(o, 0, 40); 360 elm_slider_min_max_set(o, 0, 40);
361 elm_slider_inverted_set(o, 1); 361 elm_slider_inverted_set(o, 1);
362 elm_slider_value_set(o, 10); 362 elm_slider_value_set(o, 0);
363 efl_pack(bx, o); 363 efl_pack(bx, o);
364 efl_gfx_entity_visible_set(o, 1); 364 efl_gfx_entity_visible_set(o, 1);
365 365
@@ -386,7 +386,7 @@ test_ui_table(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_
386 efl_event_callback_add(o, EFL_UI_SLIDER_EVENT_CHANGED, btnmargins_slider_cb, table); 386 efl_event_callback_add(o, EFL_UI_SLIDER_EVENT_CHANGED, btnmargins_slider_cb, table);
387 elm_slider_min_max_set(o, 0, 40); 387 elm_slider_min_max_set(o, 0, 40);
388 elm_slider_inverted_set(o, 1); 388 elm_slider_inverted_set(o, 1);
389 elm_slider_value_set(o, 10); 389 elm_slider_value_set(o, 0);
390 efl_pack(bx, o); 390 efl_pack(bx, o);
391 efl_gfx_entity_visible_set(o, 1); 391 efl_gfx_entity_visible_set(o, 1);
392 392
diff --git a/src/lib/elementary/efl_ui_box_layout.c b/src/lib/elementary/efl_ui_box_layout.c
index 90c5d1b42f..bc9ea63c86 100644
--- a/src/lib/elementary/efl_ui_box_layout.c
+++ b/src/lib/elementary/efl_ui_box_layout.c
@@ -1,6 +1,7 @@
1#define EFL_GFX_HINT_PROTECTED 1#define EFL_GFX_HINT_PROTECTED
2 2
3#include "efl_ui_box_private.h" 3#include "efl_ui_box_private.h"
4#include "efl_ui_container_layout.h"
4 5
5// FIXME: handle RTL? just invert the horizontal order? 6// FIXME: handle RTL? just invert the horizontal order?
6 7
@@ -11,65 +12,19 @@ struct _Item_Calc
11 EINA_INLIST; 12 EINA_INLIST;
12 13
13 Evas_Object *obj; 14 Evas_Object *obj;
14 double weight[2]; 15 double weight_factor;
15 double align[2]; 16 Efl_Ui_Container_Item_Hints hints[2]; /* 0 is x-axis, 1 is y-axis */
16 double space[2];
17 double comp_factor;
18 Eina_Bool fill[2];
19 Eina_Size2D max, min, aspect;
20 int pad[4];
21 Efl_Gfx_Hint_Aspect aspect_type;
22 int id;
23}; 17};
24 18
25static int 19static int
26weight_sort_cb(const void *l1, const void *l2) 20_weight_sort_cb(const void *l1, const void *l2)
27{ 21{
28 Item_Calc *it1, *it2; 22 Item_Calc *it1, *it2;
29 23
30 it1 = EINA_INLIST_CONTAINER_GET(l1, Item_Calc); 24 it1 = EINA_INLIST_CONTAINER_GET(l1, Item_Calc);
31 it2 = EINA_INLIST_CONTAINER_GET(l2, Item_Calc); 25 it2 = EINA_INLIST_CONTAINER_GET(l2, Item_Calc);
32 26
33 return it2->comp_factor <= it1->comp_factor ? -1 : 1; 27 return it2->weight_factor <= it1->weight_factor ? -1 : 1;
34}
35
36static inline void
37_min_max_calc(Item_Calc *item, int *cw, int *ch, Eina_Bool aspect_check)
38{
39 int w = *cw, h = *ch;
40
41 if (aspect_check)
42 {
43 w = h * item->aspect.w / item->aspect.h;
44 if (w > *cw)
45 {
46 w = *cw;
47 h = w * item->aspect.h / item->aspect.w;
48 }
49 }
50
51 if (w > item->max.w)
52 {
53 w = item->max.w;
54 if (aspect_check) h = w * item->aspect.h / item->aspect.w;
55 }
56 if (h > item->max.h)
57 {
58 h = item->max.h;
59 if (aspect_check) w = h * item->aspect.w / item->aspect.h;
60 }
61 if (w < item->min.w)
62 {
63 w = item->min.w;
64 if (aspect_check) h = w * item->aspect.h / item->aspect.w;
65 }
66 if (h < item->min.h)
67 {
68 h = item->min.h;
69 if (aspect_check) w = h * item->aspect.w / item->aspect.h;
70 }
71 *cw = w;
72 *ch = h;
73} 28}
74 29
75void 30void
@@ -77,37 +32,17 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
77{ 32{
78 Efl_Ui_Box_Data *pd = efl_data_scope_get(ui_box, EFL_UI_BOX_CLASS); 33 Efl_Ui_Box_Data *pd = efl_data_scope_get(ui_box, EFL_UI_BOX_CLASS);
79 Evas_Object_Box_Option *opt; 34 Evas_Object_Box_Option *opt;
80 Evas_Object *o;
81 Eina_List *li; 35 Eina_List *li;
82 Eina_Inlist *inlist = NULL; 36 Eina_Inlist *inlist = NULL;
83 int wantw = 0, wanth = 0; // requested size
84 Eina_Rect boxs;
85 Item_Calc *items, *item; 37 Item_Calc *items, *item;
86 Eina_Bool horiz = efl_ui_dir_is_horizontal(pd->dir, EINA_FALSE); 38 Efl_Ui_Container_Item_Hints *hints, *hint;
87 int id = 0, count, boxl = 0, boxr = 0, boxt = 0, boxb = 0; 39 Eina_Bool axis = !efl_ui_dir_is_horizontal(pd->dir, EINA_FALSE);
88 int length, want, pad; 40 Eina_Bool r_axis = !axis;
89 double cur_pos, weight[2] = { 0, 0 }, scale, mmin = 0; 41 int want[2] = { 0, 0 };
90 double box_align[2]; 42 int count, i = 0;
91 Eina_Bool box_fill[2] = { EINA_FALSE, EINA_FALSE }; 43 double cur_pos, mmin = 0, weight_sum = 0;
92 44 Efl_Ui_Container_Layout_Calc box_calc[2]; /* 0 is x-axis, 1 is y-axis */
93 boxs = efl_gfx_entity_geometry_get(ui_box); 45
94 efl_gfx_hint_margin_get(ui_box, &boxl, &boxr, &boxt, &boxb);
95 scale = efl_gfx_entity_scale_get(ui_box);
96
97 // Box align: used if "item has max size and fill" or "no item has a weight"
98 // Note: cells always expand on the orthogonal direction
99 box_align[0] = pd->align.h;
100 box_align[1] = pd->align.v;
101 if (box_align[0] < 0)
102 {
103 box_fill[0] = EINA_TRUE;
104 box_align[0] = 0.5;
105 }
106 if (box_align[1] < 0)
107 {
108 box_fill[1] = EINA_TRUE;
109 box_align[1] = 0.5;
110 }
111 46
112 count = eina_list_count(bd->children); 47 count = eina_list_count(bd->children);
113 if (!count) 48 if (!count)
@@ -116,240 +51,153 @@ _efl_ui_box_custom_layout(Efl_Ui_Box *ui_box, Evas_Object_Box_Data *bd)
116 return; 51 return;
117 } 52 }
118 53
54 _efl_ui_container_layout_init(ui_box, box_calc);
55
119 items = alloca(count * sizeof(*items)); 56 items = alloca(count * sizeof(*items));
120#ifdef DEBUG 57#ifdef DEBUG
121 memset(items, 0, count * sizeof(*items)); 58 memset(items, 0, count * sizeof(*items));
122#endif 59#endif
123 60
124 // box outer margin
125 boxs.w -= boxl + boxr;
126 boxs.h -= boxt + boxb;
127 boxs.x += boxl;
128 boxs.y += boxt;
129
130 // scan all items, get their properties, calculate total weight & min size 61 // scan all items, get their properties, calculate total weight & min size
131 EINA_LIST_FOREACH(bd->children, li, opt) 62 EINA_LIST_FOREACH(bd->children, li, opt)
132 { 63 {
133 item = &items[id]; 64 item = &items[i++];
134 o = item->obj = opt->obj; 65 item->obj = opt->obj;
135 66 hints = item->hints;
136 efl_gfx_hint_weight_get(o, &item->weight[0], &item->weight[1]);
137 efl_gfx_hint_align_get(o, &item->align[0], &item->align[1]);
138 efl_gfx_hint_margin_get(o, &item->pad[0], &item->pad[1], &item->pad[2], &item->pad[3]);
139 efl_gfx_hint_fill_get(o, &item->fill[0], &item->fill[1]);
140 item->max = efl_gfx_hint_size_max_get(o);
141 item->min = efl_gfx_hint_size_combined_min_get(o);
142 efl_gfx_hint_aspect_get(o, &item->aspect_type, &item->aspect);
143
144 if (horiz && (box_fill[0] || pd->homogeneous)) item->weight[0] = 1;
145 else if (item->weight[0] < 0) item->weight[0] = 0;
146 if (!horiz && (box_fill[1] || pd->homogeneous)) item->weight[1] = 1;
147 else if (item->weight[1] < 0) item->weight[1] = 0;
148
149 if (EINA_DBL_EQ(item->align[0], -1))
150 {
151 item->align[0] = 0.5;
152 item->fill[0] = EINA_TRUE;
153 }
154 else if (item->align[0] < 0) item->align[0] = 0;
155 else if (item->align[0] > 1) item->align[0] = 1;
156 if (EINA_DBL_EQ(item->align[1], -1))
157 {
158 item->align[1] = 0.5;
159 item->fill[1] = EINA_TRUE;
160 }
161 else if (item->align[1] < 0) item->align[1] = 0;
162 else if (item->align[1] > 1) item->align[1] = 1;
163 67
164 if (item->min.w < 0) item->min.w = 0; 68 _efl_ui_container_layout_item_init(item->obj, hints);
165 if (item->min.h < 0) item->min.h = 0;
166 69
167 if (item->max.w < 0) item->max.w = INT_MAX; 70 if (pd->homogeneous || box_calc[0].fill)
168 if (item->max.h < 0) item->max.h = INT_MAX; 71 hints[0].weight = 1;
72 else if (hints[0].weight < 0)
73 hints[0].weight = 0;
169 74
170 weight[0] += item->weight[0]; 75 if (pd->homogeneous || box_calc[1].fill)
171 weight[1] += item->weight[1]; 76 hints[1].weight = 1;
77 else if (hints[1].weight < 0)
78 hints[1].weight = 0;
172 79
173 if ((item->aspect.w <= 0) || (item->aspect.h <= 0)) 80 weight_sum += hints[axis].weight;
174 {
175 if ((item->aspect.w <= 0) ^ (item->aspect.h <= 0))
176 {
177 ERR("Invalid aspect parameter for obj: %p", item->obj);
178 item->aspect.w = item->aspect.h = 0;
179 item->aspect_type = EFL_GFX_HINT_ASPECT_NONE;
180 }
181 }
182 else
183 {
184 _min_max_calc(item, &item->min.w, &item->min.h, EINA_TRUE);
185 }
186 81
187 item->space[0] = item->min.w + item->pad[0] + item->pad[1]; 82 if (hints[r_axis].space > want[r_axis])
188 item->space[1] = item->min.h + item->pad[2] + item->pad[3]; 83 want[r_axis] = hints[r_axis].space;
189 84
190 if (horiz) 85 if (pd->homogeneous)
191 { 86 {
192 if (item->space[1] > wanth) 87 if (hints[axis].space > mmin)
193 wanth = item->space[1]; 88 mmin = hints[axis].space;
194 if (pd->homogeneous)
195 {
196 if (item->space[0] > mmin)
197 mmin = item->space[0];
198 }
199 else
200 {
201 wantw += item->space[0];
202 }
203 } 89 }
204 else 90 else
205 { 91 {
206 if (item->space[0] > wantw) 92 want[axis] += hints[axis].space;
207 wantw = item->space[0];
208 if (pd->homogeneous)
209 {
210 if (item->space[1] > mmin)
211 mmin = item->space[1];
212 }
213 else
214 {
215 wanth += item->space[1];
216 }
217 } 93 }
218
219 item->id = id++;
220 } 94 }
221 95
222 // total space & available space 96 // total space & available space
223 if (horiz) 97 if (pd->homogeneous)
224 { 98 want[axis] = mmin * count;
225 if (pd->homogeneous) 99
226 wantw = mmin * count; 100 if (box_calc[r_axis].size < want[r_axis])
227 want = wantw; 101 box_calc[r_axis].size = want[r_axis];
228 length = boxs.w;
229 pad = pd->pad.scalable ? (pd->pad.h * scale) : pd->pad.h;
230 if (boxs.h < wanth)
231 boxs.h = wanth;
232 }
233 else
234 {
235 if (pd->homogeneous)
236 wanth = mmin * count;
237 want = wanth;
238 length = boxs.h;
239 pad = pd->pad.scalable ? (pd->pad.v * scale) : pd->pad.v;
240 if (boxs.w < wantw)
241 boxs.w = wantw;
242 }
243 102
244 // padding can not be squeezed (note: could make it an option) 103 // padding can not be squeezed (note: could make it an option)
245 length -= pad * (count - 1); 104 box_calc[axis].size -= (box_calc[axis].pad * (count - 1));
246 cur_pos = horiz ? boxs.x : boxs.y; 105 box_calc[r_axis].pad = 0;
106 cur_pos = box_calc[axis].pos;
247 107
248 // calculate weight length 108 // calculate weight size
249 if (!pd->homogeneous && (length > want) && (weight[!horiz] > 0)) 109 if (!pd->homogeneous && (box_calc[axis].size > want[axis]) && (weight_sum > 0))
250 { 110 {
251 int orig_length = length; 111 int orig_size, calc_size;
252 double orig_weight = weight[!horiz]; 112 double orig_weight = weight_sum;
113
114 calc_size = orig_size = box_calc[axis].size;
253 115
254 for (id = 0; id < count; id++) 116 for (i = 0; i < count; i++)
255 { 117 {
256 double denom; 118 double denom;
257 item = &items[id]; 119 hint = &items[i].hints[axis];
258 120
259 denom = (item->weight[!horiz] * orig_length) - 121 denom = (hint->weight * orig_size) - (orig_weight * hint->space);
260 (orig_weight * item->space[!horiz]);
261 if (denom > 0) 122 if (denom > 0)
262 { 123 {
263 item->comp_factor = (item->weight[!horiz] * orig_length) / denom; 124 items[i].weight_factor = (hint->weight * orig_size) / denom;
264 inlist = eina_inlist_sorted_insert(inlist, EINA_INLIST_GET(item), 125 inlist = eina_inlist_sorted_insert(inlist, EINA_INLIST_GET(&items[i]),
265 weight_sort_cb); 126 _weight_sort_cb);
127
266 } 128 }
267 else 129 else
268 { 130 {
269 length -= item->space[!horiz]; 131 calc_size -= hint->space;
270 weight[!horiz] -= item->weight[!horiz]; 132 weight_sum -= hint->weight;
271 } 133 }
272 } 134 }
273 135
274 EINA_INLIST_FOREACH(inlist, item) 136 EINA_INLIST_FOREACH(inlist, item)
275 { 137 {
276 double weight_len; 138 double weight_len;
139 hint = &item->hints[axis];
277 140
278 weight_len = (length * item->weight[!horiz]) / weight[!horiz]; 141 weight_len = (calc_size * hint->weight) / weight_sum;
279 if (item->space[!horiz] < weight_len) 142 if (hint->space < weight_len)
280 { 143 {
281 item->space[!horiz] = weight_len; 144 hint->space = weight_len;
282 } 145 }
283 else 146 else
284 { 147 {
285 weight[!horiz] -= item->weight[!horiz]; 148 weight_sum -= hint->weight;
286 length -= item->space[!horiz]; 149 calc_size -= hint->space;
287 } 150 }
288 } 151 }
289 } 152 }
290 153
291 // calculate item geometry 154 // calculate item geometry
292 { 155 {
293 int x, y, w, h, sw, sh; 156 int item_size[2], item_pos[2], sw, sh;
294 157
295 if (length > want) 158 if (box_calc[axis].size > want[axis])
296 { 159 {
297 if (pd->homogeneous) 160 if (pd->homogeneous)
298 mmin = (double)length / count; 161 mmin = (double)box_calc[axis].size / count;
299 else if (EINA_DBL_EQ(weight[!horiz], 0)) 162 else if (EINA_DBL_EQ(weight_sum, 0))
300 cur_pos += (length - want) * box_align[!horiz]; 163 cur_pos += (box_calc[axis].size - want[axis]) * box_calc[axis].align;
301 } 164 }
302 165
303 for (id = 0; id < count; id++) 166 for (i = 0; i < count; i++)
304 { 167 {
305 item = &items[id]; 168 hints = items[i].hints;
169
306 if (pd->homogeneous) 170 if (pd->homogeneous)
307 item->space[!horiz] = mmin; 171 hints[axis].space = mmin;
308 item->space[horiz] = horiz ? boxs.h : boxs.w; 172 hints[r_axis].space = box_calc[r_axis].size;
309 sw = item->space[0] - item->pad[0] - item->pad[1]; 173 sw = hints[0].space - (hints[0].margin[0] + hints[0].margin[1]);
310 sh = item->space[1] - item->pad[2] - item->pad[3]; 174 sh = hints[1].space - (hints[1].margin[0] + hints[1].margin[1]);
311 175
312 if ((item->weight[0] > 0) && item->fill[0]) 176 item_size[0] = ((hints[0].weight > 0) && hints[0].fill) ? sw : 0;
313 w = sw; 177 item_size[1] = ((hints[1].weight > 0) && hints[1].fill) ? sh : 0;
314 else
315 w = 0;
316 178
317 if ((item->weight[1] > 0) && item->fill[1]) 179 _efl_ui_container_layout_min_max_calc(hints, &item_size[0], &item_size[1],
318 h = sh; 180 (hints[0].aspect > 0) && (hints[1].aspect > 0));
319 else
320 h = 0;
321 181
322 _min_max_calc(item, &w, &h, (item->aspect.w > 0) && 182 item_pos[axis] = cur_pos + 0.5;
323 (item->aspect.h > 0)); 183 item_pos[r_axis] = box_calc[r_axis].pos;
324 if (horiz) 184
325 { 185 item_pos[0] += (hints[0].margin[0] +
326 x = cur_pos + 0.5; 186 ((sw - item_size[0]) * hints[0].align));
327 y = boxs.y; 187 item_pos[1] += (hints[1].margin[0] +
328 } 188 ((sh - item_size[1]) * hints[1].align));
329 else
330 {
331 x = boxs.x;
332 y = cur_pos + 0.5;
333 }
334 x += item->pad[0] + ((sw - w) * item->align[0]);
335 y += item->pad[2] + ((sh - h) * item->align[1]);
336 189
337 cur_pos += item->space[!horiz] + pad; 190 cur_pos += hints[axis].space + box_calc[axis].pad;
338 191
339 efl_gfx_entity_geometry_set(item->obj, EINA_RECT(x, y, w, h)); 192 efl_gfx_entity_geometry_set(items[i].obj,
193 EINA_RECT(item_pos[0], item_pos[1],
194 item_size[0], item_size[1]));
340 } 195 }
341 } 196 }
197 want[0] += (box_calc[0].margin[0] + box_calc[0].margin[1]) +
198 (box_calc[0].pad * (count - 1));
199 want[1] += (box_calc[1].margin[0] + box_calc[1].margin[1]) +
200 (box_calc[1].pad * (count - 1));
342 201
343 if (horiz) 202 efl_gfx_hint_size_min_set(ui_box, EINA_SIZE2D(want[0], want[1]));
344 {
345 efl_gfx_hint_size_min_set(ui_box, EINA_SIZE2D(
346 wantw + boxl + boxr + pad * (count - 1),
347 wanth + boxt + boxb));
348 }
349 else
350 {
351 efl_gfx_hint_size_min_set(ui_box, EINA_SIZE2D(
352 wantw + boxl + boxr,
353 wanth + pad * (count - 1) + boxt + boxb));
354 }
355} 203}
diff --git a/src/lib/elementary/efl_ui_container_layout.c b/src/lib/elementary/efl_ui_container_layout.c
new file mode 100644
index 0000000000..e8c5979dd0
--- /dev/null
+++ b/src/lib/elementary/efl_ui_container_layout.c
@@ -0,0 +1,158 @@
1#include "efl_ui_container_layout.h"
2
3void
4_efl_ui_container_layout_min_max_calc(Efl_Ui_Container_Item_Hints *item, int *cw, int *ch, Eina_Bool aspect_check)
5{
6 int w = *cw, h = *ch;
7 Eina_Size2D aspect = { item[0].aspect, item[1].aspect };
8
9 if (aspect_check)
10 {
11 w = h * aspect.w / aspect.h;
12 if (w > *cw)
13 {
14 w = *cw;
15 h = w * aspect.h / aspect.w;
16 }
17 }
18
19 if (w > item[0].max)
20 {
21 w = item[0].max;
22 if (aspect_check) h = w * aspect.h / aspect.w;
23 }
24 if (h > item[1].max)
25 {
26 h = item[1].max;
27 if (aspect_check) w = h * aspect.w / aspect.h;
28 }
29 if (w < item[0].min)
30 {
31 w = item[0].min;
32 if (aspect_check) h = w * aspect.h / aspect.w;
33 }
34 if (h < item[1].min)
35 {
36 h = item[1].min;
37 if (aspect_check) w = h * aspect.w / aspect.h;
38 }
39 *cw = w;
40 *ch = h;
41}
42
43void
44_efl_ui_container_layout_item_init(Eo* o, Efl_Ui_Container_Item_Hints *item)
45{
46 Eina_Size2D max;
47 Eina_Size2D min;
48 Eina_Size2D aspect;
49 Efl_Gfx_Hint_Aspect aspect_type;
50
51 efl_gfx_hint_weight_get(o, &item[0].weight, &item[1].weight);
52 efl_gfx_hint_align_get(o, &item[0].align, &item[1].align);
53 efl_gfx_hint_margin_get(o, &item[0].margin[0], &item[0].margin[1],
54 &item[1].margin[0], &item[1].margin[1]);
55 efl_gfx_hint_fill_get(o, &item[0].fill, &item[1].fill);
56 max = efl_gfx_hint_size_max_get(o);
57 min = efl_gfx_hint_size_combined_min_get(o);
58 efl_gfx_hint_aspect_get(o, &aspect_type, &aspect);
59 item[0].aspect = aspect.w;
60 item[1].aspect = aspect.h;
61 item[0].aspect_type = aspect_type;
62 item[1].aspect_type = aspect_type;
63
64 if (EINA_DBL_EQ(item[0].align, -1))
65 {
66 item[0].align = 0.5;
67 item[0].fill = EINA_TRUE;
68 }
69 else if (item[0].align < 0) item[0].align = 0;
70 else if (item[0].align > 1) item[0].align = 1;
71 if (EINA_DBL_EQ(item[1].align, -1))
72 {
73 item[1].align = 0.5;
74 item[1].fill = EINA_TRUE;
75 }
76 else if (item[1].align < 0) item[1].align = 0;
77 else if (item[1].align > 1) item[1].align = 1;
78
79 if (min.w < 0) min.w = 0;
80 if (min.h < 0) min.h = 0;
81
82 if (max.w < 0) max.w = INT_MAX;
83 if (max.h < 0) max.h = INT_MAX;
84
85 item[0].max = max.w;
86 item[1].max = max.h;
87 item[0].min = min.w;
88 item[1].min = min.h;
89
90 if ((item[0].aspect <= 0) || (item[1].aspect_type <= 0))
91 {
92 if ((item[0].aspect <= 0) ^ (item[1].aspect_type <= 0))
93 {
94 ERR("Invalid aspect parameter for obj(%p)", o);
95 item[0].aspect = item[1].aspect_type = 0;
96 item[0].aspect_type = item[1].aspect_type = EFL_GFX_HINT_ASPECT_NONE;
97 }
98 }
99 else
100 {
101 _efl_ui_container_layout_min_max_calc(item, &item[0].min, &item[1].min,
102 EINA_TRUE);
103 }
104
105
106 item[0].space = item[0].min + item[0].margin[0] + item[0].margin[1];
107 item[1].space = item[1].min + item[1].margin[0] + item[1].margin[1];
108}
109
110void
111_efl_ui_container_layout_init(Eo* obj, Efl_Ui_Container_Layout_Calc *calc)
112{
113 Eina_Rect geom;
114 Eina_Bool pad_scalable;
115
116 geom = efl_gfx_entity_geometry_get(obj);
117 efl_gfx_hint_margin_get(obj, &calc[0].margin[0], &calc[0].margin[1],
118 &calc[1].margin[0], &calc[1].margin[1]);
119 calc[0].scale = calc[1].scale = efl_gfx_entity_scale_get(obj);
120
121 efl_pack_padding_get(obj, &calc[0].pad, &calc[1].pad, &pad_scalable);
122 calc[0].pad = pad_scalable ? (calc[0].pad * calc[0].scale) : calc[0].pad;
123 calc[1].pad = pad_scalable ? (calc[1].pad * calc[1].scale) : calc[1].pad;
124
125 // pack align is used if "no item has a weight"
126 efl_pack_align_get(obj, &calc[0].align, &calc[1].align);
127 if (calc[0].align < 0)
128 {
129 calc[0].fill = EINA_TRUE;
130 calc[0].align = 0.5;
131 }
132 else if (calc[0].align > 1)
133 {
134 calc[0].align = 1;
135 }
136 else
137 {
138 calc[0].fill = EINA_FALSE;
139 }
140
141 if (calc[1].align < 0)
142 {
143 calc[1].fill = EINA_TRUE;
144 calc[1].align = 0.5;
145 }
146 else if (calc[1].align > 1)
147 {
148 calc[1].align = 1;
149 }
150 else
151 {
152 calc[1].fill = EINA_FALSE;
153 }
154 calc[0].pos = geom.x + calc[0].margin[0];
155 calc[1].pos = geom.y + calc[1].margin[0];
156 calc[0].size = geom.w - calc[0].margin[0] - calc[0].margin[1];
157 calc[1].size = geom.h - calc[1].margin[0] - calc[1].margin[1];
158}
diff --git a/src/lib/elementary/efl_ui_container_layout.h b/src/lib/elementary/efl_ui_container_layout.h
new file mode 100644
index 0000000000..097abee13b
--- /dev/null
+++ b/src/lib/elementary/efl_ui_container_layout.h
@@ -0,0 +1,42 @@
1#ifndef _EFL_UI_CONTAINER_HELPER_H_
2#define _EFL_UI_CONTAINER_HELPER_H_
3
4#ifdef HAVE_CONFIG_H
5# include "elementary_config.h"
6#endif
7
8#include <Elementary.h>
9#include "elm_priv.h"
10
11typedef struct _Efl_Ui_Container_Item_Hints Efl_Ui_Container_Item_Hints;
12typedef struct _Efl_Ui_Container_Layout_Calc Efl_Ui_Container_Layout_Calc;
13
14struct _Efl_Ui_Container_Item_Hints
15{
16 int max;
17 int min;
18 int aspect;
19 int margin[2]; // start, end
20 Efl_Gfx_Hint_Aspect aspect_type;
21 double weight;
22 double align;
23 double space;
24 Eina_Bool fill;
25};
26
27struct _Efl_Ui_Container_Layout_Calc
28{
29 int pos;
30 int size;
31 int margin[2];
32 double align;
33 double scale;
34 double pad;
35 Eina_Bool fill : 1;
36};
37
38void _efl_ui_container_layout_min_max_calc(Efl_Ui_Container_Item_Hints *item, int *cw, int *ch, Eina_Bool aspect_check);
39void _efl_ui_container_layout_item_init(Eo* o, Efl_Ui_Container_Item_Hints *item);
40void _efl_ui_container_layout_init(Eo* obj, Efl_Ui_Container_Layout_Calc *calc);
41
42#endif
diff --git a/src/lib/elementary/efl_ui_table.c b/src/lib/elementary/efl_ui_table.c
index 889dc423db..5f42043b16 100644
--- a/src/lib/elementary/efl_ui_table.c
+++ b/src/lib/elementary/efl_ui_table.c
@@ -74,7 +74,16 @@ _table_size_hints_changed(void *data, Evas *e EINA_UNUSED,
74{ 74{
75 Efl_Ui_Table_Data *pd = efl_data_scope_get(data, MY_CLASS); 75 Efl_Ui_Table_Data *pd = efl_data_scope_get(data, MY_CLASS);
76 76
77 _sizing_eval(data, pd); 77 if (table == data)
78 efl_pack_layout_request(data);
79 else
80 _sizing_eval(data, pd);
81}
82
83static void
84_efl_ui_table_size_hints_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
85{
86 efl_pack_layout_request(ev->object);
78} 87}
79 88
80/* Custom table class: overrides smart_calculate. */ 89/* Custom table class: overrides smart_calculate. */
@@ -116,10 +125,7 @@ _custom_table_calc(Eo *obj, Custom_Table_Data *pd)
116EOLIAN static void 125EOLIAN static void
117_efl_ui_table_efl_pack_layout_layout_update(Eo *obj, Efl_Ui_Table_Data *pd) 126_efl_ui_table_efl_pack_layout_layout_update(Eo *obj, Efl_Ui_Table_Data *pd)
118{ 127{
119 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); 128 _efl_ui_table_custom_layout(obj, pd);
120
121 _sizing_eval(obj, pd);
122 efl_canvas_group_calculate(efl_super(wd->resize_obj, CUSTOM_TABLE_CLASS));
123} 129}
124 130
125EOLIAN void 131EOLIAN void
@@ -148,6 +154,8 @@ _efl_ui_table_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Table_Data *pd)
148 154
149 evas_object_event_callback_add 155 evas_object_event_callback_add
150 (table, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _table_size_hints_changed, obj); 156 (table, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _table_size_hints_changed, obj);
157 efl_event_callback_add(obj, EFL_GFX_ENTITY_EVENT_HINTS_CHANGED,
158 _efl_ui_table_size_hints_changed_cb, NULL);
151 159
152 efl_canvas_group_add(efl_super(obj, MY_CLASS)); 160 efl_canvas_group_add(efl_super(obj, MY_CLASS));
153 161
@@ -168,6 +176,8 @@ _efl_ui_table_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Table_Data *pd EINA_UNU
168 evas_object_event_callback_del_full 176 evas_object_event_callback_del_full
169 (wd->resize_obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, 177 (wd->resize_obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
170 _table_size_hints_changed, obj); 178 _table_size_hints_changed, obj);
179 efl_event_callback_del(obj, EFL_GFX_ENTITY_EVENT_HINTS_CHANGED,
180 _efl_ui_table_size_hints_changed_cb, NULL);
171 181
172 /* let's make our table object the *last* to be processed, since it 182 /* let's make our table object the *last* to be processed, since it
173 * may (smart) parent other sub objects here */ 183 * may (smart) parent other sub objects here */
@@ -197,6 +207,8 @@ _efl_ui_table_efl_object_constructor(Eo *obj, Efl_Ui_Table_Data *pd)
197 pd->last_row = -1; 207 pd->last_row = -1;
198 pd->req_cols = 0; 208 pd->req_cols = 0;
199 pd->req_rows = 0; 209 pd->req_rows = 0;
210 pd->align.h = 0.5;
211 pd->align.v = 0.5;
200 212
201 return obj; 213 return obj;
202} 214}
@@ -232,6 +244,28 @@ _efl_ui_table_efl_pack_pack_padding_get(const Eo *obj, Efl_Ui_Table_Data *pd EIN
232 if (v) *v = pd->pad.v; 244 if (v) *v = pd->pad.v;
233} 245}
234 246
247EOLIAN static void
248_efl_ui_table_efl_pack_pack_align_set(Eo *obj, Efl_Ui_Table_Data *pd, double h, double v)
249{
250 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
251
252 if (h < 0) h = -1;
253 if (v < 0) v = -1;
254 if (h > 1) h = 1;
255 if (v > 1) v = 1;
256 pd->align.h = h;
257 pd->align.v = v;
258
259 efl_pack_layout_request(obj);
260}
261
262EOLIAN static void
263_efl_ui_table_efl_pack_pack_align_get(const Eo *obj EINA_UNUSED, Efl_Ui_Table_Data *pd, double *h, double *v)
264{
265 if (h) *h = pd->align.h;
266 if (v) *v = pd->align.v;
267}
268
235static void 269static void
236_subobj_del_cb(void *data, const Efl_Event *event) 270_subobj_del_cb(void *data, const Efl_Event *event)
237{ 271{
diff --git a/src/lib/elementary/efl_ui_table.eo b/src/lib/elementary/efl_ui_table.eo
index c62612a02a..f3c067f98b 100644
--- a/src/lib/elementary/efl_ui_table.eo
+++ b/src/lib/elementary/efl_ui_table.eo
@@ -15,6 +15,7 @@ class @beta Efl.Ui.Table extends Efl.Ui.Widget implements Efl.Pack_Table, Efl.Pa
15 Efl.Pack.unpack; 15 Efl.Pack.unpack;
16 Efl.Pack.pack; 16 Efl.Pack.pack;
17 Efl.Pack.pack_padding { get; set; } 17 Efl.Pack.pack_padding { get; set; }
18 Efl.Pack.pack_align { get; set; }
18 Efl.Pack_Table.pack_table; 19 Efl.Pack_Table.pack_table;
19 Efl.Pack_Table.table_content_get; 20 Efl.Pack_Table.table_content_get;
20 Efl.Pack_Table.table_contents_get; 21 Efl.Pack_Table.table_contents_get;
diff --git a/src/lib/elementary/efl_ui_table_layout.c b/src/lib/elementary/efl_ui_table_layout.c
new file mode 100644
index 0000000000..0a21384a8f
--- /dev/null
+++ b/src/lib/elementary/efl_ui_table_layout.c
@@ -0,0 +1,294 @@
1#include "efl_ui_table_private.h"
2#include "efl_ui_container_layout.h"
3
4typedef struct _Item_Calc Item_Calc;
5typedef struct _Cell_Calc Cell_Calc;
6typedef struct _Table_Calc Table_Calc;
7
8struct _Item_Calc
9{
10 Evas_Object *obj;
11 int cell_span[2];
12 int cell_index[2];
13 Efl_Ui_Container_Item_Hints hints[2]; /* 0 is x-axis, 1 is y-axis */
14};
15
16struct _Cell_Calc
17{
18 EINA_INLIST;
19
20 int index;
21 int next;
22 double acc;
23 double space;
24 double weight;
25 double weight_factor;
26 Eina_Bool occupied : 1;
27};
28
29struct _Table_Calc
30{
31 /* 0 is x-axis, 1 is y-axis */
32
33 int rows;
34 int cols;
35 int want[2];
36 double weight_sum[2];
37 Cell_Calc *cell_calc[2];
38 Efl_Ui_Container_Layout_Calc layout_calc[2];
39};
40
41static int
42_weight_sort_cb(const void *l1, const void *l2)
43{
44 Cell_Calc *cc1, *cc2;
45
46 cc1 = EINA_INLIST_CONTAINER_GET(l1, Cell_Calc);
47 cc2 = EINA_INLIST_CONTAINER_GET(l2, Cell_Calc);
48
49 return cc2->weight_factor <= cc1->weight_factor ? -1 : 1;
50}
51
52static void
53_cell_weight_calc(Table_Calc *table_calc, Eina_Bool axis)
54{
55 int i, count, layout_size, calc_size;
56 double denom, weight_sum, calc_weight;
57 Eina_Inlist *inlist = NULL;
58 Cell_Calc *cell_calc, *cc;
59
60 layout_size = calc_size = table_calc->layout_calc[axis].size;
61 weight_sum = calc_weight = table_calc->weight_sum[axis];
62 cell_calc = table_calc->cell_calc[axis];
63 count = axis ? table_calc->rows : table_calc->cols;
64
65 for (i = 0; i < count; i = cell_calc[i].next)
66 {
67 denom = (cell_calc[i].weight * layout_size) -
68 (weight_sum * cell_calc[i].space);
69 if (denom > 0)
70 {
71 cell_calc[i].weight_factor = (cell_calc[i].weight * layout_size) / denom;
72 inlist = eina_inlist_sorted_insert(inlist,
73 EINA_INLIST_GET(&cell_calc[i]),
74 _weight_sort_cb);
75 }
76 else
77 {
78 calc_size -= cell_calc[i].space;
79 calc_weight -= cell_calc[i].weight;
80 }
81 }
82
83 EINA_INLIST_FOREACH(inlist, cc)
84 {
85 double weight_len;
86
87 weight_len = (calc_size * cc->weight) / calc_weight;
88 if (cc->space < weight_len)
89 {
90 cc->space = weight_len;
91 }
92 else
93 {
94 calc_size -= cc->space;
95 calc_weight -= cc->weight;
96 }
97 }
98}
99
100static void
101_efl_ui_table_regular_cell_init(Table_Calc *table_calc, Eina_Bool axis)
102{
103 int i, index = 0, acc, want = 0, count;
104 double weight_sum = 0;
105 Cell_Calc *prev_cell = NULL, *cell_calc;
106 Efl_Ui_Container_Layout_Calc *layout_calc;
107
108 layout_calc = &(table_calc->layout_calc[axis]);
109 cell_calc = table_calc->cell_calc[axis];
110 count = axis ? table_calc->rows : table_calc->cols;
111
112 for (i = 0; i < count; i++)
113 {
114 if (!cell_calc[i].occupied) continue;
115
116 cell_calc[i].index = index++;
117 want += cell_calc[i].space;
118 weight_sum += cell_calc[i].weight;
119
120 if (prev_cell)
121 prev_cell->next = i;
122
123 prev_cell = &cell_calc[i];
124 }
125 if (prev_cell)
126 prev_cell->next = count;
127
128 table_calc->want[axis] = want;
129 table_calc->weight_sum[axis] = weight_sum;
130 table_calc->layout_calc[axis].size -= (table_calc->layout_calc[axis].pad
131 * (index - 1));
132
133 if ((layout_calc->size > want) && (weight_sum > 0))
134 _cell_weight_calc(table_calc, axis);
135 if (EINA_DBL_EQ(weight_sum, 0.0))
136 layout_calc->pos += (layout_calc->size - want) * layout_calc->align;
137
138 for (i = 0, acc = 0; i < count; acc += cell_calc[i].space, i = cell_calc[i].next)
139 cell_calc[i].acc = acc;
140}
141
142static inline int
143_efl_ui_table_regular_item_pos_get(Table_Calc *table_calc, Item_Calc *item, Eina_Bool axis)
144{
145 return 0.5 + table_calc->layout_calc[axis].pos
146 + table_calc->cell_calc[axis][item->cell_index[axis]].acc
147 + (table_calc->cell_calc[axis][item->cell_index[axis]].index *
148 table_calc->layout_calc[axis].pad);
149}
150
151static inline int
152_efl_ui_table_regular_item_size_get(Table_Calc *table_calc, Item_Calc *item, Eina_Bool axis)
153{
154 int start, end;
155
156 start = item->cell_index[axis];
157 end = start + item->cell_span[axis] - 1;
158
159 return table_calc->cell_calc[axis][end].acc
160 - table_calc->cell_calc[axis][start].acc
161 + table_calc->cell_calc[axis][end].space
162 + ((item->cell_span[axis] - 1) * table_calc->layout_calc[axis].pad)
163 - item->hints[axis].margin[0] - item->hints[axis].margin[1];
164}
165
166void
167_efl_ui_table_custom_layout(Efl_Ui_Table *ui_table, Efl_Ui_Table_Data *pd)
168{
169 Table_Item *ti;
170 Item_Calc *items, *item;
171 Efl_Ui_Container_Item_Hints *hints;
172 int i = 0, rows, cols;
173
174 Table_Calc table_calc;
175
176 if (!pd->count)
177 {
178 efl_gfx_hint_size_min_set(ui_table, EINA_SIZE2D(0, 0));
179 return;
180 }
181
182 _efl_ui_container_layout_init(ui_table, table_calc.layout_calc);
183
184 table_calc.want[0] = table_calc.want[1] = 0;
185 table_calc.weight_sum[0] = table_calc.weight_sum[1] = 0;
186
187 efl_pack_table_size_get(ui_table, &cols, &rows);
188
189 table_calc.cell_calc[0] = alloca(cols * sizeof(Cell_Calc));
190 table_calc.cell_calc[1] = alloca(rows * sizeof(Cell_Calc));
191
192 memset(table_calc.cell_calc[0], 0, cols * sizeof(Cell_Calc));
193 memset(table_calc.cell_calc[1], 0, rows * sizeof(Cell_Calc));
194
195 items = alloca(pd->count * sizeof(*items));
196#ifdef DEBUG
197 memset(items, 0, pd->count * sizeof(*items));
198#endif
199
200 table_calc.cols = cols;
201 table_calc.rows = rows;
202 // scan all items, get their properties, calculate total weight & min size
203 EINA_INLIST_FOREACH(pd->items, ti)
204 {
205 if (((ti->col + ti->col_span) > cols) ||
206 ((ti->row + ti->row_span) > rows))
207 {
208 efl_gfx_entity_visible_set(ti->object, EINA_FALSE);
209 continue;
210 }
211
212 item = &items[i++];
213 item->obj = ti->object;
214 hints = item->hints;
215
216 _efl_ui_container_layout_item_init(item->obj, hints);
217
218 if (table_calc.layout_calc[0].fill)
219 hints[0].weight = 1;
220 else if (hints[0].weight < 0)
221 hints[0].weight = 0;
222
223 if (table_calc.layout_calc[1].fill)
224 hints[1].weight = 1;
225 else if (hints[1].weight < 0)
226 hints[1].weight = 0;
227
228 item->cell_index[0] = ti->col;
229 item->cell_index[1] = ti->row;
230 item->cell_span[0] = ti->col_span;
231 item->cell_span[1] = ti->row_span;
232
233 if (ti->col_span == 1)
234 {
235 table_calc.cell_calc[0][ti->col].occupied = EINA_TRUE;
236
237 if (table_calc.cell_calc[0][ti->col].space < hints[0].space)
238 table_calc.cell_calc[0][ti->col].space = hints[0].space;
239 if (table_calc.cell_calc[0][ti->col].weight < hints[0].weight)
240 table_calc.cell_calc[0][ti->col].weight = hints[0].weight;
241 }
242
243 if (ti->row_span == 1)
244 {
245 table_calc.cell_calc[1][ti->row].occupied = EINA_TRUE;
246
247 if (table_calc.cell_calc[1][ti->row].space < hints[1].space)
248 table_calc.cell_calc[1][ti->row].space = hints[1].space;
249 if (table_calc.cell_calc[1][ti->row].weight < hints[1].weight)
250 table_calc.cell_calc[1][ti->row].weight = hints[1].weight;
251 }
252 }
253
254 _efl_ui_table_regular_cell_init(&table_calc, 0);
255 _efl_ui_table_regular_cell_init(&table_calc, 1);
256
257 for (i = 0; i < pd->count; i++)
258 {
259 Eina_Rect space, item_geom;
260 item = &items[i];
261 hints = items[i].hints;
262
263 space.x = _efl_ui_table_regular_item_pos_get(&table_calc, item, 0);
264 space.y = _efl_ui_table_regular_item_pos_get(&table_calc, item, 1);
265 space.w = _efl_ui_table_regular_item_size_get(&table_calc, item, 0);
266 space.h = _efl_ui_table_regular_item_size_get(&table_calc, item, 1);
267
268 item_geom.w = hints[0].fill ? space.w : hints[0].min;
269 item_geom.h = hints[1].fill ? space.h : hints[1].min;
270
271 _efl_ui_container_layout_min_max_calc(hints, &item_geom.w, &item_geom.h,
272 (hints[0].aspect > 0) && (hints[1].aspect > 0));
273
274 item_geom.x = space.x + ((space.w - item_geom.w) * hints[0].align)
275 + hints[0].margin[0];
276 item_geom.y = space.y + ((space.h - item_geom.h) * hints[1].align)
277 + hints[1].margin[0];
278
279 efl_gfx_entity_geometry_set(item->obj, item_geom);
280 }
281
282 table_calc.want[0] += table_calc.layout_calc[0].margin[0]
283 + table_calc.layout_calc[0].margin[1]
284 + (table_calc.layout_calc[0].pad *
285 table_calc.cell_calc[0][cols - 1].index);
286
287 table_calc.want[1] += table_calc.layout_calc[1].margin[0]
288 + table_calc.layout_calc[1].margin[1]
289 + (table_calc.layout_calc[1].pad *
290 table_calc.cell_calc[1][rows - 1].index);
291
292 efl_gfx_hint_size_min_set(ui_table, EINA_SIZE2D(table_calc.want[0],
293 table_calc.want[1]));
294}
diff --git a/src/lib/elementary/efl_ui_table_private.h b/src/lib/elementary/efl_ui_table_private.h
index e7c3821ee9..0ab08e5109 100644
--- a/src/lib/elementary/efl_ui_table_private.h
+++ b/src/lib/elementary/efl_ui_table_private.h
@@ -14,6 +14,8 @@ typedef struct _Efl_Ui_Table_Data Efl_Ui_Table_Data;
14typedef struct _Table_Item_Iterator Table_Item_Iterator; 14typedef struct _Table_Item_Iterator Table_Item_Iterator;
15typedef struct _Table_Item Table_Item; 15typedef struct _Table_Item Table_Item;
16 16
17void _efl_ui_table_custom_layout(Efl_Ui_Table *ui_table, Efl_Ui_Table_Data *pd);
18
17#define TABLE_ITEM_KEY "__table_item" 19#define TABLE_ITEM_KEY "__table_item"
18 20
19struct _Table_Item 21struct _Table_Item
@@ -39,6 +41,9 @@ struct _Efl_Ui_Table_Data
39 double h, v; 41 double h, v;
40 Eina_Bool scalable: 1; 42 Eina_Bool scalable: 1;
41 } pad; 43 } pad;
44 struct {
45 double h, v;
46 } align;
42 Eina_Bool linear_recalc : 1; 47 Eina_Bool linear_recalc : 1;
43}; 48};
44 49
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index 38ee28fe9a..a3200855c9 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -846,6 +846,8 @@ elementary_src = [
846 'els_cursor.c', 846 'els_cursor.c',
847 'els_tooltip.c', 847 'els_tooltip.c',
848 'elu_ews_wm.c', 848 'elu_ews_wm.c',
849 'efl_ui_container_layout.c',
850 'efl_ui_container_layout.h',
849 'efl_ui_box.c', 851 'efl_ui_box.c',
850 'efl_ui_box_flow.c', 852 'efl_ui_box_flow.c',
851 'efl_ui_box_stack.c', 853 'efl_ui_box_stack.c',
@@ -858,6 +860,7 @@ elementary_src = [
858 'efl_ui_anchor_popup.c', 860 'efl_ui_anchor_popup.c',
859 'efl_ui_table.c', 861 'efl_ui_table.c',
860 'efl_ui_table_static.c', 862 'efl_ui_table_static.c',
863 'efl_ui_table_layout.c',
861 'efl_ui_table_private.h', 864 'efl_ui_table_private.h',
862 'efl_ui_text.c', 865 'efl_ui_text.c',
863 'efl_ui_text_factory_images.c', 866 'efl_ui_text_factory_images.c',