summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYeongjong Lee <yj34.lee@samsung.com>2019-02-22 19:47:47 +0900
committerJaehyun Cho <jae_hyun.cho@samsung.com>2019-02-22 19:47:47 +0900
commit3118bfc34bb97b01a0cdb0caf674aaf3fc20565c (patch)
tree2d922738f5641ed941fe434188c6d16ab7b1b1ff /src
parent6716feb1080e4b80f974620a72c763ef8e64d22f (diff)
efl_ui_relative_layout: introduce new relative container
Summary: Efl.Ui.Relative_Layout is a container which allows you to position and size with relation to each other. it is possible to position and size using relation like edje even though you don't know a edc script. Position and size can be changed dynamically using widget APIs. @feature ref T5487 Test Plan: make check examples elementary_test -to 'efl.ui.relative_layout' Reviewers: cedric, Hermet, Jaehyun_Cho, zmike, bu5hm4n, jpeg, segfaultxavi Reviewed By: Jaehyun_Cho, segfaultxavi Subscribers: segfaultxavi, kimcinoo Tags: #efl Maniphest Tasks: T5487 Differential Revision: https://phab.enlightenment.org/D7524
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_Elementary.am7
-rw-r--r--src/bin/elementary/meson.build1
-rw-r--r--src/bin/elementary/test.c3
-rw-r--r--src/bin/elementary/test_ui_relative_layout.c319
-rw-r--r--src/examples/elementary.mk8
-rw-r--r--src/examples/elementary/.gitignore2
-rw-r--r--src/examples/elementary/efl_ui_relative_layout_example_01.c51
-rw-r--r--src/examples/elementary/efl_ui_relative_layout_example_02.c45
-rw-r--r--src/lib/elementary/Efl_Ui.h1
-rw-r--r--src/lib/elementary/Elementary.h1
-rw-r--r--src/lib/elementary/efl_ui_relative_layout.c552
-rw-r--r--src/lib/elementary/efl_ui_relative_layout.eo79
-rw-r--r--src/lib/elementary/efl_ui_relative_layout_private.h90
-rw-r--r--src/lib/elementary/meson.build5
-rw-r--r--src/tests/elementary/efl_ui_suite.c1
-rw-r--r--src/tests/elementary/efl_ui_suite.h1
-rw-r--r--src/tests/elementary/efl_ui_test_relative_layout.c300
-rw-r--r--src/tests/elementary/meson.build1
18 files changed, 1463 insertions, 4 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index 5a2ddedea8..1529dcd203 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -133,6 +133,7 @@ elm_public_eolian_files = \
133 lib/elementary/efl_ui_text_part.eo \ 133 lib/elementary/efl_ui_text_part.eo \
134 lib/elementary/efl_ui_caching_factory.eo \ 134 lib/elementary/efl_ui_caching_factory.eo \
135 lib/elementary/efl_ui_widget_factory.eo \ 135 lib/elementary/efl_ui_widget_factory.eo \
136 lib/elementary/efl_ui_relative_layout.eo \
136 $(NULL) 137 $(NULL)
137 138
138# More public files -- FIXME 139# More public files -- FIXME
@@ -455,7 +456,8 @@ includesunstable_HEADERS = \
455 lib/elementary/efl_page_indicator_icon.h \ 456 lib/elementary/efl_page_indicator_icon.h \
456 lib/elementary/efl_ui_tab_pager_private.h \ 457 lib/elementary/efl_ui_tab_pager_private.h \
457 lib/elementary/efl_ui_tab_bar_private.h \ 458 lib/elementary/efl_ui_tab_bar_private.h \
458 lib/elementary/efl_ui_tab_page_private.h 459 lib/elementary/efl_ui_tab_page_private.h \
460 lib/elementary/efl_ui_relative_layout_private.h
459includesunstabledir = $(includedir)/elementary-@VMAJ@ 461includesunstabledir = $(includedir)/elementary-@VMAJ@
460 462
461nodist_includesunstable_HEADERS = \ 463nodist_includesunstable_HEADERS = \
@@ -893,6 +895,7 @@ lib_elementary_libelementary_la_SOURCES = \
893 lib/elementary/efl_ui_homogeneous_model.c \ 895 lib/elementary/efl_ui_homogeneous_model.c \
894 lib/elementary/efl_ui_exact_model.c \ 896 lib/elementary/efl_ui_exact_model.c \
895 lib/elementary/efl_ui_average_model.c \ 897 lib/elementary/efl_ui_average_model.c \
898 lib/elementary/efl_ui_relative_layout.c \
896 $(NULL) 899 $(NULL)
897 900
898 901
@@ -1111,6 +1114,7 @@ bin/elementary/test_gesture_framework.c \
1111bin/elementary/test_ui_tab_pager.c \ 1114bin/elementary/test_ui_tab_pager.c \
1112bin/elementary/test_ui_pager.c \ 1115bin/elementary/test_ui_pager.c \
1113bin/elementary/test_ui_pager_scroll.c \ 1116bin/elementary/test_ui_pager_scroll.c \
1117bin/elementary/test_ui_relative_layout.c \
1114bin/elementary/test.h 1118bin/elementary/test.h
1115 1119
1116bin_elementary_elementary_test_LDADD = @USE_ELEMENTARY_LIBS@ 1120bin_elementary_elementary_test_LDADD = @USE_ELEMENTARY_LIBS@
@@ -1620,6 +1624,7 @@ tests_elementary_efl_ui_suite_SOURCES = \
1620 tests/elementary/efl_ui_test_focus.c \ 1624 tests/elementary/efl_ui_test_focus.c \
1621 tests/elementary/efl_ui_test_focus_sub.c \ 1625 tests/elementary/efl_ui_test_focus_sub.c \
1622 tests/elementary/efl_ui_test_box.c \ 1626 tests/elementary/efl_ui_test_box.c \
1627 tests/elementary/efl_ui_test_relative_layout.c \
1623 tests/elementary/efl_ui_test_grid.c \ 1628 tests/elementary/efl_ui_test_grid.c \
1624 tests/elementary/efl_ui_test_image.c \ 1629 tests/elementary/efl_ui_test_image.c \
1625 tests/elementary/efl_ui_test_image_zoomable.c \ 1630 tests/elementary/efl_ui_test_image_zoomable.c \
diff --git a/src/bin/elementary/meson.build b/src/bin/elementary/meson.build
index 81e6309be3..a3a570a25c 100644
--- a/src/bin/elementary/meson.build
+++ b/src/bin/elementary/meson.build
@@ -155,6 +155,7 @@ elementary_test_src = [
155 'test_win_indicator.c', 155 'test_win_indicator.c',
156 'test_gesture_framework.c', 156 'test_gesture_framework.c',
157 'test_ui_tab_pager.c', 157 'test_ui_tab_pager.c',
158 'test_ui_relative_layout.c',
158 'test.h' 159 'test.h'
159] 160]
160 161
diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index 15fcc8fa5c..fa2bb740b5 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -377,6 +377,8 @@ void test_ui_tab_pager(void *data, Evas_Object *obj, void *event_info);
377void test_ui_pager(void *data, Evas_Object *obj, void *event_info); 377void test_ui_pager(void *data, Evas_Object *obj, void *event_info);
378void test_ui_pager_scroll(void *data, Evas_Object *obj, void *event_info); 378void test_ui_pager_scroll(void *data, Evas_Object *obj, void *event_info);
379 379
380void test_ui_relative_layout(void *data, Evas_Object *obj, void *event_info);
381
380static void _list_udpate(void); 382static void _list_udpate(void);
381 383
382static Evas_Object *win, *tbx, *entry; // TODO: refactoring 384static Evas_Object *win, *tbx, *entry; // TODO: refactoring
@@ -842,6 +844,7 @@ add_tests:
842 ADD_TEST_EO(NULL, "Containers", "Efl.Ui.Table", test_ui_table); 844 ADD_TEST_EO(NULL, "Containers", "Efl.Ui.Table", test_ui_table);
843 ADD_TEST_EO(NULL, "Containers", "Efl.Ui.Table (Linear API)", test_ui_table_linear); 845 ADD_TEST_EO(NULL, "Containers", "Efl.Ui.Table (Linear API)", test_ui_table_linear);
844 ADD_TEST_EO(NULL, "Containers", "Efl.Ui.Table_Static", test_ui_table_static); 846 ADD_TEST_EO(NULL, "Containers", "Efl.Ui.Table_Static", test_ui_table_static);
847 ADD_TEST_EO(NULL, "Containers", "Efl.Ui.Relative_Layout", test_ui_relative_layout);
845 848
846 //------------------------------// 849 //------------------------------//
847 ADD_TEST_EO(NULL, "Events", "Event Refeed", test_events); 850 ADD_TEST_EO(NULL, "Events", "Event Refeed", test_events);
diff --git a/src/bin/elementary/test_ui_relative_layout.c b/src/bin/elementary/test_ui_relative_layout.c
new file mode 100644
index 0000000000..9cb8b168c7
--- /dev/null
+++ b/src/bin/elementary/test_ui_relative_layout.c
@@ -0,0 +1,319 @@
1#include "test.h"
2#ifdef HAVE_CONFIG_H
3# include "elementary_config.h"
4#endif
5
6#include <Elementary.h>
7
8static Eo *layout, *btn1, *btn2, *btn3;
9
10typedef enum {
11 LEFT,
12 RIGHT,
13 TOP,
14 BOTTOM
15} Options;
16
17static void
18_btn_clicked_to_cb(void *data, const Efl_Event *event)
19{
20 Eo *to, *btn, *obj = event->object;
21 Options opt = (Options)data;
22 double relative;
23
24 btn = efl_key_wref_get(obj, "btn");
25 to = efl_key_wref_get(obj, "to");
26
27 do
28 {
29 if (to == layout)
30 to = btn1;
31 else if (to == btn1)
32 to = btn2;
33 else if (to == btn2)
34 to = btn3;
35 else if (to == btn3)
36 to = layout;
37 }
38 while (btn == to);
39 efl_key_wref_set(obj, "to", to);
40
41 switch (opt)
42 {
43 case LEFT:
44 efl_ui_relative_layout_relation_left_get(layout, btn, NULL, &relative);
45 efl_ui_relative_layout_relation_left_set(layout, btn, to, relative);
46 break;
47 case RIGHT:
48 efl_ui_relative_layout_relation_right_get(layout, btn, NULL, &relative);
49 efl_ui_relative_layout_relation_right_set(layout, btn, to, relative);
50 break;
51 case TOP:
52 efl_ui_relative_layout_relation_top_get(layout, btn, NULL, &relative);
53 efl_ui_relative_layout_relation_top_set(layout, btn, to, relative);
54 break;
55 case BOTTOM:
56 efl_ui_relative_layout_relation_bottom_get(layout, btn, NULL, &relative);
57 efl_ui_relative_layout_relation_bottom_set(layout, btn, to, relative);
58 break;
59 }
60 efl_text_set(obj, ((to == layout) ? "parent" : (char *)efl_text_get(to)));
61 efl_pack_layout_request(layout);
62}
63
64static void
65_slider_changed_relative_cb(void *data, const Efl_Event *event)
66{
67 Options opt = (Options)data;
68 Eo *btn, *slider = event->object;
69 double val;
70
71 btn = efl_key_wref_get(slider, "btn");
72 val = efl_ui_range_value_get(slider);
73
74 switch (opt)
75 {
76 case LEFT:
77 efl_ui_relative_layout_relation_left_set(layout, btn, NULL, val);
78 break;
79 case RIGHT:
80 efl_ui_relative_layout_relation_right_set(layout, btn, NULL, val);
81 break;
82 case TOP:
83 efl_ui_relative_layout_relation_top_set(layout, btn, NULL, val);
84 break;
85 case BOTTOM:
86 efl_ui_relative_layout_relation_bottom_set(layout, btn, NULL, val);
87 break;
88 }
89 efl_pack_layout_request(layout);
90}
91
92static void
93_slider_changed_align_cb(void *data, const Efl_Event *event)
94{
95 char opt = (char)(uintptr_t)data;
96 Eo *btn, *slider = event->object;
97 double val, x, y;
98
99 btn = efl_key_wref_get(slider, "btn");
100 val = efl_ui_range_value_get(slider);
101
102 efl_gfx_hint_align_get(btn, &x, &y);
103 if (opt == 'x')
104 efl_gfx_hint_align_set(btn, val, y);
105 else if (opt == 'y')
106 efl_gfx_hint_align_set(btn, x, val);
107
108 efl_pack_layout_request(layout);
109}
110
111static void
112_setter_add(Eo *vbox, Eo *btn, Options option)
113{
114 Eo *to, *hbox;
115 char *text, *btn_text;
116 double relative;
117
118 switch (option)
119 {
120 case LEFT:
121 text = "left";
122 efl_ui_relative_layout_relation_left_get(layout, btn, &to, &relative);
123 break;
124 case RIGHT:
125 text = "right";
126 efl_ui_relative_layout_relation_right_get(layout, btn, &to, &relative);
127 break;
128 case TOP:
129 text = "top";
130 efl_ui_relative_layout_relation_top_get(layout, btn, &to, &relative);
131 break;
132 case BOTTOM:
133 text = "bottom";
134 efl_ui_relative_layout_relation_bottom_get(layout, btn, &to, &relative);
135 break;
136 }
137 btn_text = ((to == layout) ? "parent" : (char *)efl_text_get(to));
138
139 hbox = efl_add(EFL_UI_BOX_CLASS, vbox,
140 efl_ui_direction_set(efl_added, EFL_UI_DIR_HORIZONTAL),
141 efl_pack_padding_set(efl_added, 2, 2, EINA_TRUE),
142 efl_pack(vbox, efl_added));
143
144 efl_add(EFL_UI_TEXT_CLASS, hbox,
145 efl_text_set(efl_added, text),
146 efl_text_interactive_editable_set(efl_added, EINA_FALSE),
147 efl_text_valign_set(efl_added, 0.5),
148 efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(40, 0)),
149 efl_gfx_hint_weight_set(efl_added, 0, EFL_GFX_HINT_EXPAND),
150 efl_pack(hbox, efl_added));
151
152 efl_add(EFL_UI_BUTTON_CLASS, hbox,
153 efl_text_set(efl_added, btn_text),
154 efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(60, 0)),
155 efl_key_wref_set(efl_added, "to", to),
156 efl_key_wref_set(efl_added, "btn", btn),
157 efl_gfx_hint_weight_set(efl_added, 0, EFL_GFX_HINT_EXPAND),
158 efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, _btn_clicked_to_cb, (void *)option),
159 efl_pack(hbox, efl_added));
160
161 efl_add(EFL_UI_SLIDER_CLASS, hbox,
162 efl_ui_range_min_max_set(efl_added, 0.0, 1.0),
163 efl_ui_range_step_set(efl_added, 0.1),
164 efl_ui_range_value_set(efl_added, relative),
165 efl_key_wref_set(efl_added, "btn", btn),
166 efl_event_callback_add(efl_added, EFL_UI_SLIDER_EVENT_CHANGED, _slider_changed_relative_cb, (void *)option),
167 efl_pack(hbox, efl_added));
168}
169
170static void
171_button_frame_add(Eo *box, Eo *btn)
172{
173 Eo *f, *vbox, *hbox;
174 double align_x, align_y;
175
176 f = efl_add(EFL_UI_FRAME_CLASS, box,
177 efl_text_set(efl_added, efl_text_get(btn)),
178 efl_gfx_hint_weight_set(efl_added, EFL_GFX_HINT_EXPAND, 0),
179 efl_pack(box, efl_added));
180
181 vbox = efl_add(EFL_UI_BOX_CLASS, f,
182 efl_ui_direction_set(efl_added, EFL_UI_DIR_VERTICAL),
183 efl_pack_padding_set(efl_added, 2, 2, EINA_TRUE),
184 efl_gfx_hint_margin_set(efl_added, 2, 2, 2, 2),
185 efl_content_set(f, efl_added));
186
187 hbox = efl_add(EFL_UI_BOX_CLASS, vbox,
188 efl_ui_direction_set(efl_added, EFL_UI_DIR_HORIZONTAL),
189 efl_pack_padding_set(efl_added, 2, 2, EINA_TRUE),
190 efl_pack(vbox, efl_added));
191
192 efl_add(EFL_CANVAS_RECTANGLE_CLASS, hbox,
193 efl_gfx_color_set(efl_added, 0, 0, 0, 0),
194 efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(40, 0)),
195 efl_gfx_hint_weight_set(efl_added, 0, EFL_GFX_HINT_EXPAND),
196 efl_pack(hbox, efl_added));
197
198 efl_add(EFL_UI_TEXT_CLASS, hbox,
199 efl_text_set(efl_added, "to"),
200 efl_text_interactive_editable_set(efl_added, EINA_FALSE),
201 efl_text_halign_set(efl_added, 0.5),
202 efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(60, 0)),
203 efl_gfx_hint_weight_set(efl_added, 0, EFL_GFX_HINT_EXPAND),
204 efl_pack(hbox, efl_added));
205
206 efl_add(EFL_UI_TEXT_CLASS, hbox,
207 efl_text_set(efl_added, "relative"),
208 efl_text_halign_set(efl_added, 0.5),
209 efl_text_interactive_editable_set(efl_added, EINA_FALSE),
210 efl_pack(hbox, efl_added));
211
212 _setter_add(vbox, btn, LEFT);
213 _setter_add(vbox, btn, RIGHT);
214 _setter_add(vbox, btn, TOP);
215 _setter_add(vbox, btn, BOTTOM);
216
217 /* align setter */
218 efl_gfx_hint_align_get(btn, &align_x, &align_y);
219
220 hbox = efl_add(EFL_UI_BOX_CLASS, vbox,
221 efl_ui_direction_set(efl_added, EFL_UI_DIR_HORIZONTAL),
222 efl_pack_padding_set(efl_added, 2, 2, EINA_TRUE),
223 efl_pack(vbox, efl_added));
224
225 efl_add(EFL_UI_TEXT_CLASS, hbox,
226 efl_text_set(efl_added, "align_x"),
227 efl_text_interactive_editable_set(efl_added, EINA_FALSE),
228 efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(40, 0)),
229 efl_gfx_hint_weight_set(efl_added, 0, EFL_GFX_HINT_EXPAND),
230 efl_pack(hbox, efl_added));
231
232 efl_add(EFL_UI_SLIDER_CLASS, hbox,
233 efl_ui_range_min_max_set(efl_added, 0.0, 1.0),
234 efl_ui_range_step_set(efl_added, 0.1),
235 efl_ui_range_value_set(efl_added, align_x),
236 efl_key_wref_set(efl_added, "btn", btn),
237 efl_event_callback_add(efl_added, EFL_UI_SLIDER_EVENT_CHANGED, _slider_changed_align_cb, (void *)'x'),
238 efl_pack(hbox, efl_added));
239
240 hbox = efl_add(EFL_UI_BOX_CLASS, vbox,
241 efl_ui_direction_set(efl_added, EFL_UI_DIR_HORIZONTAL),
242 efl_pack_padding_set(efl_added, 2, 2, EINA_TRUE),
243 efl_pack(vbox, efl_added));
244
245 efl_add(EFL_UI_TEXT_CLASS, hbox,
246 efl_text_set(efl_added, "align_y"),
247 efl_text_interactive_editable_set(efl_added, EINA_FALSE),
248 efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(40, 0)),
249 efl_gfx_hint_weight_set(efl_added, 0, EFL_GFX_HINT_EXPAND),
250 efl_pack(hbox, efl_added));
251
252 efl_add(EFL_UI_SLIDER_CLASS, hbox,
253 efl_ui_range_min_max_set(efl_added, 0.0, 1.0),
254 efl_ui_range_step_set(efl_added, 0.1),
255 efl_ui_range_value_set(efl_added, align_y),
256 efl_key_wref_set(efl_added, "btn", btn),
257 efl_event_callback_add(efl_added, EFL_UI_SLIDER_EVENT_CHANGED, _slider_changed_align_cb, (void *)'y'),
258 efl_pack(hbox, efl_added));
259}
260
261void
262test_ui_relative_layout(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
263{
264 Eo *win, *vbox, *f, *hbox;
265
266 win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
267 efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
268 efl_text_set(efl_added, "Efl.Ui.Relative_Layout"),
269 efl_ui_win_autodel_set(efl_added, EINA_TRUE));
270
271 vbox = efl_add(EFL_UI_BOX_CLASS, win,
272 efl_ui_direction_set(efl_added, EFL_UI_DIR_VERTICAL),
273 efl_pack_padding_set(efl_added, 10, 10, EINA_TRUE),
274 efl_gfx_hint_margin_set(efl_added, 5, 5, 5, 5),
275 efl_content_set(win, efl_added));
276
277 /* controls */
278 f = efl_add(EFL_UI_FRAME_CLASS, vbox,
279 efl_text_set(efl_added, "Controls"),
280 efl_gfx_hint_weight_set(efl_added, EFL_GFX_HINT_EXPAND, 0),
281 efl_pack(vbox, efl_added));
282
283 hbox = efl_add(EFL_UI_BOX_CLASS, f,
284 efl_ui_direction_set(efl_added, EFL_UI_DIR_HORIZONTAL),
285 efl_pack_padding_set(efl_added, 10, 0, EINA_TRUE),
286 efl_content_set(f, efl_added));
287
288 /* contents */
289 f = efl_add(EFL_UI_FRAME_CLASS, vbox,
290 efl_text_set(efl_added, "Contents"),
291 efl_pack(vbox, efl_added));
292
293 layout = efl_add(EFL_UI_RELATIVE_LAYOUT_CLASS, f,
294 efl_content_set(f, efl_added));
295
296 btn1 = efl_add(EFL_UI_BUTTON_CLASS, layout,
297 efl_text_set(efl_added, "button1"),
298 efl_gfx_hint_align_set(efl_added, 0.0, 0.0),
299 efl_ui_relative_layout_relation_right_set(layout, efl_added, layout, 0.0),
300 efl_ui_relative_layout_relation_bottom_set(layout, efl_added, layout, 0.0));
301
302 btn2 = efl_add(EFL_UI_BUTTON_CLASS, layout,
303 efl_text_set(efl_added, "button2"),
304 efl_gfx_hint_align_set(efl_added, 0.5, 0.0),
305 efl_ui_relative_layout_relation_left_set(layout, efl_added, btn1, 1.0),
306 efl_ui_relative_layout_relation_bottom_set(layout, efl_added, layout, 0.0));
307
308 btn3 = efl_add(EFL_UI_BUTTON_CLASS, layout,
309 efl_text_set(efl_added, "button3"),
310 efl_ui_relative_layout_relation_left_set(layout, efl_added, btn2, 0.0),
311 efl_ui_relative_layout_relation_top_set(layout, efl_added, btn2, 1.0));
312
313 _button_frame_add(hbox, btn1);
314 _button_frame_add(hbox, btn2);
315 _button_frame_add(hbox, btn3);
316
317 efl_gfx_entity_size_set(win, EINA_SIZE2D(600, 400));
318 efl_gfx_entity_visible_set(win, EINA_TRUE);
319}
diff --git a/src/examples/elementary.mk b/src/examples/elementary.mk
index ac8fe37c41..dcae89bb90 100644
--- a/src/examples/elementary.mk
+++ b/src/examples/elementary.mk
@@ -125,7 +125,9 @@ elementary/efl_ui_list_view_example_2.c \
125elementary/efl_ui_list_view_example_3.c \ 125elementary/efl_ui_list_view_example_3.c \
126elementary/efl_canvas_layout_text.c \ 126elementary/efl_canvas_layout_text.c \
127elementary/efl_ui_theme_example_01.c \ 127elementary/efl_ui_theme_example_01.c \
128elementary/efl_ui_theme_example_02.c 128elementary/efl_ui_theme_example_02.c \
129elementary/efl_ui_relative_layout_example_01.c \
130elementary/efl_ui_relative_layout_example_02.c
129 131
130ELM_SRCS += \ 132ELM_SRCS += \
131elementary/bg_cxx_example_01.cc \ 133elementary/bg_cxx_example_01.cc \
@@ -344,7 +346,9 @@ elementary/efl_ui_list_view_example_2 \
344elementary/efl_ui_list_view_example_3 \ 346elementary/efl_ui_list_view_example_3 \
345elementary/efl_canvas_layout_text \ 347elementary/efl_canvas_layout_text \
346elementary/efl_ui_theme_example_01 \ 348elementary/efl_ui_theme_example_01 \
347elementary/efl_ui_theme_example_02 349elementary/efl_ui_theme_example_02 \
350elementary/efl_ui_relative_layout_example_01 \
351elementary/efl_ui_relative_layout_example_02
348#benchmark3d 352#benchmark3d
349#sphere-hunter 353#sphere-hunter
350 354
diff --git a/src/examples/elementary/.gitignore b/src/examples/elementary/.gitignore
index 11544b23ee..06e20555aa 100644
--- a/src/examples/elementary/.gitignore
+++ b/src/examples/elementary/.gitignore
@@ -169,3 +169,5 @@
169/efl_ui_list_view_example_3 169/efl_ui_list_view_example_3
170/efl_ui_theme_example_01 170/efl_ui_theme_example_01
171/efl_ui_theme_example_02 171/efl_ui_theme_example_02
172/efl_ui_relative_layout_example_01
173/efl_ui_relative_layout_example_02
diff --git a/src/examples/elementary/efl_ui_relative_layout_example_01.c b/src/examples/elementary/efl_ui_relative_layout_example_01.c
new file mode 100644
index 0000000000..36ebd3f545
--- /dev/null
+++ b/src/examples/elementary/efl_ui_relative_layout_example_01.c
@@ -0,0 +1,51 @@
1// gcc -o efl_ui_relative_layout_example_01 efl_ui_relative_layout_example_01.c `pkg-config --cflags --libs elementary`
2
3#ifdef HAVE_CONFIG_H
4#include "elementary_config.h"
5#else
6#define EFL_BETA_API_SUPPORT 1
7#define EFL_EO_API_SUPPORT 1
8#endif
9
10#include <Elementary.h>
11#include <Efl.h>
12
13EAPI_MAIN int
14elm_main(int argc, char **argv)
15{
16 Eo *win, *layout, *btn1, *btn2, *btn3;
17
18 win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
19 efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
20 efl_text_set(efl_added, "Efl.Ui.Relative_Layout"),
21 efl_ui_win_autodel_set(efl_added, EINA_TRUE));
22
23 layout = efl_add(EFL_UI_RELATIVE_LAYOUT_CLASS, win,
24 efl_content_set(win, efl_added));
25
26 btn1 = efl_add(EFL_UI_BUTTON_CLASS, layout,
27 efl_text_set(efl_added, "btn1"),
28 efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(100, 100)),
29 efl_gfx_hint_align_set(efl_added, 0, 0),
30 efl_gfx_hint_margin_set(efl_added, 10, 30, 20, 40),
31 efl_ui_relative_layout_relation_right_set(layout, efl_added, layout, 0.0),
32 efl_ui_relative_layout_relation_bottom_set(layout, efl_added, layout, 0.0));
33
34 btn2 = efl_add(EFL_UI_BUTTON_CLASS, layout,
35 efl_text_set(efl_added, "btn2"),
36 efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(0, 200)),
37 efl_gfx_hint_align_set(efl_added, 0.5, 0),
38 efl_ui_relative_layout_relation_left_set(layout, efl_added, btn1, 1.0),
39 efl_ui_relative_layout_relation_bottom_set(layout, efl_added, layout, 0.0));
40
41 btn3 = efl_add(EFL_UI_BUTTON_CLASS, layout,
42 efl_text_set(efl_added, "btn3"),
43 efl_ui_relative_layout_relation_left_set(layout, efl_added, btn2, 0.0),
44 efl_ui_relative_layout_relation_top_set(layout, efl_added, btn2, 1.0));
45
46 efl_gfx_entity_size_set(win, EINA_SIZE2D(300, 300));
47
48 elm_run();
49 return 0;
50}
51ELM_MAIN()
diff --git a/src/examples/elementary/efl_ui_relative_layout_example_02.c b/src/examples/elementary/efl_ui_relative_layout_example_02.c
new file mode 100644
index 0000000000..4a8d46a810
--- /dev/null
+++ b/src/examples/elementary/efl_ui_relative_layout_example_02.c
@@ -0,0 +1,45 @@
1// gcc -o efl_ui_relative_layout_example_02 efl_ui_relative_layout_example_02.c `pkg-config --cflags --libs elementary`
2
3#ifdef HAVE_CONFIG_H
4#include "elementary_config.h"
5#else
6#define EFL_BETA_API_SUPPORT 1
7#define EFL_EO_API_SUPPORT 1
8#endif
9
10#include <Elementary.h>
11#include <Efl.h>
12
13EAPI_MAIN int
14elm_main(int argc, char **argv)
15{
16 Eo *win, *layout, *btn1, *btn2;
17
18 win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
19 efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
20 efl_text_set(efl_added, "Efl.Ui.Relative_Layout"),
21 efl_ui_win_autodel_set(efl_added, EINA_TRUE));
22
23 layout = efl_add(EFL_UI_RELATIVE_LAYOUT_CLASS, win,
24 efl_content_set(win, efl_added));
25
26 btn1 = efl_add(EFL_UI_BUTTON_CLASS, layout,
27 efl_text_set(efl_added, "btn1"),
28 efl_gfx_size_hint_min_set(efl_added, EINA_SIZE2D(100, 100)));
29
30 btn2 = efl_add(EFL_UI_BUTTON_CLASS, layout,
31 efl_text_set(efl_added, "btn2"),
32 efl_gfx_size_hint_min_set(efl_added, EINA_SIZE2D(0, 100)));
33
34 efl_ui_relative_layout_relation_right_set(layout, btn1, btn2, 0.0);
35 efl_ui_relative_layout_relation_bottom_set(layout, btn1, btn2, 0.0);
36
37 efl_ui_relative_layout_relation_left_set(layout, btn2, btn1, 1.0);
38 efl_ui_relative_layout_relation_top_set(layout, btn2, btn1, 1.0);
39
40 efl_gfx_entity_size_set(win, EINA_SIZE2D(300, 300));
41
42 elm_run();
43 return 0;
44}
45ELM_MAIN()
diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h
index 54b816a6fe..515ee48c06 100644
--- a/src/lib/elementary/Efl_Ui.h
+++ b/src/lib/elementary/Efl_Ui.h
@@ -188,6 +188,7 @@ EAPI void efl_ui_focus_relation_free(Efl_Ui_Focus_Relations *rel);
188# include <efl_ui_win.eo.h> 188# include <efl_ui_win.eo.h>
189# include <efl_ui_win_inlined.eo.h> 189# include <efl_ui_win_inlined.eo.h>
190# include <efl_ui_win_socket.eo.h> 190# include <efl_ui_win_socket.eo.h>
191# include <efl_ui_relative_layout.eo.h>
191 192
192/* FIXME: Efl.Ui.Text must not use elm_general.h */ 193/* FIXME: Efl.Ui.Text must not use elm_general.h */
193# warning Efl.Ui.Text is not available yet without Elementary.h 194# warning Efl.Ui.Text is not available yet without Elementary.h
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index 5bb8374e3a..8e54b4a710 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -360,6 +360,7 @@ EAPI void efl_ui_focus_relation_free(Efl_Ui_Focus_Relations *rel);
360# include <efl_ui_navigation_bar_part_back_button.eo.h> 360# include <efl_ui_navigation_bar_part_back_button.eo.h>
361# include <efl_ui_navigation_layout.eo.h> 361# include <efl_ui_navigation_layout.eo.h>
362# include <efl_ui_stack.eo.h> 362# include <efl_ui_stack.eo.h>
363# include <efl_ui_relative_layout.eo.h>
363 364
364# ifndef _EFL_UI_PAGER_EO_CLASS_TYPE 365# ifndef _EFL_UI_PAGER_EO_CLASS_TYPE
365# define _EFL_UI_PAGER_EO_CLASS_TYPE 366# define _EFL_UI_PAGER_EO_CLASS_TYPE
diff --git a/src/lib/elementary/efl_ui_relative_layout.c b/src/lib/elementary/efl_ui_relative_layout.c
new file mode 100644
index 0000000000..c5651fa793
--- /dev/null
+++ b/src/lib/elementary/efl_ui_relative_layout.c
@@ -0,0 +1,552 @@
1#include "efl_ui_relative_layout_private.h"
2
3#define MY_CLASS EFL_UI_RELATIVE_LAYOUT_CLASS
4#define MY_CLASS_NAME "Efl.Ui.Relative_Layout"
5
6#define LEFT 0
7#define RIGHT 1
8#define TOP 2
9#define BOTTOM 3
10
11#define START (axis ? TOP : LEFT)
12#define END (axis ? BOTTOM : RIGHT)
13
14static void _child_calc(Efl_Ui_Relative_Layout_Child *child, Eina_Bool axis);
15
16static int
17_chain_sort_cb(const void *l1, const void *l2)
18{
19 Efl_Ui_Relative_Layout_Calc *calc1, *calc2;
20
21 calc1 = EINA_INLIST_CONTAINER_GET(l1, Efl_Ui_Relative_Layout_Calc);
22 calc2 = EINA_INLIST_CONTAINER_GET(l2, Efl_Ui_Relative_Layout_Calc);
23
24 return calc2->comp_factor <= calc1->comp_factor ? -1 : 1;
25}
26
27static Efl_Ui_Relative_Layout_Child *
28_efl_ui_relative_layout_register(Efl_Ui_Relative_Layout_Data *pd, Eo *child)
29{
30 Efl_Ui_Relative_Layout_Child *rc;
31
32 rc = calloc(1, sizeof(Efl_Ui_Relative_Layout_Child));
33 if (!rc) return NULL;
34
35 rc->obj = child;
36 rc->layout = pd->obj;
37 rc->rel[LEFT].to = rc->layout;
38 rc->rel[LEFT].relative = 0.0;
39 rc->rel[RIGHT].to = rc->layout;
40 rc->rel[RIGHT].relative = 1.0;
41 rc->rel[TOP].to = rc->layout;
42 rc->rel[TOP].relative = 0.0;
43 rc->rel[BOTTOM].to = rc->layout;
44 rc->rel[BOTTOM].relative = 1.0;
45
46 if (pd->obj == child)
47 {
48 rc->calc.state[0] = RELATIVE_CALC_DONE;
49 rc->calc.state[1] = RELATIVE_CALC_DONE;
50 rc->calc.chain_state[0] = RELATIVE_CALC_DONE;
51 rc->calc.chain_state[1] = RELATIVE_CALC_DONE;
52 }
53 else
54 {
55 efl_ui_widget_sub_object_add(pd->obj, child);
56 efl_canvas_group_member_add(pd->obj, child);
57 efl_canvas_group_change(pd->obj);
58 }
59
60 eina_hash_add(pd->children, &child, rc);
61
62 return rc;
63}
64
65static Efl_Ui_Relative_Layout_Child *
66_relative_child_get(Efl_Ui_Relative_Layout_Data *pd, Eo *child)
67{
68 Efl_Ui_Relative_Layout_Child *rc;
69
70 rc = eina_hash_find(pd->children, &child);
71 if (!rc)
72 rc = _efl_ui_relative_layout_register(pd, child);
73
74 return rc;
75}
76
77static Efl_Ui_Relative_Layout_Child *
78_relative_child_find(const Eina_Hash *children, Eo *target)
79{
80 Efl_Ui_Relative_Layout_Child *child;
81
82 child = eina_hash_find(children, &target);
83 if (!child)
84 ERR("target(%p(%s)) is not registered", target, efl_class_name_get(target));
85
86 return child;
87}
88
89static void
90_child_aspect_calc(Efl_Ui_Relative_Layout_Child *child, Eina_Bool axis)
91{
92 Efl_Ui_Relative_Layout_Calc *calc = &child->calc;
93 int temph;
94
95 if ((calc->aspect[0] <= 0) || (calc->aspect[1] <= 0))
96 {
97 ERR("Invalid aspect parameter for obj(%p), aspect(%d, %d) ",
98 child->obj, calc->aspect[0], calc->aspect[1]);
99 return;
100 }
101
102 switch (calc->aspect_type)
103 {
104 case EFL_GFX_HINT_ASPECT_HORIZONTAL:
105 if (axis) _child_calc(child, !axis);
106 calc->want[1].length = calc->want[0].length * calc->aspect[1] / calc->aspect[0];
107 break;
108 case EFL_GFX_HINT_ASPECT_VERTICAL:
109 if (!axis) _child_calc(child, !axis);
110 calc->want[0].length = calc->want[1].length * calc->aspect[0] / calc->aspect[1];
111 break;
112 case EFL_GFX_HINT_ASPECT_BOTH:
113 if (calc->state[!axis] != RELATIVE_CALC_ON)
114 _child_calc(child, !axis);
115 temph = calc->want[axis].length * calc->aspect[!axis] / calc->aspect[axis];
116 if (temph > calc->want[!axis].length)
117 {
118 temph = calc->want[!axis].length;
119 calc->want[axis].length = temph * calc->aspect[axis] / calc->aspect[!axis];
120 }
121 else
122 calc->want[!axis].length = temph;
123 break;
124 default:
125 if (calc->state[!axis] != RELATIVE_CALC_ON)
126 _child_calc(child, !axis);
127 temph = calc->want[axis].length * calc->aspect[!axis] / calc->aspect[axis];
128 if (temph < calc->want[!axis].length)
129 {
130 temph = calc->want[!axis].length;
131 calc->want[axis].length = temph * calc->aspect[axis] / calc->aspect[!axis];
132 }
133 else
134 calc->want[!axis].length = temph;
135 }
136
137 //calculate max size
138 if (calc->want[0].length > calc->max[0])
139 {
140 calc->want[0].length = calc->max[0];
141 calc->want[1].length = calc->want[0].length * calc->aspect[1] / calc->aspect[0];
142 }
143 if (calc->want[1].length > calc->max[1])
144 {
145 calc->want[1].length = calc->max[1];
146 calc->want[0].length = calc->want[1].length * calc->aspect[0] / calc->aspect[1];
147 }
148 //calculate min size
149 if (calc->want[0].length < calc->min[0])
150 {
151 calc->want[0].length = calc->min[0];
152 calc->want[1].length = calc->want[0].length * calc->aspect[1] / calc->aspect[0];
153 }
154 if (calc->want[1].length < calc->min[1])
155 {
156 calc->want[1].length = calc->min[1];
157 calc->want[0].length = calc->want[1].length * calc->aspect[0] / calc->aspect[1];
158 }
159
160 //calculate align
161 calc->want[!axis].position =
162 calc->space[!axis].position +
163 (calc->space[!axis].length - calc->want[!axis].length) * calc->align[!axis];
164}
165
166static Eina_Bool
167_child_chain_calc(Efl_Ui_Relative_Layout_Child *child, Eina_Bool axis)
168{
169 Efl_Ui_Relative_Layout_Child *head, *tail, *o;
170 Efl_Gfx_Hint_Aspect aspect_type;
171 int space, min_sum = 0;
172 double weight_sum = 0, cur_pos;
173 Eina_Inlist *chain = NULL;
174
175 if (child->calc.chain_state[axis] == RELATIVE_CALC_DONE)
176 return EINA_TRUE;
177
178 if ((child != child->calc.to[START]->calc.to[END]) &&
179 (child != child->calc.to[END]->calc.to[START]))
180 return EINA_FALSE;
181
182 // find head
183 head = child;
184 while (head == head->calc.to[START]->calc.to[END])
185 head = head->calc.to[START];
186
187 //calculate weight_sum
188 aspect_type = !axis ? EFL_GFX_HINT_ASPECT_VERTICAL : EFL_GFX_HINT_ASPECT_HORIZONTAL;
189 o = head;
190 do
191 {
192 if ((o->calc.aspect[0] > 0) && (o->calc.aspect[1] > 0) &&
193 (o->calc.aspect_type == aspect_type))
194 {
195 _child_calc(o, !axis);
196 if (o->calc.want[axis].length > o->calc.min[axis])
197 o->calc.min[axis] = o->calc.want[axis].length;
198 }
199 else if ((o->calc.aspect[0] <= 0) ^ (o->calc.aspect[1] <= 0))
200 {
201 ERR("Invalid aspect parameter for obj(%p), aspect(%d, %d) ",
202 o->obj, o->calc.aspect[0], o->calc.aspect[1]);
203 }
204
205 o->calc.space[axis].length = o->calc.min[axis] +
206 o->calc.margin[START] + o->calc.margin[END];
207 min_sum += o->calc.space[axis].length;
208 weight_sum += o->calc.weight[axis];
209
210 tail = o;
211 o = o->calc.to[END];
212 }
213 while (o->calc.to[START] == tail);
214
215 _child_calc(head->calc.to[START], axis);
216 _child_calc(tail->calc.to[END], axis);
217
218 cur_pos = head->calc.to[START]->calc.want[axis].position +
219 (head->calc.to[START]->calc.want[axis].length * head->rel[START].relative);
220 space = tail->calc.to[END]->calc.want[axis].position +
221 (tail->calc.to[END]->calc.want[axis].length * tail->rel[END].relative) - cur_pos;
222
223 if ((space <= min_sum) || EINA_DBL_EQ(weight_sum, 0.0))
224 cur_pos += (space - min_sum) * head->calc.align[axis];
225 else
226 {
227 Efl_Ui_Relative_Layout_Calc *calc;
228 double weight_len, orig_space = space, orig_weight = weight_sum;
229
230 // Calculate compare factor
231 for (o = head; o != tail->calc.to[END]; o = o->calc.to[END])
232 {
233 double denom;
234
235 calc = &o->calc;
236 denom = (calc->weight[axis] * orig_space) - (orig_weight * calc->min[axis]);
237 if (denom > 0)
238 {
239 calc->comp_factor = (calc->weight[axis] * orig_space) / denom;
240 chain = eina_inlist_sorted_insert(chain, EINA_INLIST_GET(calc),
241 _chain_sort_cb);
242 }
243 else
244 {
245 space -= calc->space[axis].length;
246 weight_sum -= calc->weight[axis];
247 }
248 }
249
250 EINA_INLIST_FOREACH(chain, calc)
251 {
252 weight_len = (space * calc->weight[axis]) / weight_sum;
253
254 if (calc->space[axis].length < weight_len)
255 calc->space[axis].length = weight_len;
256 else
257 {
258 weight_sum -= calc->weight[axis];
259 space -= calc->space[axis].length;
260 }
261 }
262 }
263
264 for (o = head; o != tail->calc.to[END]; o = o->calc.to[END])
265 {
266 o->calc.space[axis].position = cur_pos + o->calc.margin[START] + 0.5;
267 cur_pos += o->calc.space[axis].length;
268 o->calc.space[axis].length -= o->calc.margin[START] + o->calc.margin[END];
269 o->calc.chain_state[axis] = RELATIVE_CALC_DONE;
270 }
271
272 return EINA_TRUE;
273}
274
275static void
276_child_calc(Efl_Ui_Relative_Layout_Child *child, Eina_Bool axis)
277{
278 Efl_Ui_Relative_Layout_Calc *calc = &child->calc;
279
280 if (calc->state[axis] == RELATIVE_CALC_DONE)
281 return;
282
283 if (calc->state[axis] == RELATIVE_CALC_ON)
284 {
285 ERR("%c-axis circular dependency when calculating part \"%s\"(%p).",
286 axis ? 'Y' : 'X', efl_class_name_get(child->obj), child->obj);
287 return;
288 }
289
290 calc->state[axis] = RELATIVE_CALC_ON;
291
292 if (!_child_chain_calc(child, axis))
293 {
294 _child_calc(calc->to[START], axis);
295 _child_calc(calc->to[END], axis);
296
297 calc->space[axis].position = calc->to[START]->calc.want[axis].position
298 + (calc->to[START]->calc.want[axis].length * child->rel[START].relative)
299 + calc->margin[START];
300 calc->space[axis].length = calc->to[END]->calc.want[axis].position
301 + (calc->to[END]->calc.want[axis].length * child->rel[END].relative)
302 - calc->margin[END] - calc->space[axis].position;
303 }
304
305 if (calc->fill[axis] && (calc->weight[axis] > 0))
306 calc->want[axis].length = calc->space[axis].length;
307
308 if (!calc->aspect[0] && !calc->aspect[1])
309 {
310 if (calc->want[axis].length > calc->max[axis])
311 calc->want[axis].length = calc->max[axis];
312
313 if (calc->want[axis].length < calc->min[axis])
314 calc->want[axis].length = calc->min[axis];
315 }
316 else
317 {
318 _child_aspect_calc(child, axis);
319 }
320
321 //calculate align
322 calc->want[axis].position =
323 calc->space[axis].position +
324 (calc->space[axis].length - calc->want[axis].length) * calc->align[axis];
325
326 child->calc.state[axis] = RELATIVE_CALC_DONE;
327}
328
329static void
330_hash_free_cb(void *data)
331{
332 Efl_Ui_Relative_Layout_Child *child = data;
333
334 free(child);
335}
336
337static Eina_Bool
338_hash_free_foreach_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
339 void *data, void *fdata EINA_UNUSED)
340{
341 Efl_Ui_Relative_Layout_Child *child = data;
342
343 _elm_widget_sub_object_redirect_to_top(child->layout, child->obj);
344 _hash_free_cb(child);
345
346 return EINA_TRUE;
347}
348
349static Eina_Bool
350_hash_child_calc_foreach_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
351 void *data, void *fdata EINA_UNUSED)
352{
353 Efl_Ui_Relative_Layout_Child *child = data;
354 Eina_Rect want;
355
356 if (child->obj == child->layout)
357 return EINA_TRUE;
358
359 _child_calc(child, 0);
360 _child_calc(child, 1);
361
362 want.x = child->calc.want[0].position;
363 want.w = child->calc.want[0].length;
364 want.y = child->calc.want[1].position;
365 want.h = child->calc.want[1].length;
366
367 efl_gfx_entity_geometry_set(child->obj, want);
368 return EINA_TRUE;
369}
370
371
372static Eina_Bool
373_hash_child_init_foreach_cb(const Eina_Hash *hash, const void *key EINA_UNUSED,
374 void *data, void *fdata EINA_UNUSED)
375{
376 Eina_Size2D max, min, aspect;
377 Efl_Ui_Relative_Layout_Child *child = data;
378 Efl_Ui_Relative_Layout_Calc *calc = &(child->calc);
379
380 calc->to[LEFT] = _relative_child_find(hash, child->rel[LEFT].to);
381 if (!calc->to[LEFT]) calc->to[LEFT] = eina_hash_find(hash, &child->layout);
382 calc->to[RIGHT] = _relative_child_find(hash, child->rel[RIGHT].to);
383 if (!calc->to[RIGHT]) calc->to[RIGHT] = eina_hash_find(hash, &child->layout);
384 calc->to[TOP] = _relative_child_find(hash, child->rel[TOP].to);
385 if (!calc->to[TOP]) calc->to[TOP] = eina_hash_find(hash, &child->layout);
386 calc->to[BOTTOM] = _relative_child_find(hash, child->rel[BOTTOM].to);
387 if (!calc->to[BOTTOM]) calc->to[BOTTOM] = eina_hash_find(hash, &child->layout);
388
389 if (child->obj == child->layout)
390 {
391 Eina_Rect want = efl_gfx_entity_geometry_get(child->obj);
392 calc->want[0].position = want.x;
393 calc->want[0].length = want.w;
394 calc->want[1].position = want.y;
395 calc->want[1].length = want.h;
396 calc->state[0] = RELATIVE_CALC_DONE;
397 calc->state[1] = RELATIVE_CALC_DONE;
398 calc->chain_state[0] = RELATIVE_CALC_DONE;
399 calc->chain_state[1] = RELATIVE_CALC_DONE;
400 return EINA_TRUE;
401 }
402
403 calc->state[0] = RELATIVE_CALC_NONE;
404 calc->state[1] = RELATIVE_CALC_NONE;
405 calc->chain_state[0] = RELATIVE_CALC_NONE;
406 calc->chain_state[1] = RELATIVE_CALC_NONE;
407
408 efl_gfx_hint_weight_get(child->obj, &calc->weight[0], &calc->weight[1]);
409 efl_gfx_hint_align_get(child->obj, &calc->align[0], &calc->align[1]);
410 efl_gfx_hint_fill_get(child->obj, &calc->fill[0], &calc->fill[1]);
411 efl_gfx_hint_aspect_get(child->obj, &calc->aspect_type, &aspect);
412 calc->aspect[0] = aspect.w;
413 calc->aspect[1] = aspect.h;
414 efl_gfx_hint_margin_get(child->obj, &calc->margin[LEFT], &calc->margin[RIGHT],
415 &calc->margin[TOP], &calc->margin[BOTTOM]);
416 max = efl_gfx_hint_size_max_get(child->obj);
417 min = efl_gfx_hint_size_combined_min_get(child->obj);
418 calc->max[0] = max.w;
419 calc->max[1] = max.h;
420 calc->min[0] = min.w;
421 calc->min[1] = min.h;
422
423 calc->want[0].position = 0;
424 calc->want[0].length = 0;
425 calc->want[1].position = 0;
426 calc->want[1].length = 0;
427 calc->space[0].position = 0;
428 calc->space[0].length = 0;
429 calc->space[1].position = 0;
430 calc->space[1].length = 0;
431
432 if (calc->weight[0] < 0) calc->weight[0] = 0;
433 if (calc->weight[1] < 0) calc->weight[1] = 0;
434
435 if (calc->align[0] < 0) calc->align[0] = 0;
436 if (calc->align[1] < 0) calc->align[1] = 0;
437 if (calc->align[0] > 1) calc->align[0] = 1;
438 if (calc->align[1] > 1) calc->align[1] = 1;
439
440 if (calc->max[0] < 0) calc->max[0] = INT_MAX;
441 if (calc->max[1] < 0) calc->max[1] = INT_MAX;
442 if (calc->aspect[0] < 0) calc->aspect[0] = 0;
443 if (calc->aspect[1] < 0) calc->aspect[1] = 0;
444
445 return EINA_TRUE;
446}
447
448static void
449_on_size_hints_changed(void *data EINA_UNUSED, Evas *e EINA_UNUSED,
450 Evas_Object *obj, void *event_info EINA_UNUSED)
451{
452 efl_pack_layout_request(obj);
453}
454
455EOLIAN static void
456_efl_ui_relative_layout_efl_pack_layout_layout_update(Eo *obj, Efl_Ui_Relative_Layout_Data *pd)
457{
458 eina_hash_foreach(pd->children, _hash_child_init_foreach_cb, NULL);
459 eina_hash_foreach(pd->children, _hash_child_calc_foreach_cb, NULL);
460
461 efl_event_callback_call(obj, EFL_PACK_EVENT_LAYOUT_UPDATED, NULL);
462}
463
464EOLIAN static void
465_efl_ui_relative_layout_efl_pack_layout_layout_request(Eo *obj, Efl_Ui_Relative_Layout_Data *pd EINA_UNUSED)
466{
467 efl_canvas_group_need_recalculate_set(obj, EINA_TRUE);
468}
469
470EOLIAN static void
471_efl_ui_relative_layout_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Relative_Layout_Data *pd EINA_UNUSED)
472{
473 efl_pack_layout_update(obj);
474}
475
476EOLIAN static void
477_efl_ui_relative_layout_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Relative_Layout_Data *pd EINA_UNUSED, Eina_Size2D sz)
478{
479 efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
480 efl_canvas_group_change(obj);
481}
482
483EOLIAN static void
484_efl_ui_relative_layout_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Relative_Layout_Data *pd EINA_UNUSED, Eina_Position2D pos)
485{
486 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
487 efl_canvas_group_change(obj);
488}
489
490EOLIAN static void
491_efl_ui_relative_layout_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Relative_Layout_Data *pd EINA_UNUSED)
492{
493 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_size_hints_changed, NULL);
494 efl_canvas_group_add(efl_super(obj, MY_CLASS));
495 elm_widget_sub_object_parent_add(obj);
496
497 elm_widget_highlight_ignore_set(obj, EINA_TRUE);
498}
499
500EOLIAN static Eo *
501_efl_ui_relative_layout_efl_object_constructor(Eo *obj, Efl_Ui_Relative_Layout_Data *pd)
502{
503 obj = efl_constructor(efl_super(obj, MY_CLASS));
504 efl_canvas_object_type_set(obj, MY_CLASS_NAME);
505 efl_access_object_access_type_set(obj, EFL_ACCESS_TYPE_SKIPPED);
506 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_FILLER);
507
508 pd->obj = obj;
509 pd->children = eina_hash_pointer_new(_hash_free_cb);
510 _efl_ui_relative_layout_register(pd, obj);
511
512 return obj;
513}
514
515EOLIAN static void
516_efl_ui_relative_layout_efl_object_destructor(Eo *obj, Efl_Ui_Relative_Layout_Data *pd)
517{
518 eina_hash_free(pd->children);
519 efl_destructor(efl_super(obj, MY_CLASS));
520}
521
522EOLIAN static void
523_efl_ui_relative_layout_unregister(Eo *obj, Efl_Ui_Relative_Layout_Data *pd, Efl_Object *child)
524{
525 _elm_widget_sub_object_redirect_to_top(obj, child);
526 if (!eina_hash_del_by_key(pd->children, &child))
527 ERR("child(%p(%s)) is not registered", child, efl_class_name_get(child));
528}
529
530EOLIAN static void
531_efl_ui_relative_layout_unregister_all(Eo *obj EINA_UNUSED, Efl_Ui_Relative_Layout_Data *pd)
532{
533 eina_hash_foreach(pd->children, _hash_free_foreach_cb, NULL);
534}
535
536EOLIAN static Eina_Iterator *
537_efl_ui_relative_layout_children_iterate(Eo *obj EINA_UNUSED, Efl_Ui_Relative_Layout_Data *pd)
538{
539 return eina_hash_iterator_data_new(pd->children);
540}
541
542EFL_UI_RELATIVE_LAYOUT_RELATION_SET_GET(left, LEFT);
543EFL_UI_RELATIVE_LAYOUT_RELATION_SET_GET(right, RIGHT);
544EFL_UI_RELATIVE_LAYOUT_RELATION_SET_GET(top, TOP);
545EFL_UI_RELATIVE_LAYOUT_RELATION_SET_GET(bottom, BOTTOM);
546
547/* Internal EO APIs and hidden overrides */
548
549#define EFL_UI_RELATIVE_LAYOUT_EXTRA_OPS \
550 EFL_CANVAS_GROUP_ADD_OPS(efl_ui_relative_layout)
551
552#include "efl_ui_relative_layout.eo.c"
diff --git a/src/lib/elementary/efl_ui_relative_layout.eo b/src/lib/elementary/efl_ui_relative_layout.eo
new file mode 100644
index 0000000000..967f23d623
--- /dev/null
+++ b/src/lib/elementary/efl_ui_relative_layout.eo
@@ -0,0 +1,79 @@
1class Efl.Ui.Relative_Layout extends Efl.Ui.Widget implements Efl.Pack_Layout
2{
3 [[The relative layout class.
4
5 A relative layout calculates the size and position of all the children
6 based on their relationship to each other.]]
7 methods {
8 @property relation_left {
9 [[Specifies the left side edge of the child relative to the target.
10 By default, target is parent and relative is 0.0.]]
11 keys {
12 child: Efl.Object; [[The child to specify relation.]]
13 }
14 values {
15 target: Efl.Object; [[The relative target.]]
16 relative: double; [[The ratio between left and right of the target,
17 ranging from 0.0 to 1.0.]]
18 }
19 }
20 @property relation_right {
21 [[Specifies the right side edge of the child relative to the target.
22 By default, target is parent and relative is 1.0.]]
23 keys {
24 child: Efl.Object; [[The child to specify relation.]]
25 }
26 values {
27 target: Efl.Object; [[The relative target.]]
28 relative: double; [[The ratio between left and right of the target,
29 ranging from 0.0 to 1.0.]]
30 }
31 }
32 @property relation_top {
33 [[Specifies the top side edge of the child relative to the target.
34 By default, target is parent and relative is 0.0.]]
35 keys {
36 child: Efl.Object; [[The child to specify relation.]]
37 }
38 values {
39 target: Efl.Object; [[The relative target.]]
40 relative: double; [[The ratio between top and bottom of the target,
41 ranging from 0.0 to 1.0.]]
42 }
43 }
44 @property relation_bottom {
45 [[Specifies the bottom side edge of the child relative to the target.
46 By default, target is parent and relative is 1.0.]]
47 keys {
48 child: Efl.Object; [[The child to specify relation.]]
49 }
50 values {
51 target: Efl.Object; [[The relative target.]]
52 relative: double; [[The ratio between top and bottom of the target,
53 ranging from 0.0 to 1.0.]]
54 }
55 }
56 unregister {
57 [[Remove all relations of the child.]]
58 params {
59 @in child: Efl.Object; [[The child to unregister]]
60 }
61 }
62 unregister_all {
63 [[Remove all relations from the registered children. ]]
64 }
65 children_iterate {
66 [[Begin iterating over this object's children.]]
67 return: iterator<Efl.Object> @owned @warn_unused; [[Iterator to object children.]]
68 }
69 }
70 implements {
71 Efl.Object.constructor;
72 Efl.Object.destructor;
73 Efl.Canvas.Group.group_calculate;
74 Efl.Gfx.Entity.position { set; }
75 Efl.Gfx.Entity.size { set; }
76 Efl.Pack_Layout.layout_update;
77 Efl.Pack_Layout.layout_request;
78 }
79}
diff --git a/src/lib/elementary/efl_ui_relative_layout_private.h b/src/lib/elementary/efl_ui_relative_layout_private.h
new file mode 100644
index 0000000000..b7410efc49
--- /dev/null
+++ b/src/lib/elementary/efl_ui_relative_layout_private.h
@@ -0,0 +1,90 @@
1#ifndef EFL_UI_RELATIVE_LAYOUT_PRIVATE_H
2#define EFL_UI_RELATIVE_LAYOUT_PRIVATE_H
3
4#ifdef HAVE_CONFIG_H
5# include "elementary_config.h"
6#endif
7
8#define EFL_PACK_LAYOUT_PROTECTED
9
10#include <Elementary.h>
11#include "elm_priv.h"
12
13typedef enum _Efl_Ui_Relative_Layout_Calc_State
14{
15 RELATIVE_CALC_NONE,
16 RELATIVE_CALC_DONE,
17 RELATIVE_CALC_ON
18} Efl_Ui_Relative_Layout_Calc_State;
19
20typedef struct _Efl_Ui_Relative_Layout_Data Efl_Ui_Relative_Layout_Data;
21typedef struct _Efl_Ui_Relative_Layout_Child Efl_Ui_Relative_Layout_Child;
22typedef struct _Efl_Ui_Relative_Layout_Calc Efl_Ui_Relative_Layout_Calc;
23typedef struct _Efl_Ui_Relative_Layout_Relation Efl_Ui_Relative_Layout_Relation;
24
25struct _Efl_Ui_Relative_Layout_Calc
26{
27 EINA_INLIST;
28
29 int max[2];
30 int min[2];
31 int aspect[2];
32 int margin[4];
33 Efl_Gfx_Hint_Aspect aspect_type;
34 Eina_Bool fill[2];
35 double weight[2];
36 double align[2];
37 double comp_factor;
38
39 struct {
40 int position;
41 double length;
42 } space[2], want[2];
43
44 Efl_Ui_Relative_Layout_Calc_State state[2];
45 Efl_Ui_Relative_Layout_Calc_State chain_state[2];
46 Efl_Ui_Relative_Layout_Child *to[4];
47};
48
49struct _Efl_Ui_Relative_Layout_Data
50{
51 Eo *obj;
52 Eina_Hash *children;
53};
54
55struct _Efl_Ui_Relative_Layout_Relation
56{
57 Efl_Object *to;
58 double relative;
59};
60
61struct _Efl_Ui_Relative_Layout_Child
62{
63 Eo *obj;
64 Eo *layout;
65 Efl_Ui_Relative_Layout_Relation rel[4];
66 Efl_Ui_Relative_Layout_Calc calc;
67};
68
69#define EFL_UI_RELATIVE_LAYOUT_RELATION_SET_GET(direction, DIRECTION) \
70 EOLIAN static void \
71 _efl_ui_relative_layout_relation_ ## direction ## _set(Eo *obj EINA_UNUSED, Efl_Ui_Relative_Layout_Data *pd, Eo *child, Eo *target, double relative) \
72 { \
73 Efl_Ui_Relative_Layout_Child *rc; \
74 rc = _relative_child_get(pd, child); \
75 if (target) rc->rel[DIRECTION].to = target; \
76 if (relative < 0) relative = 0; \
77 else if (relative > 1) relative = 1; \
78 rc->rel[DIRECTION].relative = relative; \
79 } \
80 \
81 EOLIAN static void \
82 _efl_ui_relative_layout_relation_ ## direction ## _get(const Eo *obj EINA_UNUSED, Efl_Ui_Relative_Layout_Data *pd, Eo *child, Eo **target, double *relative) \
83 { \
84 Efl_Ui_Relative_Layout_Child *rc; \
85 rc = _relative_child_get(pd, child); \
86 if (target) *target = rc->rel[DIRECTION].to; \
87 if (relative) *relative = rc->rel[DIRECTION].relative; \
88 }
89
90#endif
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index 21a4ab16d5..1db7752473 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -276,6 +276,7 @@ pub_eo_files = [
276 'efl_ui_text_part.eo', 276 'efl_ui_text_part.eo',
277 'efl_ui_caching_factory.eo', 277 'efl_ui_caching_factory.eo',
278 'efl_ui_widget_factory.eo', 278 'efl_ui_widget_factory.eo',
279 'efl_ui_relative_layout.eo',
279] 280]
280 281
281foreach eo_file : pub_eo_files 282foreach eo_file : pub_eo_files
@@ -480,7 +481,8 @@ elementary_headers_unstable = [
480 'efl_page_indicator_icon.h', 481 'efl_page_indicator_icon.h',
481 'efl_ui_tab_pager_private.h', 482 'efl_ui_tab_pager_private.h',
482 'efl_ui_tab_bar_private.h', 483 'efl_ui_tab_bar_private.h',
483 'efl_ui_tab_page_private.h' 484 'efl_ui_tab_page_private.h',
485 'efl_ui_relative_layout_private.h'
484] 486]
485 487
486elementary_pub_headers = [ 488elementary_pub_headers = [
@@ -912,6 +914,7 @@ elementary_src = [
912 'efl_ui_homogeneous_model.c', 914 'efl_ui_homogeneous_model.c',
913 'efl_ui_exact_model.c', 915 'efl_ui_exact_model.c',
914 'efl_ui_average_model.c' 916 'efl_ui_average_model.c'
917 'efl_ui_relative_layout.c'
915] 918]
916 919
917elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl] 920elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl]
diff --git a/src/tests/elementary/efl_ui_suite.c b/src/tests/elementary/efl_ui_suite.c
index 5cc88df007..16f7ad3fe4 100644
--- a/src/tests/elementary/efl_ui_suite.c
+++ b/src/tests/elementary/efl_ui_suite.c
@@ -14,6 +14,7 @@ static const Efl_Test_Case etc[] = {
14 { "efl_ui_focus_sub", efl_ui_test_focus_sub}, 14 { "efl_ui_focus_sub", efl_ui_test_focus_sub},
15 { "efl_ui_box", efl_ui_test_box}, 15 { "efl_ui_box", efl_ui_test_box},
16 { "efl_ui_grid", efl_ui_test_grid}, 16 { "efl_ui_grid", efl_ui_test_grid},
17 { "efl_ui_relative_layout", efl_ui_test_relative_layout},
17 { "efl_ui_image", efl_ui_test_image}, 18 { "efl_ui_image", efl_ui_test_image},
18 { "efl_ui_image_zoomable", efl_ui_test_image_zoomable}, 19 { "efl_ui_image_zoomable", efl_ui_test_image_zoomable},
19 { "efl_ui_layout", efl_ui_test_layout}, 20 { "efl_ui_layout", efl_ui_test_layout},
diff --git a/src/tests/elementary/efl_ui_suite.h b/src/tests/elementary/efl_ui_suite.h
index b65cbe5bfb..c337323823 100644
--- a/src/tests/elementary/efl_ui_suite.h
+++ b/src/tests/elementary/efl_ui_suite.h
@@ -21,6 +21,7 @@
21 21
22void efl_ui_test_box(TCase *tc); 22void efl_ui_test_box(TCase *tc);
23void efl_ui_test_grid(TCase *tc); 23void efl_ui_test_grid(TCase *tc);
24void efl_ui_test_relative_layout(TCase *tc);
24void efl_ui_test_atspi(TCase *tc); 25void efl_ui_test_atspi(TCase *tc);
25void efl_ui_test_image_zoomable(TCase *tc); 26void efl_ui_test_image_zoomable(TCase *tc);
26void efl_ui_test_layout(TCase *tc); 27void efl_ui_test_layout(TCase *tc);
diff --git a/src/tests/elementary/efl_ui_test_relative_layout.c b/src/tests/elementary/efl_ui_test_relative_layout.c
new file mode 100644
index 0000000000..0471154338
--- /dev/null
+++ b/src/tests/elementary/efl_ui_test_relative_layout.c
@@ -0,0 +1,300 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Elementary.h>
6#include "elm_suite.h"
7
8#define COORD_EQ(a, b) (!!(abs(a - b) < 2))
9#define GEOMETRY_EQ(a, b) (COORD_EQ(a.x, b.x) && COORD_EQ(a.y, b.y) && \
10 COORD_EQ(a.w, b.w) && COORD_EQ(a.h, b.h))
11
12typedef struct {
13 Eina_Size2D max;
14 Eina_Size2D min;
15 double weightx;
16 double weighty;
17 double alignx;
18 double aligny;
19 int marginl;
20 int marginr;
21 int margint;
22 int marginb;
23 Efl_Gfx_Hint_Aspect mode;
24 Eina_Size2D aspect;
25 Eina_Bool fillx;
26 Eina_Bool filly;
27 Eina_Size2D layout_size;
28 Eina_Size2D layout_expected;
29 Eina_Rect expected;
30 char testname[1024];
31} Hint;
32
33static Hint hints[] = {
34 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(0, 0), 1, 1, 0.5, 0.5, 0, 0, 0, 0,
35 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
36 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
37 EINA_RECT(0, 0, 200, 200), "[0]" },
38 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.3, 0.5, 0, 0, 0, 0,
39 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
40 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
41 EINA_RECT(0, 0, 200, 200), "[1]" },
42 { EINA_SIZE2D(50, 150), EINA_SIZE2D(70, 70), 1, 1, 0.3, 0.7, 0, 0, 0, 0,
43 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
44 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
45 EINA_RECT((200 - 70) * 0.3, (200 - 150) * 0.7, 70, 150), "[2]" },
46 { EINA_SIZE2D(150, -1), EINA_SIZE2D(70, 70), 0, 0, 0.3, 0.7, 0, 0, 0, 0,
47 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_FALSE,
48 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
49 EINA_RECT((200 - 70) * 0.3, (200 - 70) * 0.7, 70, 70), "[3]" },
50 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 0, 0.3, 0.7, 0, 0, 0, 0,
51 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_TRUE,
52 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
53 EINA_RECT((200 - 70) * 0.3, (200 - 70) * 0.7, 70, 70), "[4]" },
54 { EINA_SIZE2D(150, 150), EINA_SIZE2D(70, 70), 1, 0, 0.3, 0.7, 0, 0, 0, 0,
55 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_TRUE,
56 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
57 EINA_RECT((200 - 70) * 0.3, (200 - 70) * 0.7, 70, 70), "[5]" },
58 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 0, 1, 0.3, 0.7, 0, 0, 0, 0,
59 EFL_GFX_HINT_ASPECT_BOTH, EINA_SIZE2D(1, 3), EINA_TRUE, EINA_FALSE,
60 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
61 EINA_RECT((200 - 70) * 0.3, -7, 70, 70 * 3), "[6]" },
62 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 0, 1, 0.3, 0.7, 0, 0, 0, 0,
63 EFL_GFX_HINT_ASPECT_BOTH, EINA_SIZE2D(1, 3), EINA_TRUE, EINA_FALSE,
64 EINA_SIZE2D(300, 300), EINA_SIZE2D(300, 300),
65 EINA_RECT((300 - 70) * 0.3, (300 - 70 * 3) * 0.7, 70, 70 * 3), "[7]" },
66 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 0, 0.3, 0.7, 0, 0, 0, 0,
67 EFL_GFX_HINT_ASPECT_BOTH, EINA_SIZE2D(1, 3), EINA_TRUE, EINA_FALSE,
68 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
69 EINA_RECT((200 - 70) * 0.3, -7, 70, 70 * 3), "[8]" },
70 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 0, 0.3, 0.7, 0, 0, 0, 0,
71 EFL_GFX_HINT_ASPECT_BOTH, EINA_SIZE2D(1, 3), EINA_TRUE, EINA_FALSE,
72 EINA_SIZE2D(300, 300), EINA_SIZE2D(300, 300),
73 EINA_RECT((300 - 70) * 0.3, (300 - 70 * 3) * 0.7, 70, 70 * 3), "[9]" },
74 { EINA_SIZE2D(-1, 150), EINA_SIZE2D(70, 70), 0, 1, 0.3, 0.7, 0, 0, 0, 0,
75 EFL_GFX_HINT_ASPECT_BOTH, EINA_SIZE2D(1, 3), EINA_TRUE, EINA_FALSE,
76 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
77 EINA_RECT((200 - 70) * 0.3, -7, 70, 70 * 3), "[10]" },
78 { EINA_SIZE2D(-1, 150), EINA_SIZE2D(70, 70), 0, 1, 0.3, 0.7, 0, 0, 0, 0,
79 EFL_GFX_HINT_ASPECT_BOTH, EINA_SIZE2D(1, 3), EINA_TRUE, EINA_FALSE,
80 EINA_SIZE2D(300, 300), EINA_SIZE2D(300, 300),
81 EINA_RECT((300 - 70) * 0.3, (300 - 70 * 3) * 0.7, 70, 70 * 3), "[11]" },
82 { EINA_SIZE2D(-1, 150), EINA_SIZE2D(70, 70), 1, 0, 0.3, 0.7, 0, 0, 0, 0,
83 EFL_GFX_HINT_ASPECT_BOTH, EINA_SIZE2D(1, 3), EINA_TRUE, EINA_FALSE,
84 EINA_SIZE2D(200, 200), EINA_SIZE2D(200, 200),
85 EINA_RECT((200 - 70) * 0.3, -7, 70, 70 * 3), "[12]" },
86 { EINA_SIZE2D(-1, 150), EINA_SIZE2D(70, 70), 1, 0, 0.3, 0.7, 0, 0, 0, 0,
87 EFL_GFX_HINT_ASPECT_BOTH, EINA_SIZE2D(1, 3), EINA_TRUE, EINA_FALSE,
88 EINA_SIZE2D(300, 300), EINA_SIZE2D(300, 300),
89 EINA_RECT((300 - 70) * 0.3, (300 - 70 * 3) * 0.7, 70, 70 * 3), "[13]" },
90};
91
92static Hint hints2[][2] = {
93 {
94 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.3, 0.7, 0, 0, 0, 0,
95 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_FALSE,
96 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
97 EINA_RECT((150 - 70) * 0.3, (150 - 70) * 0.7, 70, 70), "[1/1 weight btn]" },
98 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.8, 0.2, 0, 0, 0, 0,
99 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_FALSE,
100 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
101 EINA_RECT((150 - 70) * 0.8, (150 - 70) * 0.2 + 150, 70, 70), "[1/1 weight btn2]" }
102 },
103 {
104 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 0, 0.3, 0.7, 0, 0, 0, 0,
105 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_FALSE,
106 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
107 EINA_RECT((150 - 70) * 0.3, 0, 70, 70), "[0/1 weight btn]" },
108 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.8, 0.2, 0, 0, 0, 0,
109 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_FALSE,
110 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
111 EINA_RECT((150 - 70) * 0.8, (300 - 140) * 0.2 + 70, 70, 70), "[0/1 weight btn2]" }
112 },
113 {
114 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 0, 0.3, 0.7, 0, 0, 0, 0,
115 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_FALSE,
116 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
117 EINA_RECT((150 - 70) * 0.3, (300 - 140) * 0.7, 70, 70), "[0/0 weight btn]" },
118 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 0, 0.8, 0.2, 0, 0, 0, 0,
119 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_FALSE, EINA_FALSE,
120 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
121 EINA_RECT((150 - 70) * 0.8, (300 - 140) * 0.7 + 70, 70, 70), "[0/0 weight btn2]" }
122 },
123};
124
125static Hint hints3[][3] = {
126 {
127 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.3, 0.7, 0, 0, 0, 0,
128 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
129 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
130 EINA_RECT(0, 0, 150, 100), "[1/1/1 weight_l btn]" },
131 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 100), 1, 1, 0.8, 0.2, 0, 0, 0, 0,
132 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
133 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
134 EINA_RECT(0, 100, 150, 100), "[1/1/1 weight_l btn2]" },
135 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.8, 0.2, 0, 0, 0, 0,
136 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
137 EINA_SIZE2D(150, 300), EINA_SIZE2D(150, 300),
138 EINA_RECT(0, 100 + 100, 150, 100), "[1/1/1 weight_l btn2]" }
139 },
140 {
141 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.3, 0.7, 0, 0, 0, 0,
142 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
143 EINA_SIZE2D(150, 270), EINA_SIZE2D(150, 270),
144 EINA_RECT(0, 0, 150, 85), "[1/1/1 weight_m btn]" },
145 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 100), 1, 1, 0.8, 0.2, 0, 0, 0, 0,
146 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
147 EINA_SIZE2D(150, 270), EINA_SIZE2D(150, 270),
148 EINA_RECT(0, 85, 150, 100), "[1/1/1 weight_m btn2]" },
149 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.8, 0.2, 0, 0, 0, 0,
150 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
151 EINA_SIZE2D(150, 270), EINA_SIZE2D(150, 270),
152 EINA_RECT(0, 100 + 85, 150, 85), "[1/1/1 weight_m btn2]" }
153 },
154 {
155 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.3, 0.7, 0, 0, 0, 0,
156 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
157 EINA_SIZE2D(150, 200), EINA_SIZE2D(150, 200),
158 EINA_RECT(0, -28, 150, 70), "[1/1/1 weight_s btn]" },
159 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 100), 1, 1, 0.8, 0.2, 0, 0, 0, 0,
160 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
161 EINA_SIZE2D(150, 200), EINA_SIZE2D(150, 200),
162 EINA_RECT(0, 42, 150, 100), "[1/1/1 weight_s btn2]" },
163 { EINA_SIZE2D(-1, -1), EINA_SIZE2D(70, 70), 1, 1, 0.8, 0.2, 0, 0, 0, 0,
164 EFL_GFX_HINT_ASPECT_NONE, EINA_SIZE2D(0, 0), EINA_TRUE, EINA_TRUE,
165 EINA_SIZE2D(150, 200), EINA_SIZE2D(150, 200),
166 EINA_RECT(0, 142, 150, 70), "[1/1/1 weight_s btn2]" }
167 },
168};
169
170static Eo *win, *layout;
171
172static void
173btn_hint_set(Eo *btn, Hint *hint)
174{
175 efl_gfx_entity_size_set(layout, hint->layout_size);
176 efl_gfx_hint_size_max_set(btn, hint->max);
177 efl_gfx_hint_size_min_set(btn, hint->min);
178 efl_gfx_hint_margin_set(btn, hint->marginl, hint->marginr, hint->margint,
179 hint->marginb);
180 efl_gfx_hint_weight_set(btn, hint->weightx, hint->weighty);
181 efl_gfx_hint_align_set(btn, hint->alignx, hint->aligny);
182 efl_gfx_hint_fill_set(btn, hint->fillx, hint->filly);
183 efl_gfx_hint_aspect_set(btn, hint->mode, hint->aspect);
184 efl_canvas_group_calculate(layout);
185}
186
187static void
188btn_geom_assert(Hint *hint, Eina_Rect btn_geom)
189{
190 Eina_Size2D layout_size, layout_min;
191
192 layout_size = efl_gfx_entity_size_get(layout);
193 layout_min = efl_gfx_hint_size_min_get(layout);
194 layout_size.w = layout_size.w > layout_min.w ? layout_size.w : layout_min.w;
195 layout_size.h = layout_size.h > layout_min.h ? layout_size.h : layout_min.h;
196
197 ck_assert_msg(GEOMETRY_EQ(btn_geom, hint->expected),
198 "Case %s failed... button geometry: (%d, %d, %d, %d) expected geometry: (%d, %d, %d, %d)",
199 hint->testname, btn_geom.x, btn_geom.y, btn_geom.w, btn_geom.h,
200 hint->expected.x, hint->expected.y, hint->expected.w, hint->expected.h);
201 ck_assert_msg(COORD_EQ(layout_size.w, hint->layout_expected.w) &&
202 COORD_EQ(layout_size.h, hint->layout_expected.h),
203 "Case %s failed... layout size: (%d, %d) expected size: (%d, %d)",
204 hint->testname, layout_size.w, layout_size.h,
205 hint->layout_expected.w, hint->layout_expected.h);
206}
207
208static void
209layout_setup()
210{
211 win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
212 efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC));
213
214 layout = efl_add(EFL_UI_RELATIVE_LAYOUT_CLASS, win,
215 efl_gfx_entity_size_set(efl_added, EINA_SIZE2D(200, 200)));
216
217 efl_gfx_entity_size_set(win, EINA_SIZE2D(200, 200));
218}
219
220static void
221layout_teardown()
222{
223 if (win)
224 {
225 efl_del(win);
226 win = NULL;
227 }
228}
229
230EFL_START_TEST (efl_ui_relative_layout_class_check)
231{
232 const char *class;
233
234 class = efl_class_name_get(layout);
235
236 ck_assert(class != NULL);
237 ck_assert(!strcmp(class, "Efl.Ui.Relative_Layout"));
238}
239EFL_END_TEST
240
241EFL_START_TEST (efl_ui_relative_layout_layout_update)
242{
243 int i, max_index = (sizeof(hints) / sizeof(Hint));
244
245 Eo *btn = efl_add(EFL_UI_BUTTON_CLASS, layout,
246 efl_ui_relative_layout_relation_left_set(layout, efl_added, NULL, 0.0));
247
248 for (i = 0; i < max_index; i++)
249 {
250 btn_hint_set(btn, &hints[i]);
251 btn_geom_assert(&hints[i], efl_gfx_entity_geometry_get(btn));
252 }
253}
254EFL_END_TEST
255
256EFL_START_TEST (efl_ui_relative_layout_layout_update_chain)
257{
258 int i, max_index2, max_index3;
259 Eo *btn, *btn2, *btn3;
260
261 btn = efl_add(EFL_UI_BUTTON_CLASS, layout);
262 btn2 = efl_add(EFL_UI_BUTTON_CLASS, layout);
263
264 max_index2 = ((sizeof(hints2) / sizeof(Hint)) / 2);
265 max_index3 = ((sizeof(hints3) / sizeof(Hint)) / 3);
266
267 efl_ui_relative_layout_relation_bottom_set(layout, btn, btn2, 0.0);
268 efl_ui_relative_layout_relation_top_set(layout, btn2, btn, 1.0);
269
270 for (i = 0; i < max_index2; i++)
271 {
272 btn_hint_set(btn, &hints2[i][0]);
273 btn_hint_set(btn2, &hints2[i][1]);
274 btn_geom_assert(&hints2[i][0], efl_gfx_entity_geometry_get(btn));
275 btn_geom_assert(&hints2[i][1], efl_gfx_entity_geometry_get(btn2));
276 }
277
278 btn3 = efl_add(EFL_UI_BUTTON_CLASS, layout);
279 efl_ui_relative_layout_relation_bottom_set(layout, btn2, btn3, 0.0);
280 efl_ui_relative_layout_relation_top_set(layout, btn3, btn2, 1.0);
281
282 for (i = 0; i < max_index3; i++)
283 {
284 btn_hint_set(btn, &hints3[i][0]);
285 btn_hint_set(btn2, &hints3[i][1]);
286 btn_hint_set(btn3, &hints3[i][2]);
287 btn_geom_assert(&hints3[i][0], efl_gfx_entity_geometry_get(btn));
288 btn_geom_assert(&hints3[i][1], efl_gfx_entity_geometry_get(btn2));
289 btn_geom_assert(&hints3[i][2], efl_gfx_entity_geometry_get(btn3));
290 }
291}
292EFL_END_TEST
293
294void efl_ui_test_relative_layout(TCase *tc)
295{
296 tcase_add_checked_fixture(tc, layout_setup, layout_teardown);
297 tcase_add_test(tc, efl_ui_relative_layout_class_check);
298 tcase_add_test(tc, efl_ui_relative_layout_layout_update);
299 tcase_add_test(tc, efl_ui_relative_layout_layout_update_chain);
300}
diff --git a/src/tests/elementary/meson.build b/src/tests/elementary/meson.build
index 091d1540ef..f9e6a0eec2 100644
--- a/src/tests/elementary/meson.build
+++ b/src/tests/elementary/meson.build
@@ -124,6 +124,7 @@ efl_ui_suite_src = [
124 'efl_ui_test_focus_sub.c', 124 'efl_ui_test_focus_sub.c',
125 'efl_ui_test_box.c', 125 'efl_ui_test_box.c',
126 'efl_ui_test_grid.c', 126 'efl_ui_test_grid.c',
127 'efl_ui_test_relative_layout.c',
127 'efl_ui_test_image.c', 128 'efl_ui_test_image.c',
128 'efl_ui_test_image_zoomable.c', 129 'efl_ui_test_image_zoomable.c',
129 'efl_ui_test_layout.c', 130 'efl_ui_test_layout.c',