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
This commit is contained in:
parent
a5e183ad5d
commit
aef19e9017
|
@ -347,6 +347,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 \
|
||||
|
@ -816,6 +817,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 \
|
||||
|
@ -1630,6 +1632,7 @@ tests_elementary_efl_ui_suite_SOURCES = \
|
|||
tests/elementary/efl_ui_test_image.c \
|
||||
tests/elementary/efl_ui_test_image_zoomable.c \
|
||||
tests/elementary/efl_ui_test_layout.c \
|
||||
tests/elementary/efl_ui_test_widget.c \
|
||||
tests/elementary/efl_ui_suite.h \
|
||||
tests/elementary/efl_ui_model.c
|
||||
|
||||
|
|
|
@ -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_base.eo.h>
|
||||
# include <efl_ui_layout.eo.h>
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef EFL_UI_WIDGET_COMMON_H
|
||||
#define EFL_UI_WIDGET_COMMON_H
|
||||
|
||||
/**
|
||||
* @brief Get an iterator over all subelements located at obj.
|
||||
*
|
||||
* This iterator contains also the canvas objects which are part of the widgets,
|
||||
* be aware that the construction of this tree is internal and might change heavily
|
||||
* inbetween versions.
|
||||
*
|
||||
* @param obj The widget which is the root of the subtree.
|
||||
*
|
||||
* @return A iterator that contains subelement widgets and canvas objects of the root widget. Every contained object is a Efl.Gfx.Entity.
|
||||
*/
|
||||
EAPI Eina_Iterator* efl_ui_widget_tree_iterator(Efl_Ui_Widget *obj);
|
||||
|
||||
/**
|
||||
* @brief Get an iterator over all subelements located at obj.
|
||||
*
|
||||
* @param obj The widget which is the root of the subtree.
|
||||
*
|
||||
* @return A iterator that contains subelement widgets of the root widget. Every contained object is a Efl.Ui.Widget.
|
||||
*/
|
||||
EAPI Eina_Iterator* efl_ui_widget_tree_widget_iterator(Efl_Ui_Widget *obj);
|
||||
|
||||
/**
|
||||
* @brief Get an iterator that contains all parents of the passed object.
|
||||
*
|
||||
* @param obj The object to fetch the parents from.
|
||||
*
|
||||
* @return A iterator that contains all parents of the object. Every contained object is a Efl.Ui.Widget.
|
||||
*/
|
||||
EAPI Eina_Iterator* efl_ui_widget_parent_iterator(Efl_Ui_Widget *obj);
|
||||
|
||||
#endif
|
|
@ -837,6 +837,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',
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue