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