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_pan_eo.h"
21 #include "elm_part_helper.h"
22 #include "elm_widget_combobox.h"
23 
24 typedef struct {
25    Eina_Iterator iterator;
26    Efl_Ui_Widget *origin; //where we started
27    Efl_Ui_Widget *current; // the current widget where the iterator is
28 } Widget_Iterator;
29 
30 static Widget_Iterator*
iter_init(Efl_Ui_Widget * origin)31 iter_init(Efl_Ui_Widget *origin)
32 {
33    Widget_Iterator *it;
34 
35    it = calloc(1, sizeof(Widget_Iterator));
36 
37    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
38 
39    it->origin = origin;
40    it->iterator.version = EINA_ITERATOR_VERSION;
41    it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(NULL);
42    it->iterator.free = FUNC_ITERATOR_FREE(free);
43 
44    return it;
45 }
46 
47 static Efl_Ui_Widget*
_fetch_parent_widget(Efl_Gfx_Entity * o)48 _fetch_parent_widget(Efl_Gfx_Entity* o)
49 {
50    Efl_Ui_Widget *parent;
51 
52    if (efl_isa(o, EFL_UI_WIDGET_CLASS))
53      parent = efl_ui_widget_parent_get(o);
54    else
55      parent = evas_object_data_get(o, "elm-parent");
56 
57    return parent;
58 }
59 
60 static Efl_Ui_Widget*
_next_widget(Efl_Gfx_Entity * o)61 _next_widget(Efl_Gfx_Entity* o)
62 {
63    Efl_Ui_Widget *parent;
64 
65    parent = _fetch_parent_widget(o);
66    ELM_WIDGET_DATA_GET_OR_RETURN(parent, pd, NULL);
67    unsigned int id;
68    if (eina_array_find(pd->children, o, &id) && id + 1 < eina_array_count(pd->children))
69      return eina_array_data_get(pd->children, id + 1);
70    else
71      return NULL;
72 }
73 
74 static Eina_Bool
_widget_next(Widget_Iterator * it,void ** data)75 _widget_next(Widget_Iterator *it, void **data)
76 {
77    Efl_Ui_Widget *runner;
78    Efl_Ui_Widget_Data *pd = NULL;
79 
80    //Init case
81    if (!it->current)
82      {
83         it->current = it->origin;
84         goto deliver;
85      }
86 
87    if (efl_isa(it->current, EFL_UI_WIDGET_CLASS))
88      {
89         pd = efl_data_scope_safe_get(it->current, EFL_UI_WIDGET_CLASS);
90         EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EINA_FALSE);
91      }
92 
93    //If there is a child, go there
94    if (pd && eina_array_count(pd->children))
95      {
96         it->current = eina_array_data_get(pd->children, 0);
97         goto deliver;
98      }
99 
100    //If there is no child, then iterate up the parents until we find a widget with a next widget
101    runner = it->current;
102    do
103      {
104         Efl_Ui_Widget *tmp = _next_widget(runner);
105 
106         if (tmp)
107           {
108              it->current = tmp;
109              goto deliver;
110           }
111 
112         runner = _fetch_parent_widget(runner);
113      }
114    while(runner && runner != it->origin);
115 
116    //Reaching this point here means that there is no widget left, as there is no more parent we can explore
117    it->current = NULL;
118 
119 deliver:
120    *data = (void*)it->current;
121    return !!it->current;
122 }
123 
124 EAPI Eina_Iterator*
efl_ui_widget_tree_iterator(Efl_Ui_Widget * obj)125 efl_ui_widget_tree_iterator(Efl_Ui_Widget *obj)
126 {
127    ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
128    Widget_Iterator *it = iter_init(obj);
129    it->iterator.next = FUNC_ITERATOR_NEXT(_widget_next);
130 
131    return &it->iterator;
132 }
133 
134 static Eina_Bool
_only_widget(const void * container EINA_UNUSED,void * data,void * fdata EINA_UNUSED)135 _only_widget(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
136 {
137    return efl_isa(data, EFL_UI_WIDGET_CLASS);
138 }
139 
140 EAPI Eina_Iterator*
efl_ui_widget_tree_widget_iterator(Efl_Ui_Widget * obj)141 efl_ui_widget_tree_widget_iterator(Efl_Ui_Widget *obj)
142 {
143    ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
144    Eina_Iterator *tree_iterator = efl_ui_widget_tree_iterator(obj);
145 
146    return eina_iterator_filter_new(tree_iterator, _only_widget, NULL, NULL);
147 }
148 
149 static Eina_Bool
_parent_next(Widget_Iterator * it,void ** data)150 _parent_next(Widget_Iterator *it, void **data)
151 {
152    if (!it->current)
153      {
154         *data = it->origin;
155         it->current = *data;
156      }
157    else
158      {
159         Efl_Ui_Widget *parent = efl_ui_widget_parent_get(it->current);
160 
161         *data = parent;
162         it->current = parent;
163      }
164 
165    return !!*data;
166 }
167 
168 EAPI Eina_Iterator*
efl_ui_widget_parent_iterator(Efl_Ui_Widget * obj)169 efl_ui_widget_parent_iterator(Efl_Ui_Widget *obj)
170 {
171    ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
172    Widget_Iterator *it = iter_init(obj);
173    it->iterator.next = FUNC_ITERATOR_NEXT(_parent_next);
174    return &it->iterator;
175 }
176