summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2019-02-27 13:29:08 -0500
committerMike Blumenkrantz <zmike@samsung.com>2019-02-27 13:29:08 -0500
commitaef19e9017c46d312f9c9c15b4f2bf0355e0961f (patch)
treee72f4645d2aef6538ecaf12a0aec5b8c0109ab18
parenta5e183ad5d1c4495c2149341b4a6e7c086b26e00 (diff)
efl_ui_widget: introduce a new API
Summary: this new API can be used to get a easy to use iterator, to iterate through all the children of a specific widget. ref T7553 Reviewers: stefan_schmidt, zmike, cedric, segfaultxavi Reviewed By: segfaultxavi Subscribers: woohyun, cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7553 Differential Revision: https://phab.enlightenment.org/D8014
-rw-r--r--src/Makefile_Elementary.am3
-rw-r--r--src/lib/elementary/Efl_Ui.h2
-rw-r--r--src/lib/elementary/efl_ui_widget_common.c173
-rw-r--r--src/lib/elementary/efl_ui_widget_common.h35
-rw-r--r--src/lib/elementary/meson.build1
-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_widget.c182
-rw-r--r--src/tests/elementary/meson.build1
9 files changed, 399 insertions, 0 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index 43a3d64edb..c020b343d4 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -347,6 +347,7 @@ includesunstable_HEADERS = \
347 lib/elementary/elm_interface_scrollable.h \ 347 lib/elementary/elm_interface_scrollable.h \
348 lib/elementary/elm_interfaces.h \ 348 lib/elementary/elm_interfaces.h \
349 lib/elementary/elm_widget.h \ 349 lib/elementary/elm_widget.h \
350 lib/elementary/efl_ui_widget_common.h \
350 lib/elementary/elm_widget_actionslider.h \ 351 lib/elementary/elm_widget_actionslider.h \
351 lib/elementary/elm_widget_box.h \ 352 lib/elementary/elm_widget_box.h \
352 lib/elementary/elm_widget_bubble.h \ 353 lib/elementary/elm_widget_bubble.h \
@@ -816,6 +817,7 @@ lib_elementary_libelementary_la_SOURCES = \
816 lib/elementary/elm_view_form.c \ 817 lib/elementary/elm_view_form.c \
817 lib/elementary/elm_web2.c \ 818 lib/elementary/elm_web2.c \
818 lib/elementary/efl_ui_widget.c \ 819 lib/elementary/efl_ui_widget.c \
820 lib/elementary/efl_ui_widget_common.c \
819 lib/elementary/efl_ui_win.c \ 821 lib/elementary/efl_ui_win.c \
820 lib/elementary/efl_ui_win_inlined.c \ 822 lib/elementary/efl_ui_win_inlined.c \
821 lib/elementary/efl_ui_win_socket.c \ 823 lib/elementary/efl_ui_win_socket.c \
@@ -1630,6 +1632,7 @@ tests_elementary_efl_ui_suite_SOURCES = \
1630 tests/elementary/efl_ui_test_image.c \ 1632 tests/elementary/efl_ui_test_image.c \
1631 tests/elementary/efl_ui_test_image_zoomable.c \ 1633 tests/elementary/efl_ui_test_image_zoomable.c \
1632 tests/elementary/efl_ui_test_layout.c \ 1634 tests/elementary/efl_ui_test_layout.c \
1635 tests/elementary/efl_ui_test_widget.c \
1633 tests/elementary/efl_ui_suite.h \ 1636 tests/elementary/efl_ui_suite.h \
1634 tests/elementary/efl_ui_model.c 1637 tests/elementary/efl_ui_model.c
1635 1638
diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h
index 33cc92efcb..bca10e3455 100644
--- a/src/lib/elementary/Efl_Ui.h
+++ b/src/lib/elementary/Efl_Ui.h
@@ -170,6 +170,8 @@ EAPI void efl_ui_focus_relation_free(Efl_Ui_Focus_Relations *rel);
170 170
171# include <efl_ui_theme.eo.h> 171# include <efl_ui_theme.eo.h>
172# include <efl_config_global.eo.h> 172# include <efl_config_global.eo.h>
173# include <efl_ui_widget.eo.h>
174# include <efl_ui_widget_common.h>
173# include <efl_ui_widget_part.eo.h> 175# include <efl_ui_widget_part.eo.h>
174# include <efl_ui_layout_base.eo.h> 176# include <efl_ui_layout_base.eo.h>
175# include <efl_ui_layout.eo.h> 177# include <efl_ui_layout.eo.h>
diff --git a/src/lib/elementary/efl_ui_widget_common.c b/src/lib/elementary/efl_ui_widget_common.c
new file mode 100644
index 0000000000..020848887b
--- /dev/null
+++ b/src/lib/elementary/efl_ui_widget_common.c
@@ -0,0 +1,173 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#define EFL_ACCESS_OBJECT_PROTECTED
6#define EFL_ACCESS_COMPONENT_PROTECTED
7#define ELM_WIDGET_PROTECTED
8#define ELM_WIDGET_ITEM_PROTECTED
9#define EFL_INPUT_EVENT_PROTECTED
10#define EFL_UI_L10N_PROTECTED
11#define EFL_UI_FOCUS_OBJECT_PROTECTED
12#define EFL_UI_WIDGET_PART_BG_PROTECTED
13#define EFL_PART_PROTECTED
14
15#include <Elementary.h>
16
17#include "elm_priv.h"
18#include "elm_widget_container.h"
19#include "elm_interface_scrollable.h"
20#include "elm_part_helper.h"
21#include "elm_widget_combobox.h"
22
23typedef struct {
24 Eina_Iterator iterator;
25 Efl_Ui_Widget *origin; //where we started
26 Efl_Ui_Widget *current; // the current widget where the iterator is
27} Widget_Iterator;
28
29static Widget_Iterator*
30iter_init(Efl_Ui_Widget *origin)
31{
32 Widget_Iterator *it;
33
34 it = calloc(1, sizeof(Widget_Iterator));
35
36 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
37
38 it->origin = origin;
39 it->iterator.version = EINA_ITERATOR_VERSION;
40 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(NULL);
41 it->iterator.free = FUNC_ITERATOR_FREE(free);
42
43 return it;
44}
45
46static Efl_Ui_Widget*
47_fetch_parent_widget(Efl_Gfx_Entity* o)
48{
49 Efl_Ui_Widget *parent;
50
51 if (efl_isa(o, EFL_UI_WIDGET_CLASS))
52 parent = efl_ui_widget_parent_get(o);
53 else
54 parent = evas_object_data_get(o, "elm-parent");
55
56 return parent;
57}
58
59static Efl_Ui_Widget*
60_next_widget(Efl_Gfx_Entity* o)
61{
62 Efl_Ui_Widget *parent;
63 Eina_List *rel;
64
65 parent = _fetch_parent_widget(o);
66 ELM_WIDGET_DATA_GET_OR_RETURN(parent, pd, NULL);
67 rel = eina_list_data_find_list(pd->subobjs, o);
68
69 return eina_list_data_get(eina_list_next(rel));
70}
71
72static Eina_Bool
73_widget_next(Widget_Iterator *it, void **data)
74{
75 Efl_Ui_Widget *runner;
76 Efl_Ui_Widget_Data *pd = NULL;
77
78 //Init case
79 if (!it->current)
80 {
81 it->current = it->origin;
82 goto deliver;
83 }
84
85 if (efl_isa(it->current, EFL_UI_WIDGET_CLASS))
86 {
87 pd = efl_data_scope_safe_get(it->current, EFL_UI_WIDGET_CLASS);
88 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EINA_FALSE);
89 }
90
91 //If there is a child, go there
92 if (pd && pd->subobjs)
93 {
94 it->current = eina_list_data_get(pd->subobjs);
95 goto deliver;
96 }
97
98 //If there is no child, then iterate up the parents until we find a widget with a next widget
99 runner = it->current;
100 do
101 {
102 Efl_Ui_Widget *tmp = _next_widget(runner);
103
104 if (tmp)
105 {
106 it->current = tmp;
107 goto deliver;
108 }
109
110 runner = _fetch_parent_widget(runner);
111 }
112 while(runner && runner != it->origin);
113
114 //Reaching this point here means that there is no widget left, as there is no more parent we can explore
115 it->current = NULL;
116
117deliver:
118 *data = (void*)it->current;
119 return !!it->current;
120}
121
122EAPI Eina_Iterator*
123efl_ui_widget_tree_iterator(Efl_Ui_Widget *obj)
124{
125 ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
126 Widget_Iterator *it = iter_init(obj);
127 it->iterator.next = FUNC_ITERATOR_NEXT(_widget_next);
128
129 return &it->iterator;
130}
131
132static Eina_Bool
133_only_widget(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
134{
135 return efl_isa(data, EFL_UI_WIDGET_CLASS);
136}
137
138EAPI Eina_Iterator*
139efl_ui_widget_tree_widget_iterator(Efl_Ui_Widget *obj)
140{
141 Eina_Iterator *tree_iterator = efl_ui_widget_tree_iterator(obj);
142 ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
143
144 return eina_iterator_filter_new(tree_iterator, _only_widget, NULL, NULL);
145}
146
147static Eina_Bool
148_parent_next(Widget_Iterator *it, void **data)
149{
150 if (!it->current)
151 {
152 *data = it->origin;
153 it->current = *data;
154 }
155 else
156 {
157 Efl_Ui_Widget *parent = efl_ui_widget_parent_get(it->current);
158
159 *data = parent;
160 it->current = parent;
161 }
162
163 return !!*data;
164}
165
166EAPI Eina_Iterator*
167efl_ui_widget_parent_iterator(Efl_Ui_Widget *obj)
168{
169 ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
170 Widget_Iterator *it = iter_init(obj);
171 it->iterator.next = FUNC_ITERATOR_NEXT(_parent_next);
172 return &it->iterator;
173}
diff --git a/src/lib/elementary/efl_ui_widget_common.h b/src/lib/elementary/efl_ui_widget_common.h
new file mode 100644
index 0000000000..0e538cbed5
--- /dev/null
+++ b/src/lib/elementary/efl_ui_widget_common.h
@@ -0,0 +1,35 @@
1#ifndef EFL_UI_WIDGET_COMMON_H
2#define EFL_UI_WIDGET_COMMON_H
3
4/**
5 * @brief Get an iterator over all subelements located at obj.
6 *
7 * This iterator contains also the canvas objects which are part of the widgets,
8 * be aware that the construction of this tree is internal and might change heavily
9 * inbetween versions.
10 *
11 * @param obj The widget which is the root of the subtree.
12 *
13 * @return A iterator that contains subelement widgets and canvas objects of the root widget. Every contained object is a Efl.Gfx.Entity.
14 */
15EAPI Eina_Iterator* efl_ui_widget_tree_iterator(Efl_Ui_Widget *obj);
16
17/**
18 * @brief Get an iterator over all subelements located at obj.
19 *
20 * @param obj The widget which is the root of the subtree.
21 *
22 * @return A iterator that contains subelement widgets of the root widget. Every contained object is a Efl.Ui.Widget.
23 */
24EAPI Eina_Iterator* efl_ui_widget_tree_widget_iterator(Efl_Ui_Widget *obj);
25
26/**
27 * @brief Get an iterator that contains all parents of the passed object.
28 *
29 * @param obj The object to fetch the parents from.
30 *
31 * @return A iterator that contains all parents of the object. Every contained object is a Efl.Ui.Widget.
32 */
33EAPI Eina_Iterator* efl_ui_widget_parent_iterator(Efl_Ui_Widget *obj);
34
35#endif
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index 9c7cc1ed90..38ee28fe9a 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -837,6 +837,7 @@ elementary_src = [
837 'elm_view_form.c', 837 'elm_view_form.c',
838 'elm_web2.c', 838 'elm_web2.c',
839 'efl_ui_widget.c', 839 'efl_ui_widget.c',
840 'efl_ui_widget_common.c',
840 'efl_ui_win.c', 841 'efl_ui_win.c',
841 'efl_ui_win_inlined.c', 842 'efl_ui_win_inlined.c',
842 'efl_ui_win_socket.c', 843 'efl_ui_win_socket.c',
diff --git a/src/tests/elementary/efl_ui_suite.c b/src/tests/elementary/efl_ui_suite.c
index 16f7ad3fe4..a0aa9022f8 100644
--- a/src/tests/elementary/efl_ui_suite.c
+++ b/src/tests/elementary/efl_ui_suite.c
@@ -19,6 +19,7 @@ static const Efl_Test_Case etc[] = {
19 { "efl_ui_image_zoomable", efl_ui_test_image_zoomable}, 19 { "efl_ui_image_zoomable", efl_ui_test_image_zoomable},
20 { "efl_ui_layout", efl_ui_test_layout}, 20 { "efl_ui_layout", efl_ui_test_layout},
21 { "Efl_Ui_Model", efl_ui_model }, 21 { "Efl_Ui_Model", efl_ui_model },
22 { "efl_ui_widget", efl_ui_test_widget },
22 { NULL, NULL } 23 { NULL, NULL }
23}; 24};
24 25
diff --git a/src/tests/elementary/efl_ui_suite.h b/src/tests/elementary/efl_ui_suite.h
index c337323823..e0c9089c22 100644
--- a/src/tests/elementary/efl_ui_suite.h
+++ b/src/tests/elementary/efl_ui_suite.h
@@ -31,6 +31,7 @@ void efl_ui_test_focus(TCase *tc);
31void efl_ui_test_focus_sub(TCase *tc); 31void efl_ui_test_focus_sub(TCase *tc);
32 32
33void efl_ui_model(TCase *tc); 33void efl_ui_model(TCase *tc);
34void efl_ui_test_widget(TCase *tc);
34 35
35void loop_timer_interval_set(Eo *obj, double in); 36void loop_timer_interval_set(Eo *obj, double in);
36 37
diff --git a/src/tests/elementary/efl_ui_test_widget.c b/src/tests/elementary/efl_ui_test_widget.c
new file mode 100644
index 0000000000..89a429b406
--- /dev/null
+++ b/src/tests/elementary/efl_ui_test_widget.c
@@ -0,0 +1,182 @@
1//#define EFL_NOLEGACY_API_SUPPORT
2#ifdef HAVE_CONFIG_H
3# include "elementary_config.h"
4#endif
5#include <Elementary.h>
6#include "elm_widget.h"
7#include <Efl_Ui.h>
8#include "efl_ui_suite.h"
9
10typedef struct {
11 Efl_Ui_Widget *btn1, *btn2;
12 Efl_Ui_Widget *box;
13 Efl_Ui_Widget *win;
14 Efl_Ui_Widget *ic;
15} State;
16
17static void
18_small_ui(State *s)
19{
20 s->win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
21 efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
22 efl_text_set(efl_added, "Hello World"));
23
24 s->ic = efl_add(EFL_UI_IMAGE_CLASS, s->win,
25 efl_ui_win_icon_object_set(s->win, efl_added));
26
27 s->box = efl_add(EFL_UI_BOX_CLASS, s->win,
28 efl_content_set(s->win, efl_added));
29
30 s->btn1 = efl_add(EFL_UI_BUTTON_CLASS, s->box,
31 efl_text_set(efl_added, "Quit1"),
32 efl_pack(s->box, efl_added));
33
34 s->btn2 = efl_add(EFL_UI_BUTTON_CLASS, s->box,
35 efl_text_set(efl_added, "Quit"),
36 efl_pack(s->box, efl_added));
37
38}
39
40EFL_START_TEST(efl_ui_test_widget_parent_iterator)
41{
42 Eina_Iterator *it;
43 Efl_Ui_Widget *o;
44 Eina_Array *a;
45 State s;
46
47 a = eina_array_new(10);
48 _small_ui(&s);
49 eina_array_push(a, s.win);
50 eina_array_push(a, s.box);
51 eina_array_push(a, s.btn1);
52
53 it = efl_ui_widget_parent_iterator(s.btn1);
54 EINA_ITERATOR_FOREACH(it, o)
55 {
56 ck_assert_ptr_eq(eina_array_pop(a), o);
57 }
58 eina_iterator_free(it);
59 ck_assert_int_eq(eina_array_count(a), 0);
60}
61EFL_END_TEST
62
63EFL_START_TEST(efl_ui_test_widget_widget_iterator)
64{
65 Eina_Iterator *it;
66 Efl_Ui_Widget *o;
67 Eina_Array *a;
68 State s;
69
70 a = eina_array_new(10);
71 _small_ui(&s);
72 eina_array_push(a, s.btn2);
73 eina_array_push(a, s.btn1);
74 eina_array_push(a, s.box);
75 eina_array_push(a, s.ic); //Hack arround the icon of the window
76 eina_array_push(a, s.win);
77
78 it = efl_ui_widget_tree_widget_iterator(s.win);
79 EINA_ITERATOR_FOREACH(it, o)
80 {
81 Eo *c = eina_array_pop(a);
82 ck_assert_ptr_eq(c, o);
83 }
84 eina_iterator_free(it);
85 ck_assert_int_eq(eina_array_count(a), 0);
86}
87EFL_END_TEST
88
89static Evas_Object*
90resize_object(Efl_Canvas_Object *o)
91{
92 Efl_Ui_Widget_Data *pd = efl_data_scope_safe_get(o, EFL_UI_WIDGET_CLASS);
93
94 return eina_list_data_get(pd->subobjs);
95}
96
97EFL_START_TEST(efl_ui_test_widget_widget_sub_iterator)
98{
99 Eina_Iterator *it;
100 Efl_Ui_Widget *o;
101 Eina_Array *a;
102 State s;
103
104 a = eina_array_new(10);
105 _small_ui(&s);
106 eina_array_push(a, s.btn2);
107 eina_array_push(a, s.btn1);
108 eina_array_push(a, s.box);
109
110 it = efl_ui_widget_tree_widget_iterator(s.box);
111 EINA_ITERATOR_FOREACH(it, o)
112 {
113 ck_assert_ptr_eq(eina_array_pop(a), o);
114 }
115 eina_iterator_free(it);
116 ck_assert_int_eq(eina_array_count(a), 0);
117}
118EFL_END_TEST
119
120EFL_START_TEST(efl_ui_test_widget_iterator)
121{
122 Eina_Iterator *it;
123 Efl_Ui_Widget *o;
124 Eina_Array *a;
125 State s;
126
127 a = eina_array_new(10);
128 _small_ui(&s);
129 eina_array_push(a, resize_object(s.btn2));
130 eina_array_push(a, s.btn2);
131 eina_array_push(a, resize_object(s.btn1));
132 eina_array_push(a, s.btn1);
133 eina_array_push(a, resize_object(s.box));
134 eina_array_push(a, s.box);
135 eina_array_push(a, resize_object(s.ic));
136 eina_array_push(a, s.ic);
137 eina_array_push(a, s.win);
138
139 it = efl_ui_widget_tree_iterator(s.win);
140 EINA_ITERATOR_FOREACH(it, o)
141 {
142 ck_assert_ptr_eq(eina_array_pop(a), o);
143 }
144 eina_iterator_free(it);
145 ck_assert_int_eq(eina_array_count(a), 0);
146}
147EFL_END_TEST
148
149EFL_START_TEST(efl_ui_test_widget_sub_iterator)
150{
151 Eina_Iterator *it;
152 Efl_Ui_Widget *o;
153 Eina_Array *a;
154 State s;
155
156 a = eina_array_new(10);
157 _small_ui(&s);
158 eina_array_push(a, resize_object(s.btn2));
159 eina_array_push(a, s.btn2);
160 eina_array_push(a, resize_object(s.btn1));
161 eina_array_push(a, s.btn1);
162 eina_array_push(a, resize_object(s.box));
163 eina_array_push(a, s.box);
164
165 it = efl_ui_widget_tree_iterator(s.box);
166 EINA_ITERATOR_FOREACH(it, o)
167 {
168 ck_assert_ptr_eq(eina_array_pop(a), o);
169 }
170 eina_iterator_free(it);
171 ck_assert_int_eq(eina_array_count(a), 0);
172}
173EFL_END_TEST
174
175void efl_ui_test_widget(TCase *tc)
176{
177 tcase_add_test(tc, efl_ui_test_widget_parent_iterator);
178 tcase_add_test(tc, efl_ui_test_widget_widget_iterator);
179 tcase_add_test(tc, efl_ui_test_widget_widget_sub_iterator);
180 tcase_add_test(tc, efl_ui_test_widget_iterator);
181 tcase_add_test(tc, efl_ui_test_widget_sub_iterator);
182}
diff --git a/src/tests/elementary/meson.build b/src/tests/elementary/meson.build
index f9e6a0eec2..77649a1d26 100644
--- a/src/tests/elementary/meson.build
+++ b/src/tests/elementary/meson.build
@@ -130,6 +130,7 @@ efl_ui_suite_src = [
130 'efl_ui_test_layout.c', 130 'efl_ui_test_layout.c',
131 'efl_ui_suite.h', 131 'efl_ui_suite.h',
132 'efl_ui_model.c', 132 'efl_ui_model.c',
133 'efl_ui_test_widget.c',
133] 134]
134 135
135efl_ui_suite = executable('efl_ui_suite', 136efl_ui_suite = executable('efl_ui_suite',