aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2019-02-24 10:35:28 +0100
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2019-02-24 12:43:45 +0100
commit39d6ebacf42dc21ab04cf13993288700efb8d454 (patch)
tree43da1b194ceddf035a3a41855fc26616e9991ca1
parentefl_ui_widget: remove focused_item (diff)
downloadefl-devs/bu5hm4n/widget-start.tar.gz
efl_ui_widget: introduce a new APIdevs/bu5hm4n/widget-start
this new API can be used to get a easy to use iterator, to iterate through all the children of a specific widget. ref https://phab.enlightenment.org/T7553
-rw-r--r--src/Makefile_Elementary.am2
-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.h19
-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, 382 insertions, 0 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index b6f8d17129..cf45524f8d 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -346,6 +346,7 @@ includesunstable_HEADERS = \
lib/elementary/elm_interface_scrollable.h \
lib/elementary/elm_interfaces.h \
lib/elementary/elm_widget.h \
+ lib/elementary/efl_ui_widget_common.h \
lib/elementary/elm_widget_actionslider.h \
lib/elementary/elm_widget_box.h \
lib/elementary/elm_widget_bubble.h \
@@ -815,6 +816,7 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/elm_view_form.c \
lib/elementary/elm_web2.c \
lib/elementary/efl_ui_widget.c \
+ lib/elementary/efl_ui_widget_common.c \
lib/elementary/efl_ui_win.c \
lib/elementary/efl_ui_win_inlined.c \
lib/elementary/efl_ui_win_socket.c \
diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h
index 515ee48c06..f5c3c1c346 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);
# include <efl_ui_theme.eo.h>
# include <efl_config_global.eo.h>
+# include <efl_ui_widget.eo.h>
+# include <efl_ui_widget_common.h>
# include <efl_ui_widget_part.eo.h>
# include <efl_ui_layout.eo.h>
# include <efl_ui_layout_part.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 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#define EFL_ACCESS_OBJECT_PROTECTED
+#define EFL_ACCESS_COMPONENT_PROTECTED
+#define ELM_WIDGET_PROTECTED
+#define ELM_WIDGET_ITEM_PROTECTED
+#define EFL_INPUT_EVENT_PROTECTED
+#define EFL_UI_L10N_PROTECTED
+#define EFL_UI_FOCUS_OBJECT_PROTECTED
+#define EFL_UI_WIDGET_PART_BG_PROTECTED
+#define EFL_PART_PROTECTED
+
+#include <Elementary.h>
+
+#include "elm_priv.h"
+#include "elm_widget_container.h"
+#include "elm_interface_scrollable.h"
+#include "elm_part_helper.h"
+#include "elm_widget_combobox.h"
+
+typedef struct {
+ Eina_Iterator iterator;
+ Efl_Ui_Widget *origin; //where we started
+ Efl_Ui_Widget *current; // the current widget where the iterator is
+} Widget_Iterator;
+
+static Widget_Iterator*
+iter_init(Efl_Ui_Widget *origin)
+{
+ Widget_Iterator *it;
+
+ it = calloc(1, sizeof(Widget_Iterator));
+
+ EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+
+ it->origin = origin;
+ it->iterator.version = EINA_ITERATOR_VERSION;
+ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(NULL);
+ it->iterator.free = FUNC_ITERATOR_FREE(free);
+
+ return it;
+}
+
+static Efl_Ui_Widget*
+_fetch_parent_widget(Efl_Gfx_Entity* o)
+{
+ Efl_Ui_Widget *parent;
+
+ if (efl_isa(o, EFL_UI_WIDGET_CLASS))
+ parent = efl_ui_widget_parent_get(o);
+ else
+ parent = evas_object_data_get(o, "elm-parent");
+
+ return parent;
+}
+
+static Efl_Ui_Widget*
+_next_widget(Efl_Gfx_Entity* o)
+{
+ Efl_Ui_Widget *parent;
+ Eina_List *rel;
+
+ parent = _fetch_parent_widget(o);
+ ELM_WIDGET_DATA_GET_OR_RETURN(parent, pd, NULL);
+ rel = eina_list_data_find_list(pd->subobjs, o);
+
+ return eina_list_data_get(eina_list_next(rel));
+}
+
+static Eina_Bool
+_widget_next(Widget_Iterator *it, void **data)
+{
+ Efl_Ui_Widget *runner;
+ Efl_Ui_Widget_Data *pd = NULL;
+
+ //Init case
+ if (!it->current)
+ {
+ it->current = it->origin;
+ goto deliver;
+ }
+
+ if (efl_isa(it->current, EFL_UI_WIDGET_CLASS))
+ {
+ pd = efl_data_scope_safe_get(it->current, EFL_UI_WIDGET_CLASS);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EINA_FALSE);
+ }
+
+ //If there is a child, go there
+ if (pd && pd->subobjs)
+ {
+ it->current = eina_list_data_get(pd->subobjs);
+ goto deliver;
+ }
+
+ //If there is no child, then iterate up the parents until we find a widget with a next widget
+ runner = it->current;
+ do
+ {
+ Efl_Ui_Widget *tmp = _next_widget(runner);
+
+ if (tmp)
+ {
+ it->current = tmp;
+ goto deliver;
+ }
+
+ runner = _fetch_parent_widget(runner);
+ }
+ while(runner && runner != it->origin);
+
+ //Reaching this point here means that there is no widget left, as there is no more parent we can explore
+ it->current = NULL;
+
+deliver:
+ *data = (void*)it->current;
+ return !!it->current;
+}
+
+EAPI Eina_Iterator*
+efl_ui_widget_tree_iterator(Efl_Ui_Widget *obj)
+{
+ ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
+ Widget_Iterator *it = iter_init(obj);
+ it->iterator.next = FUNC_ITERATOR_NEXT(_widget_next);
+
+ return &it->iterator;
+}
+
+static Eina_Bool
+_only_widget(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
+{
+ return efl_isa(data, EFL_UI_WIDGET_CLASS);
+}
+
+EAPI Eina_Iterator*
+efl_ui_widget_tree_widget_iterator(Efl_Ui_Widget *obj)
+{
+ Eina_Iterator *tree_iterator = efl_ui_widget_tree_iterator(obj);
+ ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
+
+ return eina_iterator_filter_new(tree_iterator, _only_widget, NULL, NULL);
+}
+
+static Eina_Bool
+_parent_next(Widget_Iterator *it, void **data)
+{
+ if (!it->current)
+ {
+ *data = it->origin;
+ it->current = *data;
+ }
+ else
+ {
+ Efl_Ui_Widget *parent = efl_ui_widget_parent_get(it->current);
+
+ *data = parent;
+ it->current = parent;
+ }
+
+ return !!*data;
+}
+
+EAPI Eina_Iterator*
+efl_ui_widget_parent_iterator(Efl_Ui_Widget *obj)
+{
+ ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
+ Widget_Iterator *it = iter_init(obj);
+ it->iterator.next = FUNC_ITERATOR_NEXT(_parent_next);
+ return &it->iterator;
+}
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..d5417e9fd5
--- /dev/null
+++ b/src/lib/elementary/efl_ui_widget_common.h
@@ -0,0 +1,19 @@
+#ifndef EFL_UI_WIDGET_COMMON_H
+#define EFL_UI_WIDGET_COMMON_H
+
+/**
+ *
+ */
+EAPI Eina_Iterator* efl_ui_widget_tree_iterator(Efl_Ui_Widget *obj);
+
+/**
+ *
+ */
+EAPI Eina_Iterator* efl_ui_widget_tree_widget_iterator(Efl_Ui_Widget *obj);
+
+/**
+ *
+ */
+EAPI Eina_Iterator* efl_ui_widget_parent_iterator(Efl_Ui_Widget *obj);
+
+#endif
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index 4363984615..cd85fa54a1 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -836,6 +836,7 @@ elementary_src = [
'elm_view_form.c',
'elm_web2.c',
'efl_ui_widget.c',
+ 'efl_ui_widget_common.c',
'efl_ui_win.c',
'efl_ui_win_inlined.c',
'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[] = {
{ "efl_ui_image_zoomable", efl_ui_test_image_zoomable},
{ "efl_ui_layout", efl_ui_test_layout},
{ "Efl_Ui_Model", efl_ui_model },
+ { "efl_ui_widget", efl_ui_test_widget },
{ NULL, NULL }
};
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);
void efl_ui_test_focus_sub(TCase *tc);
void efl_ui_model(TCase *tc);
+void efl_ui_test_widget(TCase *tc);
void loop_timer_interval_set(Eo *obj, double in);
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 @@
+//#define EFL_NOLEGACY_API_SUPPORT
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <Elementary.h>
+#include "elm_widget.h"
+#include <Efl_Ui.h>
+#include "efl_ui_suite.h"
+
+typedef struct {
+ Efl_Ui_Widget *btn1, *btn2;
+ Efl_Ui_Widget *box;
+ Efl_Ui_Widget *win;
+ Efl_Ui_Widget *ic;
+} State;
+
+static void
+_small_ui(State *s)
+{
+ s->win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
+ efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
+ efl_text_set(efl_added, "Hello World"));
+
+ s->ic = efl_add(EFL_UI_IMAGE_CLASS, s->win,
+ efl_ui_win_icon_object_set(s->win, efl_added));
+
+ s->box = efl_add(EFL_UI_BOX_CLASS, s->win,
+ efl_content_set(s->win, efl_added));
+
+ s->btn1 = efl_add(EFL_UI_BUTTON_CLASS, s->box,
+ efl_text_set(efl_added, "Quit1"),
+ efl_pack(s->box, efl_added));
+
+ s->btn2 = efl_add(EFL_UI_BUTTON_CLASS, s->box,
+ efl_text_set(efl_added, "Quit"),
+ efl_pack(s->box, efl_added));
+
+}
+
+EFL_START_TEST(efl_ui_test_widget_parent_iterator)
+{
+ Eina_Iterator *it;
+ Efl_Ui_Widget *o;
+ Eina_Array *a;
+ State s;
+
+ a = eina_array_new(10);
+ _small_ui(&s);
+ eina_array_push(a, s.win);
+ eina_array_push(a, s.box);
+ eina_array_push(a, s.btn1);
+
+ it = efl_ui_widget_parent_iterator(s.btn1);
+ EINA_ITERATOR_FOREACH(it, o)
+ {
+ ck_assert_ptr_eq(eina_array_pop(a), o);
+ }
+ eina_iterator_free(it);
+ ck_assert_int_eq(eina_array_count(a), 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(efl_ui_test_widget_widget_iterator)
+{
+ Eina_Iterator *it;
+ Efl_Ui_Widget *o;
+ Eina_Array *a;
+ State s;
+
+ a = eina_array_new(10);
+ _small_ui(&s);
+ eina_array_push(a, s.btn2);
+ eina_array_push(a, s.btn1);
+ eina_array_push(a, s.box);
+ eina_array_push(a, s.ic); //Hack arround the icon of the window
+ eina_array_push(a, s.win);
+
+ it = efl_ui_widget_tree_widget_iterator(s.win);
+ EINA_ITERATOR_FOREACH(it, o)
+ {
+ Eo *c = eina_array_pop(a);
+ ck_assert_ptr_eq(c, o);
+ }
+ eina_iterator_free(it);
+ ck_assert_int_eq(eina_array_count(a), 0);
+}
+EFL_END_TEST
+
+static Evas_Object*
+resize_object(Efl_Canvas_Object *o)
+{
+ Efl_Ui_Widget_Data *pd = efl_data_scope_safe_get(o, EFL_UI_WIDGET_CLASS);
+
+ return eina_list_data_get(pd->subobjs);
+}
+
+EFL_START_TEST(efl_ui_test_widget_widget_sub_iterator)
+{
+ Eina_Iterator *it;
+ Efl_Ui_Widget *o;
+ Eina_Array *a;
+ State s;
+
+ a = eina_array_new(10);
+ _small_ui(&s);
+ eina_array_push(a, s.btn2);
+ eina_array_push(a, s.btn1);
+ eina_array_push(a, s.box);
+
+ it = efl_ui_widget_tree_widget_iterator(s.box);
+ EINA_ITERATOR_FOREACH(it, o)
+ {
+ ck_assert_ptr_eq(eina_array_pop(a), o);
+ }
+ eina_iterator_free(it);
+ ck_assert_int_eq(eina_array_count(a), 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(efl_ui_test_widget_iterator)
+{
+ Eina_Iterator *it;
+ Efl_Ui_Widget *o;
+ Eina_Array *a;
+ State s;
+
+ a = eina_array_new(10);
+ _small_ui(&s);
+ eina_array_push(a, resize_object(s.btn2));
+ eina_array_push(a, s.btn2);
+ eina_array_push(a, resize_object(s.btn1));
+ eina_array_push(a, s.btn1);
+ eina_array_push(a, resize_object(s.box));
+ eina_array_push(a, s.box);
+ eina_array_push(a, resize_object(s.ic));
+ eina_array_push(a, s.ic);
+ eina_array_push(a, s.win);
+
+ it = efl_ui_widget_tree_iterator(s.win);
+ EINA_ITERATOR_FOREACH(it, o)
+ {
+ ck_assert_ptr_eq(eina_array_pop(a), o);
+ }
+ eina_iterator_free(it);
+ ck_assert_int_eq(eina_array_count(a), 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(efl_ui_test_widget_sub_iterator)
+{
+ Eina_Iterator *it;
+ Efl_Ui_Widget *o;
+ Eina_Array *a;
+ State s;
+
+ a = eina_array_new(10);
+ _small_ui(&s);
+ eina_array_push(a, resize_object(s.btn2));
+ eina_array_push(a, s.btn2);
+ eina_array_push(a, resize_object(s.btn1));
+ eina_array_push(a, s.btn1);
+ eina_array_push(a, resize_object(s.box));
+ eina_array_push(a, s.box);
+
+ it = efl_ui_widget_tree_iterator(s.box);
+ EINA_ITERATOR_FOREACH(it, o)
+ {
+ ck_assert_ptr_eq(eina_array_pop(a), o);
+ }
+ eina_iterator_free(it);
+ ck_assert_int_eq(eina_array_count(a), 0);
+}
+EFL_END_TEST
+
+void efl_ui_test_widget(TCase *tc)
+{
+ tcase_add_test(tc, efl_ui_test_widget_parent_iterator);
+ tcase_add_test(tc, efl_ui_test_widget_widget_iterator);
+ tcase_add_test(tc, efl_ui_test_widget_widget_sub_iterator);
+ tcase_add_test(tc, efl_ui_test_widget_iterator);
+ tcase_add_test(tc, efl_ui_test_widget_sub_iterator);
+}
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 = [
'efl_ui_test_layout.c',
'efl_ui_suite.h',
'efl_ui_model.c',
+ 'efl_ui_test_widget.c',
]
efl_ui_suite = executable('efl_ui_suite',