summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>2015-07-23 17:29:36 +0200
committerMarcel Hollerbach <marcel-hollerbach@t-online.de>2015-07-23 17:29:53 +0200
commit761ccb491aa10b9d41ef6325dfd65d2823223db0 (patch)
tree238e657c709f09f7a7b6f8e19b06337127143c99
Initial commit
-rw-r--r--.gitignore6
-rw-r--r--CMakeLists.txt25
-rw-r--r--data/elm_ext.edc.edjbin0 -> 465229 bytes
-rw-r--r--src/lib/items/CMakeLists.txt55
-rw-r--r--src/lib/items/Elm_Items.h18
-rw-r--r--src/lib/items/elm_items.c29
-rw-r--r--src/lib/items/elm_items_display.c328
-rw-r--r--src/lib/items/elm_items_display.eo59
-rw-r--r--src/lib/items/elm_items_item.c215
-rw-r--r--src/lib/items/elm_items_item.eo54
-rw-r--r--src/lib/items/elm_items_list.c344
-rw-r--r--src/lib/items/elm_items_list.eo8
-rw-r--r--src/lib/items/elm_items_list_pan.eo21
-rw-r--r--src/lib/items/elm_items_priv.h43
-rw-r--r--src/lib/tree/CMakeLists.txt44
-rw-r--r--src/lib/tree/Graph.h10
-rw-r--r--src/lib/tree/efl_compare.c3
-rw-r--r--src/lib/tree/efl_compare.eo10
-rw-r--r--src/lib/tree/efl_tree_base.c266
-rw-r--r--src/lib/tree/efl_tree_base.eo84
-rw-r--r--src/lib/tree/graph_priv.h33
-rw-r--r--src/test/CMakeLists.txt2
-rw-r--r--src/test/list/CMakeLists.txt17
-rw-r--r--src/test/list/list.c85
-rw-r--r--src/test/tree/CMakeLists.txt14
-rw-r--r--src/test/tree/tree.c113
26 files changed, 1886 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b91764d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
1*.eo.legacy.h
2*.eo.x
3*.eo.h
4*.sublime-*
5Makefile
6build/ \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..ee5512a
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,25 @@
1cmake_minimum_required(VERSION 2.81)
2
3set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
4
5project(elm_items)
6
7enable_testing()
8set(CMAKE_BUILD_TYPE DEBUG)
9
10add_definitions ("-Wall -Wextra -fvisibility=hidden -std=gnu99")
11
12find_package(Eina REQUIRED)
13find_package(Eo 1.14.99 REQUIRED)
14find_package(Eolian 1.14.99 REQUIRED)
15find_package(Efl REQUIRED)
16find_package(Evas REQUIRED)
17find_package(Edje REQUIRED)
18find_package(Ecore COMPONENTS file)
19find_package(Elementary 1.13.0 REQUIRED)
20
21pkg_check_modules(Check REQUIRED check)
22
23add_subdirectory(src/lib/tree)
24add_subdirectory(src/lib/items)
25add_subdirectory(src/test) \ No newline at end of file
diff --git a/data/elm_ext.edc.edj b/data/elm_ext.edc.edj
new file mode 100644
index 0000000..6a512f9
--- /dev/null
+++ b/data/elm_ext.edc.edj
Binary files differ
diff --git a/src/lib/items/CMakeLists.txt b/src/lib/items/CMakeLists.txt
new file mode 100644
index 0000000..dba1e36
--- /dev/null
+++ b/src/lib/items/CMakeLists.txt
@@ -0,0 +1,55 @@
1set(THEME_INSTALL_PATH "${CMAKE_SOURCE_DIR}/data/")
2
3set(THEME_PATH_DEFINITION THEME_PATH="${THEME_INSTALL_PATH}")
4
5LIST(APPEND ELM_ITEMS_LIBRARY
6 elm_items.c
7 elm_items_display.c
8 elm_items_display.eo.x
9 elm_items_display.eo.h
10 elm_items_item.c
11 elm_items_item.eo.x
12 elm_items_item.eo.h
13 elm_items_list.c
14 elm_items_list.eo.x
15 elm_items_list.eo.h
16 elm_items_list_pan.eo.x
17 elm_items_list_pan.eo.h
18 )
19
20string(REPLACE "\n" "" EOLIAN_EO_DIR_WITHOUT_NEWLINE
21"${EOLIAN_EO_DIR}")
22
23file(GLOB_RECURSE files "*.eo")
24
25foreach(filename ${files})
26add_custom_command(
27 OUTPUT ${filename}.x
28 COMMAND eolian_gen -I ${EOLIAN_EO_DIR_WITHOUT_NEWLINE} -I ${CMAKE_SOURCE_DIR}/src/lib/ -I ${CMAKE_SOURCE_DIR}/src/tree/ --gc --eo --eo -o ${filename}.x ${filename}
29 DEPENDS ${filename}
30)
31
32add_custom_command(
33 OUTPUT ${filename}.h
34 COMMAND eolian_gen -I ${EOLIAN_EO_DIR_WITHOUT_NEWLINE} -I ${CMAKE_SOURCE_DIR}/src/lib/ -I ${CMAKE_SOURCE_DIR}/src/tree/ --gh --eo -o ${filename}.h ${filename}
35 DEPENDS ${filename}
36)
37
38endforeach()
39
40add_library(elm_items SHARED ${ELM_ITEMS_LIBRARY})
41
42include_directories(
43 ${EINA_INCLUDE_DIRS}
44 ${EO_INCLUDE_DIRS}
45 ${ELEMENTARY_INCLUDE_DIRS}
46 ../tree
47)
48
49target_link_libraries(elm_items
50 ${ELEMENTARY_LIRBRARIES}
51 tree_lib
52)
53
54set_property(TARGET elm_items
55 PROPERTY COMPILE_DEFINITIONS ${THEME_PATH_DEFINITION}) \ No newline at end of file
diff --git a/src/lib/items/Elm_Items.h b/src/lib/items/Elm_Items.h
new file mode 100644
index 0000000..62baa38
--- /dev/null
+++ b/src/lib/items/Elm_Items.h
@@ -0,0 +1,18 @@
1#ifndef ELM_ITEMS_H
2#define ELM_ITEMS_H
3
4#define EFL_BETA_API_SUPPORT
5#define EFL_EO_API_SUPPORT
6
7#include <Graph.h>
8#include <Elementary.h>
9
10#include "elm_items_item.eo.h"
11#include "elm_items_display.eo.h"
12#include "elm_items_list.eo.h"
13#include "elm_items_list_pan.eo.h"
14
15EAPI int elm_items_init();
16EAPI int elm_items_shutdown();
17
18#endif \ No newline at end of file
diff --git a/src/lib/items/elm_items.c b/src/lib/items/elm_items.c
new file mode 100644
index 0000000..56b724f
--- /dev/null
+++ b/src/lib/items/elm_items.c
@@ -0,0 +1,29 @@
1#include "elm_items_priv.h"
2
3int log_domain;
4static int ref_count = 0;
5
6EAPI int
7elm_items_init()
8{
9 if (ref_count > 0)
10 return ++ ref_count;
11
12 Elm_Theme *th = elm_theme_default_get();
13 elm_theme_extension_add(th, THEME_PATH"/elm_ext.edc.edj");
14 elm_theme_flush(th);
15
16 ref_count ++;
17 log_domain = eina_log_domain_register("elm_items", NULL);
18
19 return ref_count;
20}
21
22EAPI int
23elm_items_shutdown()
24{
25 ref_count --;
26 if (ref_count > 0) return ref_count;
27 eina_log_domain_unregister(log_domain);
28 return ref_count;
29}
diff --git a/src/lib/items/elm_items_display.c b/src/lib/items/elm_items_display.c
new file mode 100644
index 0000000..c79a336
--- /dev/null
+++ b/src/lib/items/elm_items_display.c
@@ -0,0 +1,328 @@
1#include "elm_items_priv.h"
2
3typedef struct {
4 Efl_Tree_Base *root; //< the root item of the item node
5 Eina_List *realized; //< list of realized items
6 Evas_Object *pane; //< the pane of the implementor
7 Eina_Strbuf *search;
8 Ecore_Idler *recalc_idler;
9 Eina_List *selected; //< list of selected items
10} Elm_Items_Display_Data;
11
12EOLIAN static Efl_Tree_Base *
13_elm_items_display_tree_get(Eo *obj EINA_UNUSED, Elm_Items_Display_Data *pd)
14{
15 return pd->root;
16}
17
18EOLIAN static Eina_Bool
19_elm_items_display_elm_widget_event(Eo *obj, Elm_Items_Display_Data *pd, Evas_Object *source EINA_UNUSED, Evas_Callback_Type type, void *event_info)
20{
21 Evas_Event_Key_Down *ev;
22 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_TRUE;
23
24 ev = event_info;
25
26 if (ev->key[1] == '\0' && isalnum(*ev->string))
27 {
28 if (!pd->search)
29 pd->search = eina_strbuf_new();
30
31 eina_strbuf_append(pd->search, ev->string);
32 eo_do(obj, elm_items_display_search(eina_strbuf_string_get(pd->search)));
33 return EINA_TRUE;
34 }
35 else if (!strcmp(ev->key, "BackSpace"))
36 {
37 char *oldstr;
38 int oldlength;
39 //shrink search string
40
41 if (!pd->search)
42 return EO_CALLBACK_STOP;
43
44 oldlength = eina_strbuf_length_get(pd->search);
45 oldstr = eina_strbuf_string_steal(pd->search);
46
47 if (oldlength == 0)
48 return EO_CALLBACK_STOP;
49
50 //reset the string
51 eina_strbuf_reset(pd->search);
52 //cut off the last bit
53 oldstr[oldlength - 1] = '\0';
54
55 eina_strbuf_append(pd->search, oldstr);
56 free(oldstr);
57 eo_do(obj, elm_items_display_search(eina_strbuf_string_get(pd->search)));
58 return EINA_TRUE;
59 }
60 else if (!strcmp(ev->key, "Right"))
61 {
62 //sent right
63 eo_do(obj, elm_items_display_sel_move(ELM_ITEMS_MOVE_DIR_EAST));
64 return EINA_TRUE;
65 }
66 else if (!strcmp(ev->key, "Left"))
67 {
68 //sent let
69 eo_do(obj, elm_items_display_sel_move(ELM_ITEMS_MOVE_DIR_WEST));
70 return EINA_TRUE;
71 }
72 else if (!strcmp(ev->key, "Up"))
73 {
74 //sent up
75 eo_do(obj, elm_items_display_sel_move(ELM_ITEMS_MOVE_DIR_NORTH));
76 return EINA_TRUE;
77 }
78 else if (!strcmp(ev->key, "Down"))
79 {
80 //sent down
81 eo_do(obj, elm_items_display_sel_move(ELM_ITEMS_MOVE_DIR_SOUTH));
82 return EINA_TRUE;
83 }
84 else if (!strcmp(ev->key, "Return"))
85 {
86 //select
87 eo_do(obj, elm_items_display_select());
88 return EINA_TRUE;
89 }
90 else if (!strcmp(ev->key, "Home"))
91 {
92 //first item
93 eo_do(obj, elm_interface_scrollable_page_bring_in(0, 0));
94 return EINA_TRUE;
95 }
96 else if (!strcmp(ev->key, "End"))
97 {
98 //last item
99 int h,v;
100 eo_do(obj, elm_interface_scrollable_last_page_get(&h, &v);
101 elm_interface_scrollable_page_bring_in(h, v));
102 return EINA_TRUE;
103 }
104 else if (!strcmp(ev->key, "Next"))
105 {
106 //next page
107 int h,v;
108 eo_do(obj, elm_interface_scrollable_current_page_get(&h, &v);
109 elm_interface_scrollable_page_bring_in(h, v+1));
110 return EINA_TRUE;
111 }
112 else if (!strcmp(ev->key, "Prior"))
113 {
114 //prior page
115 int h,v;
116 eo_do(obj, elm_interface_scrollable_current_page_get(&h, &v);
117 elm_interface_scrollable_page_bring_in(h, v-1));
118 return EINA_TRUE;
119 }
120 return EO_CALLBACK_CONTINUE;
121}
122
123EOLIAN static void
124_elm_items_display_search(Eo *obj EINA_UNUSED, Elm_Items_Display_Data *pd, const char *search)
125{
126 Eina_List *node, *children;
127 Efl_Tree_Base *tb;
128 int min = -1;
129 Elm_Items_Item *searched = NULL;
130
131 eo_do(pd->root, children = efl_tree_base_children(EINA_TRUE));
132
133 EINA_LIST_FOREACH(children, node, tb)
134 {
135 Elm_Items_Item *item;
136 const char *searchable;
137 char *f;
138 eo_do(tb, item = efl_tree_base_carry_get());
139 eo_do(item, searchable = elm_items_item_search_get());
140
141 if (!searchable) continue;
142
143 if ((f = strstr(searchable, search)))
144 {
145 int tmin = f - searchable;
146 if (min == -1)
147 min = tmin;
148
149 if (tmin > min)
150 continue;
151 min = tmin;
152 searched = item;
153 }
154 }
155 eo_do(searched, elm_items_item_selected_set(EINA_TRUE));
156}
157
158static Eina_Bool
159_selected(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description2 *desc EINA_UNUSED, void *event EINA_UNUSED)
160{
161 Elm_Items_Display_Data *pd;
162
163 pd = eo_data_scope_get(data, ELM_ITEMS_DISPLAY_CLASS);
164 pd->selected = eina_list_append(pd->selected, obj);
165 return EO_CALLBACK_CONTINUE;
166}
167
168static Eina_Bool
169_unselected(void *data, Eo *obj, const Eo_Event_Description2 *desc EINA_UNUSED, void *event EINA_UNUSED)
170{
171 Elm_Items_Display_Data *pd;
172
173 pd = eo_data_scope_get(data, ELM_ITEMS_DISPLAY_CLASS);
174 pd->selected = eina_list_remove(pd->selected, obj);
175 return EO_CALLBACK_CONTINUE;
176}
177
178static Eina_Bool
179_del(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description2 *desc EINA_UNUSED, void *event EINA_UNUSED)
180{
181 Elm_Items_Display_Data *pd;
182 Eo *good;
183
184 pd = eo_data_scope_get(data, ELM_ITEMS_DISPLAY_CLASS);
185
186 eo_do(event, good = efl_tree_base_carry_get());
187 eo_do(good, eo_event_callback_del(ELM_ITEMS_ITEM_EVENT_SELECTED, _selected, data);
188 eo_event_callback_del(ELM_ITEMS_ITEM_EVENT_UNSELECTED, _unselected, data);
189 );
190
191 //remove from selected
192 pd->selected = eina_list_remove(pd->selected, good);
193 //remove from potential realized
194 pd->realized = eina_list_remove(pd->realized, good);
195 return EO_CALLBACK_CONTINUE;
196}
197
198static Eina_Bool
199_add(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description2 *desc EINA_UNUSED, void *event EINA_UNUSED)
200{
201 Eo *good;
202
203 //subscribe to events
204 eo_do(event, good = efl_tree_base_carry_get());
205 eo_do(good, eo_event_callback_add(ELM_ITEMS_ITEM_EVENT_SELECTED, _selected, data);
206 eo_event_callback_add(ELM_ITEMS_ITEM_EVENT_UNSELECTED, _unselected, data);
207 );
208 //XXX: check if selected and add to list
209 return EO_CALLBACK_CONTINUE;
210}
211
212EOLIAN static Eina_List *
213_elm_items_display_selected_get(Eo *obj EINA_UNUSED, Elm_Items_Display_Data *pd)
214{
215 return pd->selected;
216}
217
218EOLIAN static Eo_Base *
219_elm_items_display_eo_base_constructor(Eo *obj, Elm_Items_Display_Data *pd)
220{
221 Eo *eo;
222
223 pd->root = eo_add(EFL_TREE_BASE_CLASS, NULL);
224
225 eo_do(pd->root,
226 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_DEL_RECURSIVE, _del, obj);
227 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_DEL_DIRECT, _del, obj);
228 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_ADD_RECURSIVE, _add, obj);
229 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_ADD_DIRECT, _add, obj);
230 );
231
232 eo_do_super(obj, ELM_ITEMS_DISPLAY_CLASS, eo = eo_constructor());
233 return eo;
234}
235
236EOLIAN static void
237_elm_items_display_eo_base_destructor(Eo *obj, Elm_Items_Display_Data *pd)
238{
239 Elm_Items_Item *item;
240
241 EINA_LIST_FREE(pd->realized, item)
242 {
243 eo_do(item, eo_event_callback_del(EO_BASE_EVENT_DEL, _del, obj));
244 }
245
246 eo_del(pd->root);
247
248 eo_do_super(obj, ELM_ITEMS_DISPLAY_CLASS, eo_destructor());
249}
250
251EOLIAN static void
252_elm_items_display_realizes_set(Eo *obj EINA_UNUSED, Elm_Items_Display_Data *pd, Eina_List *realized)
253{
254 Eina_List *node;
255 Eina_List *realizes = NULL;
256
257 Elm_Items_Item *item;
258 //get the diff between the two sets of items
259 EINA_LIST_FOREACH(realized, node, item)
260 {
261 if (eina_list_data_find_list(pd->realized, item))
262 {
263 //this item is allready realized
264 pd->realized = eina_list_remove(pd->realized, item);
265 }
266 else
267 {
268 //this items needs to be realized
269 realizes = eina_list_append(realizes, item);
270 }
271 }
272 //realize the new ones
273 EINA_LIST_FREE(realizes, item)
274 {
275 eo_do(item, elm_items_item_realize());
276 evas_object_show(item);
277 }
278
279 //unrealize the old realized which are not realized anymore
280 EINA_LIST_FREE(pd->realized, item)
281 {
282 eo_do(item, elm_items_item_unrealize());
283 evas_object_hide(item);
284 }
285
286 pd->realized = realized;
287}
288
289EOLIAN static Eina_List *
290_elm_items_display_realizes_get(Eo *obj EINA_UNUSED, Elm_Items_Display_Data *pd)
291{
292 return pd->realized;
293}
294
295EOLIAN static Eina_List *
296_elm_items_display_item_search_xywh(Eo *obj EINA_UNUSED, Elm_Items_Display_Data *pd, int xx, int yy, int ww, int hh)
297{
298 Eina_List *children, *node;
299 Efl_Tree_Base *treeitem;
300 Elm_Items_Item *item;
301 Eina_List *items = NULL;
302 Eina_Rectangle viewport;
303
304 EINA_RECTANGLE_SET(&viewport, xx, yy, ww, hh);
305
306 //get all the childs
307 //eo_do(pd->root, children = efl_tree_base_children(EINA_TRUE));
308
309 //iterate throuw all the childs
310 EINA_LIST_FOREACH(pd->realized, node, item)
311 {
312 int x,y,w,h;
313 Eina_Rectangle itemrect;
314 //get the geometry of a new item
315 evas_object_geometry_get(item, &x, &y, &w, &h);
316 EINA_RECTANGLE_SET(&itemrect, x, y, w, h);
317
318 //check if the item is in the searched rectangle
319 if (eina_rectangles_intersect(&viewport, &itemrect))
320 {
321 //printf("%d-%d-%d-%d %d-%d-%d-%d\n", vpx,vpy,vpw,vph,x,y,w,h);
322 items = eina_list_append(items, item);
323 }
324 }
325 return items;
326}
327
328#include "elm_items_display.eo.x" \ No newline at end of file
diff --git a/src/lib/items/elm_items_display.eo b/src/lib/items/elm_items_display.eo
new file mode 100644
index 0000000..7ed639b
--- /dev/null
+++ b/src/lib/items/elm_items_display.eo
@@ -0,0 +1,59 @@
1enum Elm.Items.Move_Dir {
2 NORTH, WEST, EAST, SOUTH
3}
4
5abstract Elm.Items.Display (Elm.Scroller) {
6 [[]]
7 methods {
8 @property tree {
9 get {
10
11 }
12 values {
13 root : Efl.Tree.Base*;
14 }
15 }
16 sel_move {
17 params {
18 direction : Elm.Items.Move_Dir;
19 }
20 }
21 select {
22
23 }
24 item_search_xywh {
25 params {
26 x : int;
27 y : int;
28 w : int;
29 h : int;
30 }
31 return : list<Elm.Items.Item*>*;
32 }
33 search {
34 params {
35 search : const(char)*;
36 }
37 }
38 @property selected {
39 get {
40
41 }
42 values {
43 selected : list<Elm.Items.Item*>*;
44 }
45 }
46 @property realizes {
47 values {
48 realizes : list <Elm.Items.Item*>*;
49 }
50 }
51 }
52 implements {
53 @virtual .sel_move;
54 @virtual .select;
55 Elm.Widget.event;
56 Eo.Base.constructor;
57 Eo.Base.destructor;
58 }
59} \ No newline at end of file
diff --git a/src/lib/items/elm_items_item.c b/src/lib/items/elm_items_item.c
new file mode 100644
index 0000000..f283cd1
--- /dev/null
+++ b/src/lib/items/elm_items_item.c
@@ -0,0 +1,215 @@
1#include "elm_items_priv.h"
2
3typedef struct {
4 Evas_Object *edje;
5 Evas_Object *content;
6 Eina_Bool selected;
7 Efl_Tree_Base *item;
8 Ecore_Timer *double_timer;
9 const char * searchable;
10} Elm_Items_Item_Data;
11
12static Ecore_Idler *realize_idler;
13static Eina_List *realizes = NULL;
14
15static Eina_Bool
16_idler(void *data)
17{
18 Eo *realize;
19
20 realize = eina_list_data_get(realizes);
21
22 realizes = eina_list_remove(realizes, realize);
23
24 eo_do(realize, eo_event_callback_call(ELM_ITEMS_ITEM_EVENT_REALIZE, NULL));
25
26 return !!realize;
27}
28
29
30EOLIAN static void
31_elm_items_item_content_set(Eo *obj EINA_UNUSED, Elm_Items_Item_Data *pd, Evas_Object *content)
32{
33 pd->content = content;
34 elm_object_part_content_unset(pd->edje, "content");
35 elm_object_part_content_set(pd->edje, "content", pd->content);
36}
37
38EOLIAN static Evas_Object *
39_elm_items_item_content_get(Eo *obj EINA_UNUSED, Elm_Items_Item_Data *pd)
40{
41 return pd->content;
42}
43
44EOLIAN static void
45_elm_items_item_realize(Eo *obj, Elm_Items_Item_Data *pd EINA_UNUSED)
46{
47 //call realize event
48 if (!pd->content)
49 realizes = eina_list_append(realizes, obj);
50
51 if (!realize_idler)
52 {
53 realize_idler = ecore_idler_add(_idler, NULL);
54 eo_weak_ref(&realize_idler);
55 }
56}
57
58EOLIAN static void
59_elm_items_item_unrealize(Eo *obj, Elm_Items_Item_Data *pd EINA_UNUSED)
60{
61 eo_do(obj, eo_event_callback_call(ELM_ITEMS_ITEM_EVENT_UNREALIZE, NULL));
62
63 realizes = eina_list_remove(realizes, obj);
64}
65
66EOLIAN static void
67_elm_items_item_selected_set(Eo *obj, Elm_Items_Item_Data *pd, Eina_Bool selected)
68{
69 if (pd->selected == selected) return;
70
71 pd->selected = selected;
72
73 if (selected)
74 {
75 elm_layout_signal_emit(pd->edje, "elm,state,selected,on", "elm");
76 eo_do(obj, eo_event_callback_call(ELM_ITEMS_ITEM_EVENT_SELECTED, NULL));
77 }
78 else
79 {
80 elm_layout_signal_emit(pd->edje, "elm,state,selected,off", "elm");
81 eo_do(obj, eo_event_callback_call(ELM_ITEMS_ITEM_EVENT_UNSELECTED, NULL));
82 }
83}
84
85EOLIAN static Eina_Bool
86_elm_items_item_selected_get(Eo *obj EINA_UNUSED, Elm_Items_Item_Data *pd)
87{
88 return pd->selected;
89}
90
91static Eina_Bool
92_timer_cb(void *data)
93{
94 Elm_Items_Item_Data *pd;
95
96 pd = eo_data_scope_get(data, ELM_ITEMS_ITEM_CLASS);
97
98 if (!pd)
99 {
100 ERR("timer is not corrected correct /o\\");
101 return EINA_FALSE;
102 }
103
104 pd->double_timer = NULL;
105
106 return EINA_FALSE;
107}
108
109static void
110_mouse_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
111{
112 Evas_Event_Mouse_Up *ev;
113 Eina_Bool selected;
114 Elm_Items_Item_Data *pd;
115 Eo *sobj;
116
117 pd = eo_data_scope_get(obj, ELM_ITEMS_ITEM_CLASS);
118 ev = event_info;
119
120 if (ev->button != 1) return;
121
122 //get a self reference, if one of the callbacks leads to a deletion of this object, we can detect it and return
123 eo_do(obj, eo_wref_add(&sobj));
124
125 eo_do(sobj, selected = elm_items_item_selected_get());
126
127 if (selected && pd->double_timer)
128 {
129 //this is a double click! nasty!
130 ecore_timer_del(pd->double_timer);
131 pd->double_timer = NULL;
132 eo_do(sobj, eo_event_callback_call(ELM_ITEMS_ITEM_EVENT_CLICKED_DOUBLE, NULL));
133 return;
134 }
135
136 eo_do(sobj, eo_event_callback_call(ELM_ITEMS_ITEM_EVENT_CLICKED, NULL));
137 if (!sobj)
138 return;
139
140 eo_do(sobj, elm_items_item_selected_set(!selected));
141 if (!sobj)
142 return;
143
144 if (!selected)
145 pd->double_timer = ecore_timer_add(1.0, _timer_cb, obj);
146
147}
148
149EOLIAN static void
150_elm_items_item_evas_object_smart_add(Eo *obj, Elm_Items_Item_Data *pd)
151{
152 eo_do_super(obj,ELM_ITEMS_ITEM_CLASS,evas_obj_smart_add());
153
154 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP, _mouse_down, NULL);
155
156 pd->edje = elm_layout_add(obj);
157
158 if (!elm_layout_theme_set(pd->edje, "icons", "item", "default"))
159 {
160 ERR("Failed to set theme");
161 }
162
163 elm_widget_resize_object_set(obj, pd->edje, EINA_TRUE);
164}
165
166static Eina_Bool
167_del(void *data, Eo *obj, const Eo_Event_Description2 *desc, void *event_info)
168{
169 Elm_Items_Item_Data *pd;
170
171 pd = eo_data_scope_get(data, ELM_ITEMS_ITEM_CLASS);
172
173 pd->item = NULL;
174
175 eo_del(data);
176 return EO_CALLBACK_CONTINUE;
177}
178
179EOLIAN static Efl_Tree_Base *
180_elm_items_item_item_get(Eo *obj, Elm_Items_Item_Data *pd)
181{
182 if (pd->item)
183 return pd->item;
184
185 pd->item = eo_add(EFL_TREE_BASE_CLASS, obj);
186 eo_do(pd->item, efl_tree_base_carry_set(obj);
187 eo_event_callback_add(EO_BASE_EVENT_DEL, _del, obj));
188
189 return pd->item;
190}
191
192EOLIAN static void
193_elm_items_item_eo_base_destructor(Eo *obj, Elm_Items_Item_Data *pd)
194{
195 if (pd->item)
196 eo_del(pd->item);
197 ecore_timer_del(pd->double_timer);
198 pd->double_timer = NULL;
199 eo_do_super(obj, ELM_ITEMS_ITEM_CLASS, eo_destructor());
200}
201
202EOLIAN static void
203_elm_items_item_search_set(Eo *obj EINA_UNUSED, Elm_Items_Item_Data *pd, const char *string)
204{
205 pd->searchable = string;
206}
207
208EOLIAN static const char *
209_elm_items_item_search_get(Eo *obj EINA_UNUSED, Elm_Items_Item_Data *pd)
210{
211 return pd->searchable;
212}
213
214
215#include "elm_items_item.eo.x" \ No newline at end of file
diff --git a/src/lib/items/elm_items_item.eo b/src/lib/items/elm_items_item.eo
new file mode 100644
index 0000000..3405397
--- /dev/null
+++ b/src/lib/items/elm_items_item.eo
@@ -0,0 +1,54 @@
1class Elm.Items.Item (Elm.Widget) {
2 [[A selectable widget which shows the selection state of the widget
3
4 The content set by content.set is displayed in the widget.
5
6 The displaying widget of this item is calling realize everytime the item will be displayed.
7 If content is set the call will not result in the event realize, if there is no content the call is called.
8 If the item moves out of the view unrealize is called. This call results in a unrealize event.
9
10 ]]
11
12 methods {
13 @property content {
14 [[The content which is displayed in this item]]
15 values {
16 content : Evas.Object*;
17 }
18 }
19 @property selected {
20 [[Set true/false if this item is selected/not selected]]
21 values {
22 selected : bool;
23 }
24 }
25 realize {
26 [[Call before this item is about to be displayed]]
27 }
28 unrealize {
29 [[Call this if you dont display this item anymore]]
30 }
31 item_get {
32 [[Get the item in the tree assiciated with this item]]
33 return : Efl.Tree.Base*;
34 }
35 @property search {
36 [[Elm.Items.Display supports seraching, this property is the way how it compares this item to the others]]
37 values {
38 string: const(char)*;
39 }
40 }
41 }
42 implements {
43 Evas.Object_Smart.add;
44 Eo.Base.destructor;
45 }
46 events {
47 realize;
48 unrealize;
49 selected;
50 unselected;
51 clicked;
52 clicked,double;
53 }
54} \ No newline at end of file
diff --git a/src/lib/items/elm_items_list.c b/src/lib/items/elm_items_list.c
new file mode 100644
index 0000000..72aa2ab
--- /dev/null
+++ b/src/lib/items/elm_items_list.c
@@ -0,0 +1,344 @@
1#include "elm_items_priv.h"
2
3//XXX: For now everything works just for strait items, no children or something will be displayed
4
5typedef struct {
6 Eo *root;
7 Eina_Bool unselect_barrier;
8 Evas_Object *pan;
9 Eina_List *realitems;
10 Ecore_Idler *flush_idle;
11} Elm_Items_List_Data;
12
13typedef struct {
14 Evas_Box *box;
15 Eo *obj;
16 int w,h;
17 int px,py;
18 int y;
19 int old_first;
20 int old_last;
21 Eina_List *realitems;
22 Eina_List *realized;
23} Elm_Items_List_Pan_Data;
24
25#define HACKY_HEIGHT 30
26
27EOLIAN static void
28_elm_items_list_elm_items_display_select(Eo *obj, Elm_Items_List_Data *pd EINA_UNUSED)
29{
30 Eina_List *selection;
31
32 eo_do(obj, selection = elm_items_display_selected_get());
33
34 if (eina_list_count(selection) != 1)
35 return;
36 //emulate double click on this item XXX find a proper way
37 eo_do(eina_list_data_get(selection), eo_event_callback_call(ELM_ITEMS_ITEM_EVENT_CLICKED_DOUBLE, NULL));
38}
39
40EOLIAN static void
41_elm_items_list_elm_items_display_sel_move(Eo *obj, Elm_Items_List_Data *pd, Elm_Items_Move_Dir direction)
42{
43
44}
45
46EOLIAN static void
47_elm_items_list_evas_object_smart_add(Eo *obj, Elm_Items_List_Data *pd EINA_UNUSED)
48{
49 eo_do_super(obj, ELM_ITEMS_LIST_CLASS, evas_obj_smart_add());
50}
51
52static Eina_Bool
53_selected(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event EINA_UNUSED)
54{
55 Elm_Items_List_Data *pd;
56 Elm_Items_Item *sel;
57 const Evas_Modifier *mods;
58 Eina_List *selection;
59
60 pd = eo_data_scope_get(data, ELM_ITEMS_LIST_CLASS);
61 eo_do(data, selection = elm_items_display_selected_get());
62
63 mods = evas_key_modifier_get(evas_object_evas_get(obj));
64
65 if (!evas_key_modifier_is_set(mods, "Control"))
66 {
67 Eina_List *selected;
68
69 selected = eina_list_clone(selection);
70 //stop unselecting work
71 pd->unselect_barrier = EINA_TRUE;
72 EINA_LIST_FREE(selected, sel)
73 {
74 if (sel == obj) continue;
75 eo_do(sel, elm_items_item_selected_set(EINA_FALSE));
76 }
77 //restart unselecting work
78 pd->unselect_barrier = EINA_FALSE;
79 }
80 return EO_CALLBACK_CONTINUE;
81}
82
83static Eina_Bool
84_unselected(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event EINA_UNUSED)
85{
86 Elm_Items_List_Data *pd;
87 const Evas_Modifier *mods;
88 Eina_List *selection;
89
90 pd = eo_data_scope_get(data, ELM_ITEMS_LIST_CLASS);
91 eo_do(data, selection = elm_items_display_selected_get());
92 if (pd->unselect_barrier) return EO_CALLBACK_CONTINUE;
93
94 mods = evas_key_modifier_get(evas_object_evas_get(data));
95
96 if (!evas_key_modifier_is_set(mods, "Control"))
97 {
98 if (eina_list_count(selection) > 1)
99 eo_do(obj, elm_items_item_selected_set(EINA_TRUE));
100
101 }
102 return EO_CALLBACK_CONTINUE;
103}
104
105static Eina_Bool
106_idle_tree_flush(void *data)
107{
108 Elm_Items_List_Data *pd;
109
110 pd = eo_data_scope_get(data, ELM_ITEMS_LIST_CLASS);
111 eo_do(pd->pan, elm_items_list_pan_realitems(pd->realitems));
112
113 pd->flush_idle = NULL;
114
115 return EINA_FALSE;
116}
117
118static Eina_Bool
119_add(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event)
120{
121 Eo *good;
122 Eo *prev;
123 Eo *next;
124 Elm_Items_List_Data *pd;
125
126 pd = eo_data_scope_get(data, ELM_ITEMS_LIST_CLASS);
127
128 eo_do(event, good = efl_tree_base_carry_get();
129 prev = efl_tree_base_prev_get();
130 next = efl_tree_base_next_get();
131 );
132 //subscribe to item events
133 eo_do(good, eo_event_callback_add(ELM_ITEMS_ITEM_EVENT_SELECTED, _selected, data);
134 eo_event_callback_add(ELM_ITEMS_ITEM_EVENT_UNSELECTED, _unselected, data);
135 );
136 //set hints
137 evas_object_size_hint_min_set(good, 1, HACKY_HEIGHT);
138 evas_object_size_hint_align_set(good, EVAS_HINT_FILL, 1.0);
139 evas_object_size_hint_weight_set(good, EVAS_HINT_EXPAND, 0.0);
140 //show the item
141 evas_object_show(good);
142
143 pd->realitems = eina_list_append(pd->realitems, good);
144
145 if (!pd->flush_idle)
146 pd->flush_idle = ecore_idler_add(_idle_tree_flush, data);
147
148 return EO_CALLBACK_CONTINUE;
149}
150
151static Eina_Bool
152_del(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event)
153{
154 Eo *good;
155 Elm_Items_List_Data *pd;
156
157 pd = eo_data_scope_get(data, ELM_ITEMS_LIST_CLASS);
158
159 eo_do(event, good = efl_tree_base_carry_get());
160
161 pd->realitems = eina_list_remove(pd->realitems, good);
162
163 if (!pd->flush_idle)
164 pd->flush_idle = ecore_idler_add(_idle_tree_flush, data);
165
166 return EO_CALLBACK_CONTINUE;
167}
168
169EOLIAN static Eo_Base *
170_elm_items_list_eo_base_constructor(Eo *obj, Elm_Items_List_Data *pd)
171{
172 Eo *eo;
173
174 eo_do_super(obj, ELM_ITEMS_LIST_CLASS, eo = eo_constructor());
175
176 if (!eo)
177 return eo;
178
179 //get the root
180 eo_do(obj, pd->root = elm_items_display_tree_get());
181
182 //monitor changes on the tree
183 eo_do(pd->root,
184 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_ADD_DIRECT, _add, obj);
185 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_DEL_DIRECT, _del, obj);
186 );
187
188 pd->pan = eo_add(ELM_ITEMS_LIST_PAN_CLASS, obj);
189 {
190 Elm_Items_List_Pan_Data *pdpan = eo_data_scope_get(pd->pan, ELM_ITEMS_LIST_PAN_CLASS);
191 pdpan->obj = obj;
192 pdpan->box = evas_object_box_add(evas_object_evas_get(obj));
193 evas_object_smart_member_add(pdpan->box, pd->pan);
194 evas_object_box_padding_set(pdpan->box, 0, 0);
195 evas_object_box_align_set(pdpan->box, 0.0, 0.0);
196 evas_object_box_layout_set(pdpan->box, evas_object_box_layout_vertical, pdpan->box, NULL);
197 evas_object_show(pdpan->box);
198 }
199
200 eo_do(obj, elm_interface_scrollable_extern_pan_set(pd->pan));
201 return eo;
202}
203
204//===== pan element =====
205
206static void
207_pan_update(Eo *obj, Elm_Items_List_Pan_Data *pd)
208{
209 int first_item, last_item;
210 int gap;
211 Eina_Bool realize_dir;
212 Eina_List *realizes = NULL;
213
214 gap = pd->y % (HACKY_HEIGHT);
215 first_item = pd->y / HACKY_HEIGHT;
216 last_item = ((pd->y + pd->h) / HACKY_HEIGHT);
217
218 //remove all children from the box if we have new items
219 if (pd->old_last != last_item || pd->old_first != first_item)
220 evas_object_box_remove_all(pd->box, EINA_FALSE);
221
222 //move the box to the new position
223 evas_object_move(pd->box, pd->px, pd->py - (gap));
224 evas_object_resize(pd->box, pd->w, (last_item - first_item) * HACKY_HEIGHT);
225
226
227 if (pd->old_last != last_item || pd->old_first != first_item)
228 {
229 Eina_List *itemlist;
230 //add the new items
231 itemlist = eina_list_nth_list(pd->realitems, first_item);
232
233 for (int i = first_item; i <= last_item; i++)
234 {
235 Eo *item;
236
237 item = eina_list_data_get(itemlist);
238
239 evas_object_box_append(pd->box, item);
240 realizes = eina_list_append(realizes, item);
241 itemlist = eina_list_next(itemlist);
242 }
243 //update old items
244 pd->old_first = first_item;
245 pd->old_last = last_item;
246 //set new realizes
247 eo_do(pd->obj, elm_items_display_realizes_set(realizes));
248 }
249}
250
251EOLIAN static void
252_elm_items_list_pan_realitems(Eo *obj, Elm_Items_List_Pan_Data *pd, Eina_List *list)
253{
254 eo_do(pd->obj, elm_items_display_realizes_set(NULL));
255 pd->old_first = -1;
256 pd->old_last = -1;
257 //set new list
258 pd->realized = NULL;
259 pd->realitems = list;
260 //update pan
261 _pan_update(obj, pd);
262 eo_do(obj, eo_event_callback_call(ELM_PAN_EVENT_CHANGED, NULL));
263}
264
265EOLIAN static void
266_elm_items_list_pan_elm_pan_gravity_set(Eo *obj, Elm_Items_List_Pan_Data *pd, double x, double y)
267{
268
269}
270
271EOLIAN static void
272_elm_items_list_pan_elm_pan_gravity_get(Eo *obj, Elm_Items_List_Pan_Data *pd, double *x, double *y)
273{
274 if (x)
275 *x = 0;
276 if (y)
277 *y = 0;
278}
279
280EOLIAN static void
281_elm_items_list_pan_elm_pan_pos_set(Eo *obj, Elm_Items_List_Pan_Data *pd, Evas_Coord x, Evas_Coord y)
282{
283 if (pd->y == y) return;
284 pd->y = y;
285
286 _pan_update(obj, pd);
287}
288
289EOLIAN static void
290_elm_items_list_pan_elm_pan_pos_get(Eo *obj EINA_UNUSED, Elm_Items_List_Pan_Data *pd, Evas_Coord *x, Evas_Coord *y)
291{
292 if (x)
293 *x = 0;
294 if (y)
295 *y = pd->y;
296}
297
298EOLIAN static void
299_elm_items_list_pan_elm_pan_content_size_get(Eo *obj EINA_UNUSED, Elm_Items_List_Pan_Data *pd, Evas_Coord *w, Evas_Coord *h)
300{
301 if (w)
302 *w = 10;
303 if (h)
304 *h = eina_list_count(pd->realitems) * HACKY_HEIGHT;
305}
306
307EOLIAN static void
308_elm_items_list_pan_elm_pan_pos_min_get(Eo *obj EINA_UNUSED, Elm_Items_List_Pan_Data *pd EINA_UNUSED, Evas_Coord *x, Evas_Coord *y)
309{
310 if (x)
311 *x = 0;
312 if (y)
313 *y = 0;
314}
315
316EOLIAN static void
317_elm_items_list_pan_elm_pan_pos_max_get(Eo *obj EINA_UNUSED, Elm_Items_List_Pan_Data *pd, Evas_Coord *x, Evas_Coord *y)
318{
319 if (x)
320 *x = 0;
321 if (y)
322 *y = eina_list_count(pd->realitems) * HACKY_HEIGHT - pd->h;
323}
324
325EOLIAN static void
326_elm_items_list_pan_evas_object_smart_resize(Eo *obj EINA_UNUSED, Elm_Items_List_Pan_Data *pd, Evas_Coord w, Evas_Coord h)
327{
328 pd->w = w;
329 pd->h = h;
330 _pan_update(obj, pd);
331 eo_do_super(obj, ELM_ITEMS_LIST_PAN_CLASS, evas_obj_smart_resize(w, h));
332}
333
334EOLIAN static void
335_elm_items_list_pan_evas_object_smart_move(Eo *obj, Elm_Items_List_Pan_Data *pd, Evas_Coord x, Evas_Coord y)
336{
337 pd->px = x;
338 pd->py = y;
339 _pan_update(obj, pd);
340 eo_do_super(obj, ELM_ITEMS_LIST_PAN_CLASS, evas_obj_smart_move(x, y));
341}
342
343#include "elm_items_list.eo.x"
344#include "elm_items_list_pan.eo.x" \ No newline at end of file
diff --git a/src/lib/items/elm_items_list.eo b/src/lib/items/elm_items_list.eo
new file mode 100644
index 0000000..6800bb4
--- /dev/null
+++ b/src/lib/items/elm_items_list.eo
@@ -0,0 +1,8 @@
1class Elm.Items.List(Elm.Items.Display) {
2 implements {
3 Elm.Items.Display.sel_move;
4 Elm.Items.Display.select;
5 Evas.Object_Smart.add;
6 Eo.Base.constructor;
7 }
8} \ No newline at end of file
diff --git a/src/lib/items/elm_items_list_pan.eo b/src/lib/items/elm_items_list_pan.eo
new file mode 100644
index 0000000..0a70132
--- /dev/null
+++ b/src/lib/items/elm_items_list_pan.eo
@@ -0,0 +1,21 @@
1class Elm.Items.List.Pan (Elm_Pan) {
2 methods {
3 realitems {
4 params {
5 list : list<Elm.Items.Item*>*;
6 }
7 }
8 }
9
10 implements {
11 Elm_Pan.gravity.set;
12 Elm_Pan.gravity.get;
13 Elm_Pan.pos.set;
14 Elm_Pan.pos.get;
15 Elm_Pan.content_size.get;
16 Elm_Pan.pos_min.get;
17 Elm_Pan.pos_max.get;
18 Evas.Object_Smart.resize;
19 Evas.Object_Smart.move;
20 }
21} \ No newline at end of file
diff --git a/src/lib/items/elm_items_priv.h b/src/lib/items/elm_items_priv.h
new file mode 100644
index 0000000..eb3291e
--- /dev/null
+++ b/src/lib/items/elm_items_priv.h
@@ -0,0 +1,43 @@
1#ifndef ELM_ITEMS_PRIV
2#define ELM_ITEMS_PRIV
3
4#include "Elm_Items.h"
5
6#define ELM_INTERNAL_API_ARGESFSDFEFC
7#include <elm_widget.h>
8
9#ifdef EAPI
10# undef EAPI
11#endif
12
13#ifdef _WIN32
14# ifdef EFL_ECORE_BUILD
15# ifdef DLL_EXPORT
16# define EAPI __declspec(dllexport)
17# else
18# define EAPI
19# endif /* ! DLL_EXPORT */
20# else
21# define EAPI __declspec(dllimport)
22# endif /* ! EFL_ECORE_BUILD */
23#else
24# ifdef __GNUC__
25# if __GNUC__ >= 4
26# define EAPI __attribute__ ((visibility("default")))
27# else
28# define EAPI
29# endif
30# else
31# define EAPI
32# endif
33#endif /* ! _WIN32 */
34
35
36extern int log_domain;
37
38#define CRI(...) EINA_LOG_DOM_CRIT(log_domain, __VA_ARGS__)
39#define ERR(...) EINA_LOG_DOM_ERR(log_domain, __VA_ARGS__)
40#define INF(...) EINA_LOG_DOM_INFO(log_domain, __VA_ARGS__)
41#define DBG(...) EINA_LOG_DOM_DBG(log_domain, __VA_ARGS__)
42
43#endif \ No newline at end of file
diff --git a/src/lib/tree/CMakeLists.txt b/src/lib/tree/CMakeLists.txt
new file mode 100644
index 0000000..a711f26
--- /dev/null
+++ b/src/lib/tree/CMakeLists.txt
@@ -0,0 +1,44 @@
1set(THEME_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/share/elm_ext/")
2
3set(THEME_PATH_DEFINITION THEME_PATH="${THEME_INSTALL_PATH}")
4
5LIST(APPEND ETREE_FILES
6 efl_compare.c
7 efl_compare.eo.h
8 efl_compare.eo.x
9 efl_tree_base.eo.x
10 efl_tree_base.eo.h
11 efl_tree_base.c
12 )
13
14string(REPLACE "\n" "" EOLIAN_EO_DIR_WITHOUT_NEWLINE
15"${EOLIAN_EO_DIR}")
16
17file(GLOB_RECURSE files "*.eo")
18
19foreach(filename ${files})
20add_custom_command(
21 OUTPUT ${filename}.x
22 COMMAND eolian_gen -I ${EOLIAN_EO_DIR_WITHOUT_NEWLINE} --gc --eo -o ${filename}.x ${filename}
23 DEPENDS ${filename}
24)
25
26add_custom_command(
27 OUTPUT ${filename}.h
28 COMMAND eolian_gen -I ${EOLIAN_EO_DIR_WITHOUT_NEWLINE} --gh --eo -o ${filename}.h ${filename}
29 DEPENDS ${filename}
30)
31
32endforeach()
33
34add_library(etree SHARED ${ETREE_FILES})
35
36include_directories(
37 ${EINA_INCLUDE_DIRS}
38 ${EO_INCLUDE_DIRS}
39 ${ELEMENTARY_INCLUDE_DIRS}
40)
41
42target_link_libraries(etree
43 ${ELEMENTARY_LIRBRARIES}
44) \ No newline at end of file
diff --git a/src/lib/tree/Graph.h b/src/lib/tree/Graph.h
new file mode 100644
index 0000000..95e1da0
--- /dev/null
+++ b/src/lib/tree/Graph.h
@@ -0,0 +1,10 @@
1#ifndef GRAPH_H
2#define GRAPH_H
3
4#include <Eina.h>
5#include <Eo.h>
6
7#include "efl_tree_base.eo.h"
8#include "efl_compare.eo.h"
9
10#endif \ No newline at end of file
diff --git a/src/lib/tree/efl_compare.c b/src/lib/tree/efl_compare.c
new file mode 100644
index 0000000..a065486
--- /dev/null
+++ b/src/lib/tree/efl_compare.c
@@ -0,0 +1,3 @@
1#include "graph_priv.h"
2
3#include "efl_compare.eo.x" \ No newline at end of file
diff --git a/src/lib/tree/efl_compare.eo b/src/lib/tree/efl_compare.eo
new file mode 100644
index 0000000..07c9606
--- /dev/null
+++ b/src/lib/tree/efl_compare.eo
@@ -0,0 +1,10 @@
1interface Efl.Compare {
2 methods {
3 compare {
4 params {
5 data : const(void)*;
6 }
7 return : int;
8 }
9 }
10} \ No newline at end of file
diff --git a/src/lib/tree/efl_tree_base.c b/src/lib/tree/efl_tree_base.c
new file mode 100644
index 0000000..fe80a4d
--- /dev/null
+++ b/src/lib/tree/efl_tree_base.c
@@ -0,0 +1,266 @@
1#include "graph_priv.h"
2
3typedef struct {
4 Eina_List *children;
5 Eo *next;
6 Eo *prev;
7 Eo* good;
8} Efl_Tree_Base_Data;
9
10static Eina_Bool
11_child_removed(void *data, Eo *obj, const Eo_Event_Description2 *event EINA_UNUSED, void *event_info EINA_UNUSED)
12{
13 eo_do(data, efl_tree_base_remove(obj));
14 return EO_CALLBACK_CONTINUE;
15}
16
17static Eina_Bool
18_child_changes(void *data, Eo *obj, const Eo_Event_Description2 *event, void *event_info)
19{
20 Efl_Tree_Update ev;
21
22 if (event == EFL_TREE_BASE_EVENT_CHILDREN_DEL_DIRECT)
23 {
24 ev.parent = obj;
25 ev.child = event_info;
26 eo_do(data, eo_event_callback_call(EFL_TREE_BASE_EVENT_CHILDREN_DEL_RECURSIVE, &ev));
27
28 }
29 else if (event == EFL_TREE_BASE_EVENT_CHILDREN_ADD_DIRECT)
30 {
31 ev.parent = obj;
32 ev.child = event_info;
33 eo_do(data, eo_event_callback_call(EFL_TREE_BASE_EVENT_CHILDREN_ADD_RECURSIVE, &ev));
34
35 }
36 else if (event == EFL_TREE_BASE_EVENT_CHILDREN_ADD_RECURSIVE || event == EFL_TREE_BASE_EVENT_CHILDREN_DEL_RECURSIVE)
37 {
38 eo_do(data, eo_event_callback_call(event, event_info));
39 }
40 return EO_CALLBACK_CONTINUE;
41}
42
43static void
44_child_subscribe(Eo *obj, Efl_Tree_Base *item)
45{
46 eo_do(item, eo_event_callback_add(EO_BASE_EVENT_DEL, _child_removed, obj);
47 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_ADD_RECURSIVE, _child_changes, obj);
48 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_ADD_DIRECT, _child_changes, obj);
49 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_DEL_RECURSIVE, _child_changes, obj);
50 eo_event_callback_add(EFL_TREE_BASE_EVENT_CHILDREN_DEL_DIRECT, _child_changes, obj);
51 );
52}
53static void
54_child_unsubscribe(Eo *obj, Efl_Tree_Base *item)
55{
56 eo_do(item, eo_event_callback_del(EO_BASE_EVENT_DEL, _child_removed, obj);
57 eo_event_callback_del(EFL_TREE_BASE_EVENT_CHILDREN_ADD_RECURSIVE, _child_changes, obj);
58 eo_event_callback_del(EFL_TREE_BASE_EVENT_CHILDREN_ADD_DIRECT, _child_changes, obj);
59 eo_event_callback_del(EFL_TREE_BASE_EVENT_CHILDREN_DEL_RECURSIVE, _child_changes, obj);
60 eo_event_callback_del(EFL_TREE_BASE_EVENT_CHILDREN_DEL_DIRECT, _child_changes, obj);
61 );
62}
63EOLIAN static Eina_List *
64_efl_tree_base_children(Eo *obj EINA_UNUSED, Efl_Tree_Base_Data *pd, Eina_Bool recursive)
65{
66 if (!recursive)
67 {
68 return pd->children;
69 }
70 else
71 {
72 Eina_List *node, *node2, *result = NULL;
73 Efl_Tree_Base *it, *child;
74
75 EINA_LIST_FOREACH(pd->children, node, it)
76 {
77 Eina_List *child_children;
78
79 eo_do(it, child_children = efl_tree_base_children(EINA_TRUE));
80
81 //merge child_children into result
82 EINA_LIST_FOREACH(child_children, node2, child)
83 {
84 //
85 result = eina_list_append(result, child);
86 }
87 result = eina_list_append(result, it);
88 }
89 return result;
90 }
91}
92
93static void
94_update_relatives(Eo *p1, Eo *zero, Eo *p2)
95{
96 Efl_Tree_Base_Data *pd1;
97 Efl_Tree_Base_Data *pdzero;
98 Efl_Tree_Base_Data *pd2;
99
100 if (p1)
101 pd1 = eo_data_scope_get(p1, EFL_TREE_BASE_CLASS);
102 pdzero = eo_data_scope_get(zero, EFL_TREE_BASE_CLASS);
103 if (p2)
104 pd2 = eo_data_scope_get(p2, EFL_TREE_BASE_CLASS);
105
106 if (p1)
107 pd1->next = zero;
108 pdzero->prev = p1;
109 pdzero->next = p2;
110 if (p2)
111 pd2->prev = zero;
112}
113
114static inline void
115_update_relatives_list(Eina_List *p1, Eina_List *zero, Eina_List *p2)
116{
117 _update_relatives(eina_list_data_get(p1), eina_list_data_get(zero), eina_list_data_get(p2));
118}
119
120EOLIAN static void
121_efl_tree_base_remove(Eo *obj, Efl_Tree_Base_Data *pd, Efl_Tree_Base *item)
122{
123 Eina_List *node;
124
125 _child_unsubscribe(obj, item);
126 //search this item
127 node = eina_list_data_find_list(pd->children, item);
128 //update the other items
129 _update_relatives_list(eina_list_prev(node), node, eina_list_next(node));
130 //remove it
131 pd->children = eina_list_remove(pd->children, item);
132 //call for the change
133 eo_do(obj, eo_event_callback_call(EFL_TREE_BASE_EVENT_CHILDREN_DEL_DIRECT, item));
134}
135
136EOLIAN static void
137_efl_tree_base_append(Eo *obj, Efl_Tree_Base_Data *pd, Efl_Tree_Base *item, Efl_Tree_Base *relative)
138{
139 //subscribe to changes
140 _child_subscribe(obj, item);
141
142 if (relative)
143 {
144 Eina_List *rel;
145
146 //if we have a relative, find it
147 rel = eina_list_data_find_list(pd->children, relative);
148 if (!rel)
149 return;
150 pd->children = eina_list_append_relative_list(pd->children, item, rel);
151 _update_relatives_list(rel, eina_list_next(rel), eina_list_next(eina_list_next(rel)));
152 }
153 else
154 {
155 pd->children = eina_list_append(pd->children, item);
156 _update_relatives_list(eina_list_prev(eina_list_last(pd->children)), eina_list_last(pd->children), NULL);
157 }
158 eo_do(obj, eo_event_callback_call(EFL_TREE_BASE_EVENT_CHILDREN_ADD_DIRECT, item));
159}
160
161EOLIAN static void
162_efl_tree_base_prepend(Eo *obj EINA_UNUSED, Efl_Tree_Base_Data *pd, Efl_Tree_Base *item, Efl_Tree_Base *relative)
163{
164 _child_subscribe(obj, item);
165 if (relative)
166 {
167 Eina_List *rel;
168
169 rel = eina_list_data_find_list(pd->children, relative);
170 if (!rel)
171 return;
172 pd->children = eina_list_prepend_relative_list(pd->children, item, rel);
173 _update_relatives_list(eina_list_prev(eina_list_prev(rel)), eina_list_prev(rel), rel);
174 }
175 else
176 {
177 _update_relatives(NULL, item, eina_list_data_get(pd->children));
178 pd->children = eina_list_prepend(pd->children, item);
179 }
180 eo_do(obj, eo_event_callback_call(EFL_TREE_BASE_EVENT_CHILDREN_ADD_DIRECT, item));
181}
182
183static int
184_compare_func(const void *data1, const void *data2)
185{
186 int res;
187 Eo *c1;
188 Eo *c2;
189
190 eo_do(data1, c1 = efl_tree_base_carry_get());
191 eo_do(data2, c2 = efl_tree_base_carry_get());
192
193 eo_do(c1, res = efl_compare(c2));
194
195 return res;
196}
197
198EOLIAN static void
199_efl_tree_base_insert_sorted(Eo *obj EINA_UNUSED, Efl_Tree_Base_Data *pd, Efl_Tree_Base *item)
200{
201 Eina_List *itemlist;
202
203 //subscribe to events
204 _child_subscribe(obj, item);
205
206 //insert
207 pd->children = eina_list_sorted_insert(pd->children, _compare_func, item);
208
209 //search where it was inserted
210 itemlist = eina_list_data_find_list(pd->children, item);
211
212 //update the relatives of the neighbours
213 _update_relatives_list(eina_list_prev(itemlist), itemlist, eina_list_next(itemlist));
214
215 //populate the change
216 eo_do(obj, eo_event_callback_call(EFL_TREE_BASE_EVENT_CHILDREN_ADD_DIRECT, item));
217}
218
219EOLIAN static void
220_efl_tree_base_carry_set(Eo *obj EINA_UNUSED, Efl_Tree_Base_Data *pd, void *good)
221{
222 if (pd->good)
223 eo_do(pd->good, eo_wref_del(&pd->good));
224 pd->good = good;
225 eo_do(pd->good, eo_wref_add(&pd->good));
226}
227
228EOLIAN static void *
229_efl_tree_base_carry_get(Eo *obj EINA_UNUSED, Efl_Tree_Base_Data *pd)
230{
231 return pd->good;
232}
233
234EOLIAN static Efl_Tree_Base*
235_efl_tree_base_next_get(Eo *obj EINA_UNUSED, Efl_Tree_Base_Data *pd)
236{
237 return pd->next;
238}
239
240EOLIAN static Efl_Tree_Base*
241_efl_tree_base_prev_get(Eo *obj EINA_UNUSED, Efl_Tree_Base_Data *pd)
242{
243 return pd->prev;
244}
245
246EOLIAN static void
247_efl_tree_base_eo_base_destructor(Eo *obj, Efl_Tree_Base_Data *pd)
248{
249 Eina_List *children = eina_list_clone(pd->children);
250 Eina_List *node;
251 Efl_Tree_Base *child;
252
253 if (pd->good)
254 eo_do(pd->good, eo_wref_del(&pd->good));
255
256 EINA_LIST_FOREACH(children, node, child)
257 {
258 eo_do(obj, efl_tree_base_remove(child));
259 eo_del(child);
260 }
261
262 eo_do_super(obj, EFL_TREE_BASE_CLASS, eo_destructor());
263}
264
265
266#include "efl_tree_base.eo.x" \ No newline at end of file
diff --git a/src/lib/tree/efl_tree_base.eo b/src/lib/tree/efl_tree_base.eo
new file mode 100644
index 0000000..c4129d9
--- /dev/null
+++ b/src/lib/tree/efl_tree_base.eo
@@ -0,0 +1,84 @@
1struct Efl.Tree.Update {
2 parent : Efl.Tree.Base*;
3 child : Efl.Tree.Base*;
4}
5
6class Efl.Tree.Base(Eo.Base) {
7 methods {
8 append {
9 [[Appends item as child after the relative node
10
11 If relative is not found this call will fail.
12 If relative is NULL, the item will be added at the end]]
13 params {
14 item : Efl.Tree.Base*;
15 relative: Efl.Tree.Base*;
16 }
17 }
18 prepend {
19 [[Prepends the item as child before the relative node
20
21 If relative is not found this call will fail.
22 If relative is NULL, the item will be added at the beginning]]
23 params {
24 item: Efl.Tree.Base*;
25 relative: Efl.Tree.Base*;
26 }
27 }
28 insert_sorted {
29 [[Will insert the item into the correct position in the children
30
31 If you use this function. ALL carrys of the children need to implement efl.compare]]
32 params {
33 item: Efl.Tree.Base*; [[Need to implement efl.compare]]
34 }
35 }
36 remove {
37 [[Remove the given item from the children]]
38 params {
39 item : Efl.Tree.Base*;
40 }
41 }
42 children {
43 [[Get the list of children of this tree item]]
44 params {
45 @in recursive : bool; [[if true all children which are somewhere lower in this tree will be returned]]
46 }
47
48 return : list<Efl.Tree.Base*>*;
49 }
50 @property carry {
51 [[The pointer which is associated with this tree node]]
52 values {
53 good : void*;
54 }
55 }
56 @property next {
57 [[Get the node which is next to this one. NULL if there is none]]
58 get {
59
60 }
61 values {
62 prev : Efl.Tree.Base*;
63 }
64 }
65 @property prev {
66 [[Get the node which is before this one. NULL if there is none]]
67 get {
68
69 }
70 values {
71 prev : Efl.Tree.Base*;
72 }
73 }
74 }
75 implements {
76 Eo.Base.destructor;
77 }
78 events {
79 children,add,direct : Efl.Tree.Base*; [[A child was added to this tree]]
80 children,add,recursive : Efl.Tree.Update*; [[A child was added to a tree, which is a child of this tree item ]]
81 children,del,direct : Efl.Tree.Base*; [[A child was deleted from this tree]]
82 children,del,recursive : Efl.Tree.Update*; [[A child was deleted from a tree, which is a child of this tree item ]]
83 }
84} \ No newline at end of file
diff --git a/src/lib/tree/graph_priv.h b/src/lib/tree/graph_priv.h
new file mode 100644
index 0000000..2abe1d4
--- /dev/null
+++ b/src/lib/tree/graph_priv.h
@@ -0,0 +1,33 @@
1#ifndef GRAPH_PRIV_H
2#define GRAPH_PRIV_H
3
4#include <Eo.h>
5#include "Graph.h"
6
7#ifdef EAPI
8# undef EAPI
9#endif
10
11#ifdef _WIN32
12# ifdef EFL_ECORE_BUILD
13# ifdef DLL_EXPORT
14# define EAPI __declspec(dllexport)
15# else
16# define EAPI
17# endif /* ! DLL_EXPORT */
18# else
19# define EAPI __declspec(dllimport)
20# endif /* ! EFL_ECORE_BUILD */
21#else
22# ifdef __GNUC__
23# if __GNUC__ >= 4
24# define EAPI __attribute__ ((visibility("default")))
25# else
26# define EAPI
27# endif
28# else
29# define EAPI
30# endif
31#endif /* ! _WIN32 */
32
33#endif \ No newline at end of file
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
new file mode 100644
index 0000000..e0aa966
--- /dev/null
+++ b/src/test/CMakeLists.txt
@@ -0,0 +1,2 @@
1add_subdirectory(list)
2add_subdirectory(tree) \ No newline at end of file
diff --git a/src/test/list/CMakeLists.txt b/src/test/list/CMakeLists.txt
new file mode 100644
index 0000000..dee4f1b
--- /dev/null
+++ b/src/test/list/CMakeLists.txt
@@ -0,0 +1,17 @@
1include_directories(
2 ${ELEMENTARY_INCLUDE_DIRS}
3 ../../lib/items/
4 ../../lib/tree/
5)
6
7add_executable(list list.c)
8
9target_link_libraries (list
10 ${EFL_LIBRARIES}
11 ${EVAS_LIBRARIES}
12 ${EO_LIBRARIES}
13 ${EFREET_MIME_LIBRARIES}
14 ${ECORE_LIBRARIES}
15 ${ELEMENTARY_LIBRARIES}
16 elm_items
17) \ No newline at end of file
diff --git a/src/test/list/list.c b/src/test/list/list.c
new file mode 100644
index 0000000..72ed988
--- /dev/null
+++ b/src/test/list/list.c
@@ -0,0 +1,85 @@
1#define EFL_BETA_API_SUPPORT
2#define EFL_EO_API_SUPPORT
3
4#include <Efl.h>
5#include <Elementary.h>
6#include <Elm_Items.h>
7
8static void
9on_done(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
10{
11 // quit the mainloop (elm_run function will return)
12 elm_exit();
13}
14
15static Eina_Bool
16_realize(void *data, Eo *obj, const Eo_Event_Description2 *desc, void *event)
17{
18 Eo *btn;
19 struct timespec tim;
20 btn = elm_button_add(obj);
21
22 eo_do(obj, elm_items_item_content_set(btn));
23 evas_object_color_set(btn, 30, 30, 30, 30);
24
25 tim.tv_sec = 0;
26 tim.tv_nsec = 5000000;
27 nanosleep(&tim, NULL);
28 evas_object_show(btn);
29
30 return EINA_TRUE;
31}
32
33static Eina_Bool
34_unrealize(void *data, Eo *obj, const Eo_Event_Description2 *desc, void *event)
35{
36 Eo *content;
37
38 eo_do(obj, content = elm_items_item_content_get();
39 elm_items_item_content_set(NULL););
40 evas_object_hide(content);
41
42 return EINA_TRUE;
43}
44
45EAPI_MAIN int
46elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
47{
48 Evas_Object *win, *ic, *bx;
49
50 elm_need_ethumb();
51 elm_need_efreet();
52
53 elm_items_init();
54
55 win = elm_win_util_standard_add("efm", "efm - Jesus");
56 evas_object_smart_callback_add(win, "delete,request", on_done, NULL);
57
58 bx = eo_add(ELM_ITEMS_LIST_CLASS, win);
59
60 {
61 Eo *root, *it;
62 Eo *item;
63
64 eo_do(bx, root = elm_items_display_tree_get());
65
66 for(int i = 0; i < 5000; i++)
67 {
68 item = eo_add(ELM_ITEMS_ITEM_CLASS, bx);
69 eo_do(item, eo_event_callback_add(ELM_ITEMS_ITEM_EVENT_REALIZE, _realize, NULL);
70 eo_event_callback_add(ELM_ITEMS_ITEM_EVENT_UNREALIZE, _unrealize, NULL));
71 eo_do(item, it = elm_items_item_get());
72 eo_do(root, efl_tree_base_append(it, NULL));
73 evas_object_show(item);
74 }
75 }
76 evas_object_show(bx);
77
78 elm_win_resize_object_add(win, bx);
79 evas_object_resize(win, 200,200);
80 evas_object_show(win);
81
82 elm_run();
83 return 0;
84}
85ELM_MAIN()
diff --git a/src/test/tree/CMakeLists.txt b/src/test/tree/CMakeLists.txt
new file mode 100644
index 0000000..619d793
--- /dev/null
+++ b/src/test/tree/CMakeLists.txt
@@ -0,0 +1,14 @@
1include_directories(
2 ${ELEMENTARY_INCLUDE_DIRS}
3 ../../lib/tree/
4)
5
6add_executable(tree_test tree.c)
7
8target_link_libraries (tree_test
9 ${EO_LIBRARIES}
10 etree
11 ${Check_LIBRARIES}
12)
13
14add_test(tree_test tree_test)
diff --git a/src/test/tree/tree.c b/src/test/tree/tree.c
new file mode 100644
index 0000000..5d2686f
--- /dev/null
+++ b/src/test/tree/tree.c
@@ -0,0 +1,113 @@
1#define EFL_BETA_API_SUPPORT
2#define EFL_EO_API_SUPPORT
3
4#include <Eo.h>
5#include <Graph.h>
6#include <check.h>
7
8static void
9_rec_add(Efl_Tree_Base *root, int depth)
10{
11 Efl_Tree_Base *child;
12
13 if (depth == 0) return;
14
15 for (int i = 0; i < 10; i++)
16 {
17 child = eo_add(EFL_TREE_BASE_CLASS, NULL);
18
19 _rec_add(child, depth - 1);
20 eo_do(root, efl_tree_base_append(child, NULL));
21 }
22}
23
24START_TEST(tree_creation_time)
25{
26 eo_init();
27 Efl_Tree_Base *root;
28 Eina_List *children;
29 int i = 0;
30 root = eo_add(EFL_TREE_BASE_CLASS, NULL);
31
32 _rec_add(root, 2);
33
34 eo_do(root, children = efl_tree_base_children(EINA_TRUE));
35 {
36 Eina_List *node;
37
38 EINA_LIST_FOREACH(children, node, root)
39 {
40 i++;
41 }
42 }
43 ck_assert_int_eq(i, 10+10*10);
44 eo_shutdown();
45}
46END_TEST
47START_TEST(next_prev)
48{
49 eo_init();
50 Efl_Tree_Base *root;
51 Efl_Tree_Base* child[8];
52
53 root = eo_add(EFL_TREE_BASE_CLASS, NULL);
54
55 for (int i = 0; i < 8; i++)
56 {
57 child[i] = eo_add(EFL_TREE_BASE_CLASS, root);
58 eo_do(root, efl_tree_base_append(child[i], NULL));
59 }
60
61 for (int i = 1; i < 7; i++)
62 {
63 eo_do(child[i],
64 ck_assert_ptr_eq(child[i + 1], efl_tree_base_next_get());
65 ck_assert_ptr_eq(child[i - 1], efl_tree_base_prev_get());
66 );
67 }
68 eo_do(child[0],
69 ck_assert_ptr_eq(child[1], efl_tree_base_next_get());
70 ck_assert_ptr_eq(NULL, efl_tree_base_prev_get());
71 );
72 eo_do(child[7],
73 ck_assert_ptr_eq(NULL, efl_tree_base_next_get());
74 ck_assert_ptr_eq(child[6], efl_tree_base_prev_get());
75 );
76
77
78 eo_shutdown();
79}
80END_TEST
81Suite * tree_suite(void)
82{
83 Suite *s;
84 TCase *tc_core;
85
86 s = suite_create("tree");
87
88 /* Core test case */
89 tc_core = tcase_create("tree");
90
91 tcase_set_timeout(tc_core, 7);
92 tcase_add_test(tc_core, tree_creation_time);
93 tcase_add_test(tc_core, next_prev);
94
95 suite_add_tcase(s, tc_core);
96
97 return s;
98}
99
100int main(void)
101{
102 int number_failed;
103 Suite *s;
104 SRunner *sr;
105
106 s = tree_suite();
107 sr = srunner_create(s);
108
109 srunner_run_all(sr, CK_NORMAL);
110 number_failed = srunner_ntests_failed(sr);
111 srunner_free(sr);
112 return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
113 } \ No newline at end of file