summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLarry Lira <larry@expertisesolutions.com.br>2019-01-24 17:07:07 -0200
committerLarry Lira <larry@expertisesolutions.com.br>2019-01-31 20:22:42 -0200
commit7e5dff70813e1f02cbfca5c0d47e1e91b335dc6f (patch)
tree193f3a0dec6c40a7d82b23cfa45f9a59246c133c
parent0d138acc76c26d7e648bb997c2db2945a91a229b (diff)
Efl.Ui.Tree_View: added new MVVM asynchronous widgetdevs/larrylira/treeview
new classes added: Efl.Ui.Tree_View Efl.Ui.Tree_View_Layouter Efl.Ui.Tree_Factory added tree_view_example_1 in elementary example
-rw-r--r--data/elementary/themes/edc/efl/list.edc4
-rw-r--r--src/Makefile_Elementary.am14
-rw-r--r--src/examples/elementary.mk6
-rw-r--r--src/examples/elementary/.gitignore1
-rw-r--r--src/examples/elementary/tree_view_example_1.c129
-rw-r--r--src/lib/elementary/Elementary.h7
-rw-r--r--src/lib/elementary/efl_ui.eot2
-rw-r--r--src/lib/elementary/efl_ui_tree_factory.c93
-rw-r--r--src/lib/elementary/efl_ui_tree_factory.eo26
-rw-r--r--src/lib/elementary/efl_ui_tree_view.c1158
-rw-r--r--src/lib/elementary/efl_ui_tree_view.eo96
-rw-r--r--src/lib/elementary/efl_ui_tree_view_layouter.c722
-rw-r--r--src/lib/elementary/efl_ui_tree_view_layouter.eo10
-rw-r--r--src/lib/elementary/efl_ui_tree_view_model.eo68
-rw-r--r--src/lib/elementary/efl_ui_tree_view_pan.eo12
-rw-r--r--src/lib/elementary/efl_ui_tree_view_private.h73
-rw-r--r--src/lib/elementary/efl_ui_tree_view_relayout.eo30
-rw-r--r--src/lib/elementary/efl_ui_tree_view_seg_array.c469
-rw-r--r--src/lib/elementary/efl_ui_tree_view_seg_array.h50
-rw-r--r--src/lib/elementary/efl_ui_tree_view_seg_array_depth_model.c79
-rw-r--r--src/lib/elementary/efl_ui_tree_view_seg_array_depth_model.eo11
-rw-r--r--src/lib/elementary/meson.build14
22 files changed, 3072 insertions, 2 deletions
diff --git a/data/elementary/themes/edc/efl/list.edc b/data/elementary/themes/edc/efl/list.edc
index ca3c5b47ff..a551f1c7aa 100644
--- a/data/elementary/themes/edc/efl/list.edc
+++ b/data/elementary/themes/edc/efl/list.edc
@@ -6,6 +6,10 @@ group { "efl/list_view";
6 inherit: "efl/list"; 6 inherit: "efl/list";
7} 7}
8 8
9group { "efl/tree_view";
10 inherit: "efl/list";
11}
12
9group { "efl/list_item"; 13group { "efl/list_item";
10 data.item: "selectraise" "on"; 14 data.item: "selectraise" "on";
11 data.item: "focusraise" "on"; 15 data.item: "focusraise" "on";
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index 2ed29dd393..a68dc0a1ec 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -81,6 +81,9 @@ elm_public_eolian_files = \
81 lib/elementary/efl_ui_list_view.eo \ 81 lib/elementary/efl_ui_list_view.eo \
82 lib/elementary/efl_ui_list_view_model.eo \ 82 lib/elementary/efl_ui_list_view_model.eo \
83 lib/elementary/efl_ui_list_view_pan.eo \ 83 lib/elementary/efl_ui_list_view_pan.eo \
84 lib/elementary/efl_ui_tree_view.eo \
85 lib/elementary/efl_ui_tree_view_model.eo \
86 lib/elementary/efl_ui_tree_view_pan.eo \
84 lib/elementary/efl_ui_item.eo \ 87 lib/elementary/efl_ui_item.eo \
85 lib/elementary/efl_ui_list_item.eo \ 88 lib/elementary/efl_ui_list_item.eo \
86 lib/elementary/efl_ui_list_default_item_part_icon.eo \ 89 lib/elementary/efl_ui_list_default_item_part_icon.eo \
@@ -180,6 +183,10 @@ elm_private_eolian_files = \
180 lib/elementary/efl_ui_homogeneous_model.eo \ 183 lib/elementary/efl_ui_homogeneous_model.eo \
181 lib/elementary/efl_ui_exact_model.eo \ 184 lib/elementary/efl_ui_exact_model.eo \
182 lib/elementary/efl_ui_average_model.eo \ 185 lib/elementary/efl_ui_average_model.eo \
186 lib/elementary/efl_ui_tree_view_seg_array_depth_model.eo \
187 lib/elementary/efl_ui_tree_view_relayout.eo \
188 lib/elementary/efl_ui_tree_view_layouter.eo \
189 lib/elementary/efl_ui_tree_factory.eo \
183 $(NULL) 190 $(NULL)
184 191
185# Legacy classes - not part of public EO API 192# Legacy classes - not part of public EO API
@@ -431,6 +438,7 @@ includesunstable_HEADERS = \
431 lib/elementary/efl_ui_grid_private.h \ 438 lib/elementary/efl_ui_grid_private.h \
432 lib/elementary/efl_ui_list_view_private.h \ 439 lib/elementary/efl_ui_list_view_private.h \
433 lib/elementary/efl_ui_list_view_seg_array.h \ 440 lib/elementary/efl_ui_list_view_seg_array.h \
441 lib/elementary/efl_ui_tree_view_private.h \
434 lib/elementary/elm_widget_web.h \ 442 lib/elementary/elm_widget_web.h \
435 lib/elementary/efl_ui_clock.h \ 443 lib/elementary/efl_ui_clock.h \
436 lib/elementary/elm_code.h \ 444 lib/elementary/elm_code.h \
@@ -661,6 +669,7 @@ includesub_HEADERS = \
661 lib/elementary/efl_ui_video.h \ 669 lib/elementary/efl_ui_video.h \
662 lib/elementary/efl_ui_video_eo.h \ 670 lib/elementary/efl_ui_video_eo.h \
663 lib/elementary/efl_ui_video_legacy.h \ 671 lib/elementary/efl_ui_video_legacy.h \
672 lib/elementary/efl_ui_tree_view_seg_array.h \
664 lib/elementary/elm_view_list.h \ 673 lib/elementary/elm_view_list.h \
665 lib/elementary/elm_view_form.h \ 674 lib/elementary/elm_view_form.h \
666 lib/elementary/elm_web.h \ 675 lib/elementary/elm_web.h \
@@ -865,7 +874,12 @@ lib_elementary_libelementary_la_SOURCES = \
865 lib/elementary/efl_ui_list_view.c \ 874 lib/elementary/efl_ui_list_view.c \
866 lib/elementary/efl_ui_list_view_precise_layouter.c \ 875 lib/elementary/efl_ui_list_view_precise_layouter.c \
867 lib/elementary/efl_ui_list_view_seg_array.c \ 876 lib/elementary/efl_ui_list_view_seg_array.c \
877 lib/elementary/efl_ui_tree_view.c \
878 lib/elementary/efl_ui_tree_view_layouter.c \
879 lib/elementary/efl_ui_tree_view_seg_array.c \
880 lib/elementary/efl_ui_tree_view_seg_array_depth_model.c \
868 lib/elementary/efl_ui_layout_factory.c \ 881 lib/elementary/efl_ui_layout_factory.c \
882 lib/elementary/efl_ui_tree_factory.c \
869 lib/elementary/efl_ui_scroller.c \ 883 lib/elementary/efl_ui_scroller.c \
870 lib/elementary/efl_ui_scroll_manager.c \ 884 lib/elementary/efl_ui_scroll_manager.c \
871 lib/elementary/efl_ui_pan.c \ 885 lib/elementary/efl_ui_pan.c \
diff --git a/src/examples/elementary.mk b/src/examples/elementary.mk
index 0d817258dc..604cecd5f0 100644
--- a/src/examples/elementary.mk
+++ b/src/examples/elementary.mk
@@ -125,7 +125,8 @@ elementary/efl_ui_list_view_example_2.c \
125elementary/efl_ui_list_view_example_3.c \ 125elementary/efl_ui_list_view_example_3.c \
126elementary/efl_canvas_layout_text.c \ 126elementary/efl_canvas_layout_text.c \
127elementary/efl_ui_theme_example_01.c \ 127elementary/efl_ui_theme_example_01.c \
128elementary/efl_ui_theme_example_02.c 128elementary/efl_ui_theme_example_02.c \
129elementary/tree_view_example_1.c
129 130
130ELM_SRCS += \ 131ELM_SRCS += \
131elementary/bg_cxx_example_01.cc \ 132elementary/bg_cxx_example_01.cc \
@@ -344,7 +345,8 @@ elementary/efl_ui_list_view_example_2 \
344elementary/efl_ui_list_view_example_3 \ 345elementary/efl_ui_list_view_example_3 \
345elementary/efl_canvas_layout_text \ 346elementary/efl_canvas_layout_text \
346elementary/efl_ui_theme_example_01 \ 347elementary/efl_ui_theme_example_01 \
347elementary/efl_ui_theme_example_02 348elementary/efl_ui_theme_example_02 \
349elementary/tree_view_example_1
348#benchmark3d 350#benchmark3d
349#sphere-hunter 351#sphere-hunter
350 352
diff --git a/src/examples/elementary/.gitignore b/src/examples/elementary/.gitignore
index 54d71c14a0..1ac5db594b 100644
--- a/src/examples/elementary/.gitignore
+++ b/src/examples/elementary/.gitignore
@@ -63,6 +63,7 @@
63/list_example_02 63/list_example_02
64/list_example_03 64/list_example_03
65/efl_ui_list_example_1 65/efl_ui_list_example_1
66/tree_view_example_1
66/efl_ui_view_list_example_1 67/efl_ui_view_list_example_1
67/efl_ui_view_list_example_2 68/efl_ui_view_list_example_2
68/efl_ui_view_list_example_3 69/efl_ui_view_list_example_3
diff --git a/src/examples/elementary/tree_view_example_1.c b/src/examples/elementary/tree_view_example_1.c
new file mode 100644
index 0000000000..aadf601b95
--- /dev/null
+++ b/src/examples/elementary/tree_view_example_1.c
@@ -0,0 +1,129 @@
1// gcc -o tree_view_example_1 tree_view_example_1.c `pkg-config --cflags --libs elementary`
2
3#ifdef HAVE_CONFIG_H
4# include "config.h"
5#else
6# define EFL_BETA_API_SUPPORT 1
7# define EFL_EO_API_SUPPORT 1
8#endif
9
10#include <Elementary.h>
11#include <Efl.h>
12#include <Eio.h>
13#include <stdio.h>
14#include <time.h>
15
16#define NUM_ITEMS 10
17
18static void
19_realized_cb(void *data EINA_UNUSED, const Efl_Event *event)
20{
21 char *depth, *name;
22 Eina_Value *vd, *vn;
23 Efl_Ui_Tree_View_Item_Event *ie = event->info;
24 if (!ie->child) return;
25
26 vd = efl_model_property_get(ie->child, "depth");
27 vn = efl_model_property_get(ie->child, "name");
28 depth = eina_value_to_string(vd);
29 name = eina_value_to_string(vn);
30 eina_value_free(vd);
31 eina_value_free(vn);
32
33 printf("realize item=%s depth=%s\n", name, depth);
34 free(name);
35 free(depth);
36}
37
38static Efl_Model*
39_child_add(Efl_Generic_Model *parent, Eina_Value *value, const char *msg)
40{
41 Efl_Generic_Model *model;
42
43 model = efl_model_child_add(parent);
44 if (model)
45 {
46 eina_value_set(value, msg);
47 efl_model_property_set(model, "name", value);
48 }
49
50 return model;
51}
52
53static void
54_children_add(Efl_Generic_Model *parent, Eina_Value *value, int n, const char *msg)
55{
56 char msgbuf[256];
57 char buff[256];
58 int i;
59
60 if (!parent) return;
61 snprintf(msgbuf, sizeof(msgbuf), " %s - %%i", msg);
62
63 for (i = 0; i < n; ++i)
64 {
65 snprintf(buff, sizeof(buff), msgbuf, i);
66 _children_add(_child_add(parent, value, buff), value, i, buff);
67 }
68}
69
70static Efl_Model*
71_make_model(Eo *win)
72{
73 Efl_Generic_Model *root, *child;
74 Eina_Value vtext;
75 unsigned int i;
76
77 srand(time(NULL));
78 eina_value_setup(&vtext, EINA_VALUE_TYPE_STRING);
79 root = efl_add(EFL_GENERIC_MODEL_CLASS, win);
80 char buf[256];
81
82 for (i = 0; i < (NUM_ITEMS); ++i)
83 {
84 snprintf(buf, sizeof(buf), "Item # %i", i);
85 child = _child_add(root, &vtext, buf);
86 snprintf(buf, sizeof(buf), "|-> Item # %i", i);
87 _children_add(child, &vtext, 1, buf);
88 }
89
90 eina_value_flush(&vtext);
91 return root;
92}
93
94EAPI_MAIN int
95elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
96{
97 Efl_Ui_Layout_Factory *factory;
98 Eo *win, *model, *tree;
99
100 win = elm_win_util_standard_add("viewtree", "ViewTree");
101 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
102
103 elm_win_autodel_set(win, EINA_TRUE);
104
105 model = _make_model(win);
106 factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win);
107 efl_ui_model_connect(factory, "efl.text", "name");
108 efl_ui_layout_factory_theme_config(factory, "list_item", NULL, "default");
109
110 tree = efl_add(EFL_UI_TREE_VIEW_CLASS, win
111 , efl_ui_tree_view_layout_factory_set(efl_added, factory)
112 , efl_ui_view_model_set(efl_added, model)
113 );
114
115 evas_object_size_hint_weight_set(tree, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
116 evas_object_size_hint_align_set(tree, EVAS_HINT_FILL, EVAS_HINT_FILL);
117 efl_event_callback_add(tree, EFL_UI_TREE_VIEW_EVENT_ITEM_REALIZED, _realized_cb, NULL);
118
119 elm_win_resize_object_add(win, tree);
120
121 //showall
122 evas_object_show(tree);
123 evas_object_resize(win, 320, 320);
124 evas_object_show(win);
125
126 elm_run();
127 return 0;
128}
129ELM_MAIN()
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index 5bb8374e3a..8f8a8c815e 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -330,6 +330,7 @@ EAPI void efl_ui_focus_relation_free(Efl_Ui_Focus_Relations *rel);
330# include <efl_ui_slider.eo.h> 330# include <efl_ui_slider.eo.h>
331# include <efl_ui_slider_interval.eo.h> 331# include <efl_ui_slider_interval.eo.h>
332# include <efl_ui_layout_factory.eo.h> 332# include <efl_ui_layout_factory.eo.h>
333# include <efl_ui_tree_factory.eo.h>
333# include <efl_ui_item.eo.h> 334# include <efl_ui_item.eo.h>
334# include <efl_ui_list_item.eo.h> 335# include <efl_ui_list_item.eo.h>
335# include <efl_ui_list_default_item_part_icon.eo.h> 336# include <efl_ui_list_default_item_part_icon.eo.h>
@@ -348,6 +349,12 @@ EAPI void efl_ui_focus_relation_free(Efl_Ui_Focus_Relations *rel);
348# include <efl_ui_list_view_pan.eo.h> 349# include <efl_ui_list_view_pan.eo.h>
349# include <efl_ui_widget_factory.eo.h> 350# include <efl_ui_widget_factory.eo.h>
350# include <efl_ui_caching_factory.eo.h> 351# include <efl_ui_caching_factory.eo.h>
352# include <efl_ui_tree_view_seg_array_depth_model.eo.h>
353# include <efl_ui_tree_view_model.eo.h>
354# include <efl_ui_tree_view_relayout.eo.h>
355# include <efl_ui_tree_view_layouter.eo.h>
356# include <efl_ui_tree_view.eo.h>
357# include <efl_ui_tree_view_pan.eo.h>
351# include <efl_ui_pan.eo.h> 358# include <efl_ui_pan.eo.h>
352# include <efl_ui_scroll_manager.eo.h> 359# include <efl_ui_scroll_manager.eo.h>
353# include <efl_ui_scroller.eo.h> 360# include <efl_ui_scroller.eo.h>
diff --git a/src/lib/elementary/efl_ui.eot b/src/lib/elementary/efl_ui.eot
index ce17980e56..7d3985d0fa 100644
--- a/src/lib/elementary/efl_ui.eot
+++ b/src/lib/elementary/efl_ui.eot
@@ -104,3 +104,5 @@ enum Efl.Ui.Widget_Orientation_Mode
104 104
105/* Types for A11Y (internal/beta API) */ 105/* Types for A11Y (internal/beta API) */
106type @extern Efl.Access.Action_Data: __undefined_type; [[Internal struct for accesssibility.]] 106type @extern Efl.Access.Action_Data: __undefined_type; [[Internal struct for accesssibility.]]
107
108struct Efl_Ui_Tree_View_Seg_Array;
diff --git a/src/lib/elementary/efl_ui_tree_factory.c b/src/lib/elementary/efl_ui_tree_factory.c
new file mode 100644
index 0000000000..b25f6f38f5
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_factory.c
@@ -0,0 +1,93 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Elementary.h>
6#include "elm_priv.h"
7
8#define MY_CLASS EFL_UI_TREE_FACTORY_CLASS
9#define MY_CLASS_NAME "Efl.Ui.Tree_Factory"
10
11typedef struct _Efl_Ui_Tree_Factory_Data
12{
13 Eina_Stringshare *exp_style;
14} Efl_Ui_Tree_Factory_Data;
15
16typedef struct _Efl_Ui_Tree_Factory_Request
17{
18 Efl_Ui_Tree_Factory_Data *pd;
19 Efl_Model *model;
20} Efl_Ui_Tree_Factory_Request;
21
22EOLIAN static void
23_efl_ui_tree_factory_efl_object_destructor(Eo *obj, Efl_Ui_Tree_Factory_Data *pd)
24{
25 eina_stringshare_del(pd->exp_style);
26
27 efl_destructor(efl_super(obj, MY_CLASS));
28}
29
30static Eina_Value
31_efl_ui_tree_factory_connect(Eo *obj, void *data, const Eina_Value value)
32{
33 Efl_Ui_Tree_Factory_Request *r = data;
34 Efl_Ui_Tree_Factory_Data *pd = r->pd;
35 Efl_Model *model = r->model;
36 Efl_Ui_Tree_Factory_Item_Event evt;
37
38 evt.model = model;
39 evt.expandable = EINA_FALSE;
40
41 if (efl_model_children_count_get(model) > 0)
42 evt.expandable = EINA_TRUE;
43
44 efl_event_callback_call(obj, EFL_UI_TREE_FACTORY_EVENT_ITEM_CREATE, &evt);
45
46 if (pd->exp_style && evt.expandable)
47 {
48 Efl_Gfx_Entity *layout;
49 eina_value_pget(&value, &layout);
50 efl_ui_widget_style_set(layout, pd->exp_style);
51 }
52
53 return value;
54}
55
56static void
57_efl_ui_tree_factory_create_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
58{
59 Efl_Ui_Tree_Factory_Request *r = data;
60
61 efl_unref(r->model);
62 free(r);
63}
64
65EOLIAN static Eina_Future *
66_efl_ui_tree_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Tree_Factory_Data *pd
67 , Efl_Model *model, Efl_Gfx_Entity *parent)
68{
69 Efl_Ui_Tree_Factory_Request *r;
70 Eina_Future *f;
71
72 r = calloc(1, sizeof (Efl_Ui_Tree_Factory_Request));
73 if (!r) return efl_loop_future_rejected(obj, ENOMEM);
74
75 r->pd = pd;
76 r->model = efl_ref(model);
77
78 f = efl_ui_factory_create(efl_super(obj, MY_CLASS), model, parent);
79
80 return efl_future_then(obj, f,
81 .success_type = EINA_VALUE_TYPE_OBJECT,
82 .success = _efl_ui_tree_factory_connect,
83 .data = r,
84 .free = _efl_ui_tree_factory_create_cleanup);
85}
86
87EOLIAN static void
88_efl_ui_tree_factory_expandable_style_set(Eo *obj EINA_UNUSED, Efl_Ui_Tree_Factory_Data *pd, const char *style)
89{
90 eina_stringshare_replace(&pd->exp_style, style);
91}
92
93#include "efl_ui_tree_factory.eo.c"
diff --git a/src/lib/elementary/efl_ui_tree_factory.eo b/src/lib/elementary/efl_ui_tree_factory.eo
new file mode 100644
index 0000000000..3e3d2c393f
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_factory.eo
@@ -0,0 +1,26 @@
1struct Efl.Ui.Tree_Factory_Item_Event
2{
3 model: Efl.Model;
4 expandable: bool;
5}
6
7class Efl.Ui.Tree_Factory extends Efl.Ui.Layout_Factory
8{
9 [[Efl Ui Tree Factory class]]
10 methods {
11 @property expandable_style {
12 [[Style used to expandable itens]]
13 set {}
14 values {
15 style: string; [[The style to use.]]
16 }
17 }
18 }
19 events {
20 item,create : Efl.Ui.Tree_Factory_Item_Event;
21 }
22 implements {
23 Efl.Object.destructor;
24 Efl.Ui.Factory.create;
25 }
26}
diff --git a/src/lib/elementary/efl_ui_tree_view.c b/src/lib/elementary/efl_ui_tree_view.c
new file mode 100644
index 0000000000..41a9728bf6
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view.c
@@ -0,0 +1,1158 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4#define EFL_ACCESS_OBJECT_PROTECTED
5#define EFL_ACCESS_SELECTION_PROTECTED
6#define EFL_UI_SCROLL_MANAGER_PROTECTED
7#define EFL_UI_SCROLLBAR_PROTECTED
8#define EFL_UI_SCROLLBAR_BETA
9#define EFL_UI_FOCUS_COMPOSITION_PROTECTED
10#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED
11
12#include <Elementary.h>
13#include "elm_priv.h"
14#include "efl_ui_tree_view_private.h"
15
16#define MY_CLASS EFL_UI_TREE_VIEW_CLASS
17#define MY_CLASS_NAME "Efl.Ui.Tree_View"
18
19#define MY_PAN_CLASS EFL_UI_TREE_VIEW_PAN_CLASS
20
21#define SELECTED_PROP "selected"
22
23static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
24static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
25static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
26
27static const Elm_Action key_actions[] = {
28 {"move", _key_action_move},
29 {"select", _key_action_select},
30 {"escape", _key_action_escape},
31 {NULL, NULL}
32};
33
34typedef struct _Tree_View_Slice_Callback_Data
35{
36 Efl_Ui_Tree_View_Data *private;
37 Efl_Ui_Tree_View_Item *parent_item;
38 Eina_Future *future;
39 int first;
40} Tree_View_Slice_Callback_Data;
41
42static Eina_Bool
43_key_action_move(Evas_Object *obj EINA_UNUSED, const char *params EINA_UNUSED)
44{
45 return EINA_FALSE;
46}
47
48static Eina_Bool
49_key_action_select(Evas_Object *obj, const char *params EINA_UNUSED)
50{
51 Efl_Ui_Focus_Object *focused = efl_ui_focus_manager_focus_get(obj);
52
53 if (!focused) return EINA_FALSE;
54
55//TODO expanded actions
56 return EINA_FALSE;
57}
58
59static Eina_Bool
60_key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
61{
62 efl_ui_focus_manager_reset_history(obj);
63 return EINA_TRUE;
64}
65
66void _efl_ui_tree_view_item_select_set(Efl_Ui_Tree_View_Item*, Eina_Bool);
67static void _layout(Efl_Ui_Tree_View_Data* pd);
68
69EOLIAN static void
70_efl_ui_tree_view_pan_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Pan_Data *psd)
71{
72 evas_object_smart_changed(psd->wobj);
73}
74
75EOLIAN static void
76_efl_ui_tree_view_pan_efl_ui_pan_pan_position_set(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Pan_Data *psd, Eina_Position2D pos)
77{
78 if ((pos.x == psd->gmt.x) && (pos.y == psd->gmt.y)) return;
79
80 psd->gmt.x = pos.x;
81 psd->gmt.y = pos.y;
82
83 efl_event_callback_call(obj, EFL_UI_PAN_EVENT_POSITION_CHANGED, NULL);
84 evas_object_smart_changed(psd->wobj);
85}
86
87EOLIAN static Eina_Position2D
88_efl_ui_tree_view_pan_efl_ui_pan_pan_position_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Pan_Data *psd)
89{
90 return psd->gmt.pos;
91}
92
93EOLIAN static Eina_Position2D
94_efl_ui_tree_view_pan_efl_ui_pan_pan_position_max_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Pan_Data *psd)
95{
96 EFL_UI_TREE_VIEW_DATA_GET(psd->wobj, pd);
97 Eina_Rect vgmt = {};
98 Eina_Size2D min = {};
99
100 vgmt = efl_ui_scrollable_viewport_geometry_get(pd->scrl_mgr);
101 min = efl_ui_tree_view_model_min_size_get(psd->wobj);
102
103 min.w = min.w - vgmt.w;
104 if (min.w < 0) min.w = 0;
105 min.h = min.h - vgmt.h;
106 if (min.h < 0) min.h = 0;
107
108 return EINA_POSITION2D(min.w, min.h);
109}
110
111EOLIAN static Eina_Position2D
112_efl_ui_tree_view_pan_efl_ui_pan_pan_position_min_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Pan_Data *psd EINA_UNUSED)
113{
114 return EINA_POSITION2D(0, 0);
115}
116
117EOLIAN static Eina_Size2D
118_efl_ui_tree_view_pan_efl_ui_pan_content_size_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Pan_Data *psd)
119{
120 return efl_ui_tree_view_model_min_size_get(psd->wobj);
121}
122
123EOLIAN static void
124_efl_ui_tree_view_pan_efl_object_destructor(Eo *obj, Efl_Ui_Tree_View_Pan_Data *psd EINA_UNUSED)
125{
126 efl_destructor(efl_super(obj, MY_PAN_CLASS));
127}
128
129#include "efl_ui_tree_view_pan.eo.c"
130
131EOLIAN static void
132_efl_ui_tree_view_efl_ui_scrollable_interactive_content_pos_set(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *psd, Eina_Position2D pos)
133{
134 efl_ui_scrollable_content_pos_set(psd->scrl_mgr, pos);
135}
136
137EOLIAN static Eina_Position2D
138_efl_ui_tree_view_efl_ui_scrollable_interactive_content_pos_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *psd)
139{
140 return efl_ui_scrollable_content_pos_get(psd->scrl_mgr);
141}
142
143EOLIAN static Eina_Size2D
144_efl_ui_tree_view_efl_ui_scrollable_interactive_content_size_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *psd)
145{
146 return efl_ui_scrollable_content_size_get(psd->scrl_mgr);
147}
148
149EOLIAN static Eina_Rect
150_efl_ui_tree_view_efl_ui_scrollable_interactive_viewport_geometry_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *psd)
151{
152 return efl_ui_scrollable_viewport_geometry_get(psd->scrl_mgr);
153}
154
155EOLIAN static void
156_efl_ui_tree_view_efl_ui_scrollable_interactive_scroll(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *psd, Eina_Rect rect, Eina_Bool animation)
157{
158 efl_ui_scrollable_scroll(psd->scrl_mgr, rect, animation);
159}
160
161static Eina_Bool
162_efl_model_properties_has(Efl_Model *model, Eina_Stringshare *propfind)
163{
164 Eina_Iterator *properties;
165 const char *property;
166 Eina_Bool ret = EINA_FALSE;
167
168 EINA_SAFETY_ON_NULL_RETURN_VAL(model, EINA_FALSE);
169 EINA_SAFETY_ON_NULL_RETURN_VAL(propfind, EINA_FALSE);
170
171 properties = efl_model_properties_get(model);
172
173 EINA_ITERATOR_FOREACH(properties, property)
174 {
175 if (property == propfind ||
176 !strcmp(property, propfind))
177 {
178 ret = EINA_TRUE;
179 break;
180 }
181 }
182 eina_iterator_free(properties);
183
184 return ret;
185}
186
187static void
188_list_element_focused(void *data EINA_UNUSED, const Efl_Event *ev)
189{
190 Eina_Rect geom;
191 Eina_Position2D pos;
192 Efl_Ui_Focus_Object *focused = efl_ui_focus_manager_focus_get(ev->object);
193
194 if (!focused) return;
195
196 EFL_UI_TREE_VIEW_DATA_GET(ev->object, pd);
197 geom = efl_ui_focus_object_focus_geometry_get(focused);
198 pos = efl_ui_scrollable_content_pos_get(pd->scrl_mgr);
199
200 geom.x += pos.x;
201 geom.y += pos.y;
202 efl_ui_scrollable_scroll(ev->object, geom, EINA_TRUE);
203}
204
205static void
206_on_item_mouse_up(void *data, Evas *evas EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info)
207{
208 Evas_Event_Mouse_Down *ev = event_info;
209 Efl_Ui_Tree_View_Item *item = data;
210
211 if (ev->button != 1) return;
212 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
213
214 _efl_ui_tree_view_item_select_set(item, EINA_TRUE);
215}
216
217EOLIAN static void
218_efl_ui_tree_view_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Tree_View_Data *pd, Eina_Position2D pos)
219{
220 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
221 return;
222
223 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
224 evas_object_smart_changed(pd->obj);
225}
226
227EOLIAN static void
228_efl_ui_tree_view_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Tree_View_Data *pd, Eina_Size2D size)
229{
230 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, size.w, size.h))
231 return;
232
233 efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), size);
234
235 evas_object_smart_changed(pd->obj);
236}
237
238EOLIAN static void
239_efl_ui_tree_view_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd)
240{
241 _layout(pd);
242}
243
244EOLIAN static void
245_efl_ui_tree_view_efl_canvas_group_group_member_add(Eo *obj, Efl_Ui_Tree_View_Data *pd EINA_UNUSED, Evas_Object *member)
246{
247 efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member);
248}
249
250//Scrollable Implement
251static void
252_efl_ui_tree_view_bar_read_and_update(Eo *obj)
253{
254 EFL_UI_TREE_VIEW_DATA_GET(obj, pd);
255 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
256 double vx, vy;
257
258 edje_object_part_drag_value_get
259 (wd->resize_obj, "efl.dragable.vbar", NULL, &vy);
260 edje_object_part_drag_value_get
261 (wd->resize_obj, "efl.dragable.hbar", &vx, NULL);
262
263 efl_ui_scrollbar_bar_position_set(pd->scrl_mgr, vx, vy);
264
265 efl_canvas_group_change(pd->pan_obj);
266}
267
268static void
269_efl_ui_tree_view_reload_cb(void *data,
270 Evas_Object *obj EINA_UNUSED,
271 const char *emission EINA_UNUSED,
272 const char *source EINA_UNUSED)
273{
274 EFL_UI_TREE_VIEW_DATA_GET(data, pd);
275
276 efl_ui_scrollbar_bar_visibility_update(pd->scrl_mgr);
277}
278
279static void
280_efl_ui_tree_view_vbar_drag_cb(void *data,
281 Evas_Object *obj EINA_UNUSED,
282 const char *emission EINA_UNUSED,
283 const char *source EINA_UNUSED)
284{
285 _efl_ui_tree_view_bar_read_and_update(data);
286
287 Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL;
288 efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_DRAG, &type);
289}
290
291static void
292_efl_ui_tree_view_vbar_press_cb(void *data,
293 Evas_Object *obj EINA_UNUSED,
294 const char *emission EINA_UNUSED,
295 const char *source EINA_UNUSED)
296{
297 Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL;
298 efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_PRESS, &type);
299}
300
301static void
302_efl_ui_tree_view_vbar_unpress_cb(void *data,
303 Evas_Object *obj EINA_UNUSED,
304 const char *emission EINA_UNUSED,
305 const char *source EINA_UNUSED)
306{
307 Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL;
308 efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_UNPRESS, &type);
309}
310
311static void
312_efl_ui_tree_view_edje_drag_start_cb(void *data,
313 Evas_Object *obj EINA_UNUSED,
314 const char *emission EINA_UNUSED,
315 const char *source EINA_UNUSED)
316{
317 EFL_UI_TREE_VIEW_DATA_GET(data, pd);
318
319 _efl_ui_tree_view_bar_read_and_update(data);
320
321 pd->scrl_freeze = efl_ui_scrollable_scroll_freeze_get(pd->scrl_mgr);
322 efl_ui_scrollable_scroll_freeze_set(pd->scrl_mgr, EINA_TRUE);
323 efl_event_callback_call(data, EFL_UI_EVENT_SCROLL_DRAG_START, NULL);
324}
325
326static void
327_efl_ui_tree_view_edje_drag_stop_cb(void *data,
328 Evas_Object *obj EINA_UNUSED,
329 const char *emission EINA_UNUSED,
330 const char *source EINA_UNUSED)
331{
332 EFL_UI_TREE_VIEW_DATA_GET(data, pd);
333
334 _efl_ui_tree_view_bar_read_and_update(data);
335
336 efl_ui_scrollable_scroll_freeze_set(pd->scrl_mgr, pd->scrl_freeze);
337 efl_event_callback_call(data, EFL_UI_EVENT_SCROLL_DRAG_STOP, NULL);
338}
339
340static void
341_efl_ui_tree_view_edje_drag_cb(void *data,
342 Evas_Object *obj EINA_UNUSED,
343 const char *emission EINA_UNUSED,
344 const char *source EINA_UNUSED)
345{
346 _efl_ui_tree_view_bar_read_and_update(data);
347}
348
349static void
350_efl_ui_tree_view_hbar_drag_cb(void *data,
351 Evas_Object *obj EINA_UNUSED,
352 const char *emission EINA_UNUSED,
353 const char *source EINA_UNUSED)
354{
355 _efl_ui_tree_view_bar_read_and_update(data);
356
357 Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL;
358 efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_DRAG, &type);
359}
360
361static void
362_efl_ui_tree_view_hbar_press_cb(void *data,
363 Evas_Object *obj EINA_UNUSED,
364 const char *emission EINA_UNUSED,
365 const char *source EINA_UNUSED)
366{
367 Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL;
368 efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_PRESS, &type);
369}
370
371static void
372_efl_ui_tree_view_hbar_unpress_cb(void *data,
373 Evas_Object *obj EINA_UNUSED,
374 const char *emission EINA_UNUSED,
375 const char *source EINA_UNUSED)
376{
377 Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL;
378 efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_UNPRESS, &type);
379}
380
381EOLIAN static void
382_efl_ui_tree_view_efl_ui_scrollbar_bar_mode_set(Eo *obj EINA_UNUSED,
383 Efl_Ui_Tree_View_Data *pd,
384 Efl_Ui_Scrollbar_Mode hmode,
385 Efl_Ui_Scrollbar_Mode vmode)
386{
387 efl_ui_scrollbar_bar_mode_set(pd->scrl_mgr, hmode, vmode);
388}
389
390EOLIAN static void
391_efl_ui_tree_view_efl_ui_scrollbar_bar_mode_get(Eo const *obj EINA_UNUSED,
392 Efl_Ui_Tree_View_Data *pd,
393 Efl_Ui_Scrollbar_Mode *hmode,
394 Efl_Ui_Scrollbar_Mode *vmode)
395{
396 efl_ui_scrollbar_bar_mode_get(pd->scrl_mgr, hmode, vmode);
397}
398
399static void
400_efl_ui_tree_view_bar_size_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
401{
402 Eo *obj = data;
403 EFL_UI_TREE_VIEW_DATA_GET(obj, pd);
404 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
405
406 double width = 0.0, height = 0.0;
407
408 efl_ui_scrollbar_bar_size_get(pd->scrl_mgr, &width, &height);
409
410 edje_object_part_drag_size_set(wd->resize_obj, "efl.dragable.hbar", width, 1.0);
411 edje_object_part_drag_size_set(wd->resize_obj, "efl.dragable.vbar", 1.0, height);
412}
413
414static void
415_efl_ui_tree_view_bar_pos_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
416{
417 Eo *obj = data;
418 EFL_UI_TREE_VIEW_DATA_GET(obj, pd);
419 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
420
421 double posx = 0.0, posy = 0.0;
422
423 efl_ui_scrollbar_bar_position_get(pd->scrl_mgr, &posx, &posy);
424
425 edje_object_part_drag_value_set(wd->resize_obj, "efl.dragable.hbar", posx, 0.0);
426 edje_object_part_drag_value_set(wd->resize_obj, "efl.dragable.vbar", 0.0, posy);
427}
428
429static void
430_efl_ui_tree_view_bar_show_cb(void *data, const Efl_Event *event)
431{
432 Eo *obj = data;
433 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
434 Efl_Ui_Scrollbar_Direction type = *(Efl_Ui_Scrollbar_Direction *)(event->info);
435
436 if (type == EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL)
437 edje_object_signal_emit(wd->resize_obj, "efl,action,show,hbar", "efl");
438 else if (type == EFL_UI_SCROLLBAR_DIRECTION_VERTICAL)
439 edje_object_signal_emit(wd->resize_obj, "efl,action,show,vbar", "efl");
440}
441
442static void
443_efl_ui_tree_view_bar_hide_cb(void *data, const Efl_Event *event)
444{
445 Eo *obj = data;
446 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
447 Efl_Ui_Scrollbar_Direction type = *(Efl_Ui_Scrollbar_Direction *)(event->info);
448
449 if (type == EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL)
450 edje_object_signal_emit(wd->resize_obj, "efl,action,hide,hbar", "efl");
451 else if (type == EFL_UI_SCROLLBAR_DIRECTION_VERTICAL)
452 edje_object_signal_emit(wd->resize_obj, "efl,action,hide,vbar", "efl");
453}
454
455EOLIAN static Eina_Bool
456_efl_ui_tree_view_efl_layout_signal_signal_callback_add(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *sd EINA_UNUSED,
457 const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
458{
459 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
460 return efl_layout_signal_callback_add(wd->resize_obj, emission, source, func_cb, data);
461}
462
463EOLIAN static Eina_Bool
464_efl_ui_tree_view_efl_layout_signal_signal_callback_del(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *sd EINA_UNUSED,
465 const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
466{
467 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
468 return efl_layout_signal_callback_del(wd->resize_obj, emission, source, func_cb, data);
469}
470
471static void
472_efl_ui_tree_view_edje_object_attach(Eo *obj)
473{
474 efl_layout_signal_callback_add
475 (obj, "reload", "efl",
476 _efl_ui_tree_view_reload_cb, obj);
477 //Vertical bar
478 efl_layout_signal_callback_add
479 (obj, "drag", "efl.dragable.vbar",
480 _efl_ui_tree_view_vbar_drag_cb, obj);
481 efl_layout_signal_callback_add
482 (obj, "drag,set", "efl.dragable.vbar",
483 _efl_ui_tree_view_edje_drag_cb, obj);
484 efl_layout_signal_callback_add
485 (obj, "drag,start", "efl.dragable.vbar",
486 _efl_ui_tree_view_edje_drag_start_cb, obj);
487 efl_layout_signal_callback_add
488 (obj, "drag,stop", "efl.dragable.vbar",
489 _efl_ui_tree_view_edje_drag_stop_cb, obj);
490 efl_layout_signal_callback_add
491 (obj, "drag,step", "efl.dragable.vbar",
492 _efl_ui_tree_view_edje_drag_cb, obj);
493 efl_layout_signal_callback_add
494 (obj, "drag,page", "efl.dragable.vbar",
495 _efl_ui_tree_view_edje_drag_cb, obj);
496 efl_layout_signal_callback_add
497 (obj, "efl,vbar,press", "efl",
498 _efl_ui_tree_view_vbar_press_cb, obj);
499 efl_layout_signal_callback_add
500 (obj, "efl,vbar,unpress", "efl",
501 _efl_ui_tree_view_vbar_unpress_cb, obj);
502
503 //Horizontal bar
504 efl_layout_signal_callback_add
505 (obj, "drag", "efl.dragable.hbar",
506 _efl_ui_tree_view_hbar_drag_cb, obj);
507 efl_layout_signal_callback_add
508 (obj, "drag,set", "efl.dragable.hbar",
509 _efl_ui_tree_view_edje_drag_cb, obj);
510 efl_layout_signal_callback_add
511 (obj, "drag,start", "efl.dragable.hbar",
512 _efl_ui_tree_view_edje_drag_start_cb, obj);
513 efl_layout_signal_callback_add
514 (obj, "drag,stop", "efl.dragable.hbar",
515 _efl_ui_tree_view_edje_drag_stop_cb, obj);
516 efl_layout_signal_callback_add
517 (obj, "drag,step", "efl.dragable.hbar",
518 _efl_ui_tree_view_edje_drag_cb, obj);
519 efl_layout_signal_callback_add
520 (obj, "drag,page", "efl.dragable.hbar",
521 _efl_ui_tree_view_edje_drag_cb, obj);
522 efl_layout_signal_callback_add
523 (obj, "efl,hbar,press", "efl",
524 _efl_ui_tree_view_hbar_press_cb, obj);
525 efl_layout_signal_callback_add
526 (obj, "efl,hbar,unpress", "efl",
527 _efl_ui_tree_view_hbar_unpress_cb, obj);
528}
529
530static void
531_efl_ui_tree_view_edje_object_detach(Evas_Object *obj)
532{
533 efl_layout_signal_callback_del
534 (obj, "reload", "efl", _efl_ui_tree_view_reload_cb, obj);
535 //Vertical bar
536 efl_layout_signal_callback_del
537 (obj, "drag", "efl.dragable.vbar",
538 _efl_ui_tree_view_vbar_drag_cb, obj);
539 efl_layout_signal_callback_del
540 (obj, "drag,set", "efl.dragable.vbar",
541 _efl_ui_tree_view_edje_drag_cb, obj);
542 efl_layout_signal_callback_del
543 (obj, "drag,start", "efl.dragable.vbar",
544 _efl_ui_tree_view_edje_drag_start_cb, obj);
545 efl_layout_signal_callback_del
546 (obj, "drag,stop", "efl.dragable.vbar",
547 _efl_ui_tree_view_edje_drag_stop_cb, obj);
548 efl_layout_signal_callback_del
549 (obj, "drag,step", "efl.dragable.vbar",
550 _efl_ui_tree_view_edje_drag_cb, obj);
551 efl_layout_signal_callback_del
552 (obj, "drag,page", "efl.dragable.vbar",
553 _efl_ui_tree_view_edje_drag_cb, obj);
554 efl_layout_signal_callback_del
555 (obj, "efl,vbar,press", "efl",
556 _efl_ui_tree_view_vbar_press_cb, obj);
557 efl_layout_signal_callback_del
558 (obj, "efl,vbar,unpress", "efl",
559 _efl_ui_tree_view_vbar_unpress_cb, obj);
560
561 //Horizontal bar
562 efl_layout_signal_callback_del
563 (obj, "drag", "efl.dragable.hbar",
564 _efl_ui_tree_view_hbar_drag_cb, obj);
565 efl_layout_signal_callback_del
566 (obj, "drag,set", "efl.dragable.hbar",
567 _efl_ui_tree_view_edje_drag_cb, obj);
568 efl_layout_signal_callback_del
569 (obj, "drag,start", "efl.dragable.hbar",
570 _efl_ui_tree_view_edje_drag_start_cb, obj);
571 efl_layout_signal_callback_del
572 (obj, "drag,stop", "efl.dragable.hbar",
573 _efl_ui_tree_view_edje_drag_stop_cb, obj);
574 efl_layout_signal_callback_del
575 (obj, "drag,step", "efl.dragable.hbar",
576 _efl_ui_tree_view_edje_drag_cb, obj);
577 efl_layout_signal_callback_del
578 (obj, "drag,page", "efl.dragable.hbar",
579 _efl_ui_tree_view_edje_drag_cb, obj);
580 efl_layout_signal_callback_del
581 (obj, "efl,hbar,press", "efl",
582 _efl_ui_tree_view_hbar_press_cb, obj);
583 efl_layout_signal_callback_del
584 (obj, "efl,hbar,unpress", "efl",
585 _efl_ui_tree_view_hbar_unpress_cb, obj);
586}
587
588EOLIAN static void
589_efl_ui_tree_view_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Tree_View_Data *pd)
590{
591 Efl_Ui_Tree_View_Pan_Data *pan_data;
592 Eina_Size2D min = {};
593 Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
594 Evas_Object *o;
595
596 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
597
598 efl_canvas_group_add(efl_super(obj, MY_CLASS));
599 elm_widget_sub_object_parent_add(obj);
600
601 elm_widget_can_focus_set(obj, EINA_TRUE);
602
603 if (!elm_layout_theme_set(obj, "tree_view", "base", elm_widget_style_get(obj)))
604 CRI("Failed to set layout!");
605
606 pd->scrl_mgr = efl_add(EFL_UI_SCROLL_MANAGER_CLASS, obj,
607 efl_ui_mirrored_set(efl_added, efl_ui_mirrored_get(obj)));
608 efl_composite_attach(obj, pd->scrl_mgr);
609 pd->pan_obj = efl_add(MY_PAN_CLASS, obj);
610 pan_data = efl_data_scope_get(pd->pan_obj, MY_PAN_CLASS);
611 pan_data->wobj = obj;
612
613 efl_ui_scroll_manager_pan_set(pd->scrl_mgr, pd->pan_obj);
614 efl_ui_scrollable_bounce_enabled_set(pd->scrl_mgr, bounce, bounce);
615
616 edje_object_part_swallow(wd->resize_obj, "efl.content", pd->pan_obj);
617 edje_object_freeze(wd->resize_obj);
618 o = (Evas_Object *)edje_object_part_object_get(wd->resize_obj, "efl.dragable.vbar");
619 edje_object_thaw(wd->resize_obj);
620 efl_gfx_stack_raise((Eo *)o);
621
622 efl_gfx_entity_visible_set(pd->pan_obj, EINA_TRUE);
623 efl_access_object_access_type_set(obj, EFL_ACCESS_TYPE_DISABLED);
624
625 edje_object_size_min_calc(wd->resize_obj, &min.w, &min.h);
626 efl_gfx_size_hint_restricted_min_set(obj, min);
627
628 efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SIZE_CHANGED,
629 _efl_ui_tree_view_bar_size_changed_cb, obj);
630 efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_POS_CHANGED,
631 _efl_ui_tree_view_bar_pos_changed_cb, obj);
632 efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SHOW,
633 _efl_ui_tree_view_bar_show_cb, obj);
634 efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_HIDE,
635 _efl_ui_tree_view_bar_hide_cb, obj);
636
637 _efl_ui_tree_view_edje_object_attach(obj);
638
639 elm_layout_sizing_eval(obj);
640}
641
642EOLIAN static void
643_efl_ui_tree_view_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Tree_View_Data *pd)
644{
645 efl_ui_tree_view_relayout_model_set(pd->layouter, NULL);
646
647 ELM_SAFE_FREE(pd->pan_obj, efl_del);
648 efl_canvas_group_del(efl_super(obj, MY_CLASS));
649}
650
651EOLIAN static Efl_Ui_Focus_Manager*
652_efl_ui_tree_view_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj EINA_UNUSED,
653 Efl_Ui_Tree_View_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
654{
655 if (!pd->manager)
656 pd->manager = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj,
657 efl_ui_focus_manager_root_set(efl_added, root));
658
659 return pd->manager;
660}
661
662EOLIAN static Eo *
663_efl_ui_tree_view_efl_object_finalize(Eo *obj, Efl_Ui_Tree_View_Data *pd)
664{
665
666 if (!pd->factory)
667 {
668 pd->factory = efl_new(EFL_UI_LAYOUT_FACTORY_CLASS);
669 efl_ui_layout_factory_theme_config(pd->factory, "list_item", NULL, "default");
670 }
671
672 if(!pd->layouter)
673 {
674 pd->layouter = efl_new(EFL_UI_TREE_VIEW_LAYOUTER_CLASS);
675 efl_ui_tree_view_relayout_model_set(pd->layouter, pd->model);
676 }
677 return obj;
678}
679
680EOLIAN static Eo *
681_efl_ui_tree_view_efl_object_constructor(Eo *obj, Efl_Ui_Tree_View_Data *pd)
682{
683 obj = efl_constructor(efl_super(obj, MY_CLASS));
684 pd->obj = obj;
685 efl_canvas_object_type_set(obj, MY_CLASS_NAME);
686 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_LIST);
687
688 pd->segarray = efl_ui_tree_view_seg_array_setup(32);
689
690 efl_event_callback_add(obj, EFL_UI_FOCUS_MANAGER_EVENT_FOCUS_CHANGED, _list_element_focused, NULL);
691
692 efl_ui_focus_composition_custom_manager_set(obj, obj);
693 efl_ui_focus_composition_logical_mode_set(obj, EINA_TRUE);
694
695// pd->style = eina_stringshare_add(elm_widget_style_get(obj));
696
697 //efl_event_callback_add(obj, EFL_UI_FOCUS_MANAGER_EVENT_FOCUS_CHANGED,
698 // _list_element_focused, NULL);
699 return obj;
700}
701
702EOLIAN static void
703_efl_ui_tree_view_efl_object_destructor(Eo *obj, Efl_Ui_Tree_View_Data *pd)
704{
705 efl_event_callback_del(obj, EFL_UI_FOCUS_MANAGER_EVENT_FOCUS_CHANGED,
706 _list_element_focused, NULL);
707
708 _efl_ui_tree_view_edje_object_detach(obj);
709 efl_ui_tree_view_seg_array_flush(pd->segarray);
710
711 efl_replace(&pd->model, NULL);
712 efl_replace(&pd->layouter, NULL);
713 efl_replace(&pd->factory, NULL);
714 efl_ui_tree_view_seg_array_free(pd->segarray);
715
716 efl_destructor(efl_super(obj, MY_CLASS));
717}
718
719EOLIAN static void
720_efl_ui_tree_view_layout_factory_set(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd, Efl_Ui_Factory *factory)
721{
722 if (pd->factory == factory)
723 return;
724
725 efl_replace(&pd->factory, factory);
726}
727
728EOLIAN static Efl_Ui_Factory *
729_efl_ui_tree_view_layout_factory_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd)
730{
731 return pd->factory;
732}
733
734EOLIAN static void
735_efl_ui_tree_view_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd, Efl_Model *model)
736{
737 if (pd->model == model)
738 return;
739
740 if (pd->model)
741 {
742 if (pd->layouter)
743 efl_ui_tree_view_relayout_model_set(pd->layouter, NULL);
744 efl_ui_tree_view_seg_array_flush(pd->segarray);
745 }
746
747 efl_replace(&pd->model, model);
748
749 if (pd->model && pd->layouter)
750 efl_ui_tree_view_relayout_model_set(pd->layouter, pd->model);
751
752 evas_object_smart_changed(pd->obj);
753}
754
755EOLIAN static Efl_Model *
756_efl_ui_tree_view_efl_ui_view_model_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd)
757{
758 return pd->model;
759}
760
761EOLIAN int
762_efl_ui_tree_view_efl_access_selection_selected_children_count_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd)
763{
764 return eina_list_count(pd->selected_items);
765}
766
767EOLIAN Eo*
768_efl_ui_tree_view_efl_access_selection_selected_child_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd, int child_index)
769{
770 if(child_index < (int) eina_list_count(pd->selected_items))
771 {
772 Efl_Ui_Tree_View_Item* items = eina_list_nth(pd->selected_items, child_index);
773 return items[child_index].layout;
774 }
775 else
776 return NULL;
777}
778
779EOLIAN Eina_Bool
780_efl_ui_tree_view_efl_access_selection_child_select(Eo *obj EINA_UNUSED,
781 Efl_Ui_Tree_View_Data *pd EINA_UNUSED, int child_index EINA_UNUSED)
782{
783 return EINA_FALSE;
784}
785
786EOLIAN Eina_Bool
787_efl_ui_tree_view_efl_access_selection_selected_child_deselect(Eo *obj EINA_UNUSED,
788 Efl_Ui_Tree_View_Data *pd EINA_UNUSED, int child_index EINA_UNUSED)
789{
790 return EINA_FALSE;
791}
792
793EOLIAN Eina_Bool
794_efl_ui_tree_view_efl_access_selection_is_child_selected(Eo *obj EINA_UNUSED,
795 Efl_Ui_Tree_View_Data *pd EINA_UNUSED, int child_index EINA_UNUSED)
796{
797 return EINA_FALSE;
798}
799
800EOLIAN Eina_Bool
801_efl_ui_tree_view_efl_access_selection_all_children_select(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd EINA_UNUSED)
802{
803 return EINA_TRUE;
804}
805
806EOLIAN Eina_Bool
807_efl_ui_tree_view_efl_access_selection_access_selection_clear(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd EINA_UNUSED)
808{
809 return EINA_TRUE;
810}
811
812EOLIAN Eina_Bool
813_efl_ui_tree_view_efl_access_selection_child_deselect(Eo *obj EINA_UNUSED,
814 Efl_Ui_Tree_View_Data *pd EINA_UNUSED, int child_index EINA_UNUSED)
815{
816 return EINA_FALSE;
817}
818
819static Eina_Value
820_expand_children_slice_then(void * data, Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
821{
822 Efl_Ui_Tree_View_Data *pd;
823 Efl_Model *children;
824 Tree_View_Slice_Callback_Data *slice = data;
825 unsigned int i, len;
826
827 if (!slice || eina_value_type_get(&v) == EINA_VALUE_TYPE_ERROR)
828 goto on_error;
829
830 pd = slice->private;
831 if (eina_value_type_get(&v) == EINA_VALUE_TYPE_OBJECT)
832 {
833 children = eina_value_object_get(&v);
834 efl_ui_tree_view_seg_array_insert(pd->segarray, slice->parent_item, 0, children);
835 }
836 else if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ARRAY)
837 {
838 EINA_VALUE_ARRAY_FOREACH(&v, len, i, children)
839 {
840 unsigned int idx = 0 + i;
841 efl_ui_tree_view_seg_array_insert(pd->segarray, slice->parent_item, idx, children);
842 }
843 }
844 else
845 {
846 ERR ("_expand_children_slice_then");
847 }
848 slice->future = NULL;
849
850 efl_ui_tree_view_relayout_layout_do(pd->layouter, pd->obj, pd->segarray_first, pd->segarray);
851 on_error:
852 free(slice);
853 return v;
854}
855
856void
857_efl_ui_tree_view_item_select_set(Efl_Ui_Tree_View_Item *item, Eina_Bool selected)
858{
859 Eina_Stringshare *sprop;
860 assert(item != NULL);
861 assert(item->model != NULL);
862
863 selected = !!selected;
864
865 sprop = eina_stringshare_add(SELECTED_PROP);
866
867 if (_efl_model_properties_has(item->model, sprop))
868 {
869 Eina_Value v;
870 eina_value_setup(&v, EINA_VALUE_TYPE_UCHAR);
871 eina_value_set(&v, selected);
872 efl_model_property_set(item->model, sprop, &v);
873 eina_value_flush(&v);
874 }
875 eina_stringshare_del(sprop);
876}
877
878EOLIAN static void
879_efl_ui_tree_view_relayout_set(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd, Efl_Ui_Tree_View_Relayout *layouter)
880{
881 if (pd->layouter == layouter)
882 return;
883
884 efl_replace(&pd->layouter, layouter);
885
886 if (pd->model && pd->layouter)
887 efl_ui_tree_view_relayout_model_set(pd->layouter, pd->model);
888}
889
890EOLIAN static Efl_Ui_Tree_View_Relayout *
891_efl_ui_tree_view_relayout_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd)
892{
893 return pd->layouter;
894}
895
896EOLIAN static void
897_efl_ui_tree_view_show_root_set(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd, Eina_Bool showroot)
898{
899 pd->show_root = showroot;
900}
901
902EOLIAN static Eina_Bool
903_efl_ui_tree_view_show_root_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd)
904{
905 return pd->show_root;
906}
907
908static void
909_layout(Efl_Ui_Tree_View_Data *pd)
910{
911 if (!pd->model)
912 return;
913
914 efl_ui_tree_view_relayout_layout_do(pd->layouter, pd->obj, pd->segarray_first, pd->segarray);
915}
916
917static Eina_Value
918_children_slice_then(void * data, Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
919{
920 Efl_Ui_Tree_View_Data *pd = data;
921 Efl_Model *children;
922 unsigned int i, len;
923
924 if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ERROR)
925 goto on_error;
926
927 if (eina_value_type_get(&v) == EINA_VALUE_TYPE_OBJECT)
928 {
929 children = eina_value_object_get(&v);
930 efl_ui_tree_view_seg_array_insert(pd->segarray, NULL, pd->slice.start, children);
931 }
932 else if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ARRAY)
933 {
934 EINA_VALUE_ARRAY_FOREACH(&v, len, i, children)
935 {
936 unsigned int idx = pd->slice.start + i;
937
938 efl_ui_tree_view_seg_array_insert(pd->segarray, NULL, idx, children);
939 }
940 }
941
942 pd->segarray_first = pd->slice.start;
943 pd->slice.start = pd->slice.count = 0;
944 pd->slice.future = NULL;
945
946 efl_ui_tree_view_relayout_layout_do(pd->layouter, pd->obj, pd->segarray_first, pd->segarray);
947 on_error:
948 return v;
949}
950
951/* EFL UI TREE MODEL INTERFACE */
952EOLIAN static Eina_Size2D
953_efl_ui_tree_view_efl_ui_tree_view_model_min_size_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd)
954{
955 return pd->min;
956}
957
958EOLIAN static void
959_efl_ui_tree_view_efl_ui_tree_view_model_min_size_set(Eo *obj, Efl_Ui_Tree_View_Data *pd, Eina_Size2D min)
960{
961 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
962
963 pd->min.w = min.w;
964 pd->min.h = min.h;
965
966 evas_object_size_hint_min_set(wd->resize_obj, pd->min.w, pd->min.h);
967 efl_event_callback_call(pd->pan_obj, EFL_UI_PAN_EVENT_CONTENT_CHANGED, NULL);
968}
969
970EOLIAN static void
971_efl_ui_tree_view_efl_ui_focus_composition_prepare(Eo *obj, Efl_Ui_Tree_View_Data *pd)
972{
973 Eina_List *order = efl_ui_tree_view_relayout_elements_get(pd->layouter);
974 efl_ui_focus_composition_elements_set(obj, order);
975}
976
977EOLIAN Eina_List*
978_efl_ui_tree_view_efl_access_object_access_children_get(const Eo *obj, Efl_Ui_Tree_View_Data *pd)
979{
980 Eina_List *ret = NULL, *ret2 = NULL;
981
982 ret = efl_ui_tree_view_relayout_elements_get(pd->layouter);
983 ret2 = efl_access_object_access_children_get(efl_super(obj, EFL_UI_TREE_VIEW_CLASS));
984
985 return eina_list_merge(ret, ret2);
986}
987
988EOLIAN static Eina_Bool
989_efl_ui_tree_view_efl_ui_widget_focus_state_apply(Eo *obj, Efl_Ui_Tree_View_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect EINA_UNUSED)
990{
991 return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj);
992}
993
994typedef struct _Efl_Ui_Tree_View_Layout_Item_Tracking Efl_Ui_Tree_View_Layout_Item_Tracking;
995struct _Efl_Ui_Tree_View_Layout_Item_Tracking
996{
997 Efl_Ui_Tree_View_Item *item;
998 Efl_Ui_Tree_View_Data *pd;
999};
1000
1001static Eina_Value
1002_content_created(Eo *obj EINA_UNUSED, void *data, const Eina_Value value)
1003{
1004 Efl_Ui_Tree_View_Item_Event evt;
1005 Efl_Ui_Tree_View_Layout_Item_Tracking *tracking = data;
1006 Efl_Ui_Tree_View_Item *item = tracking->item;
1007 Efl_Ui_Tree_View_Data *pd = tracking->pd;
1008
1009 eina_value_pget(&value, &item->layout);
1010
1011 evas_object_smart_member_add(item->layout, pd->pan_obj);
1012 evas_object_event_callback_add(item->layout, EVAS_CALLBACK_MOUSE_UP, _on_item_mouse_up, item);
1013
1014 if (_elm_config->atspi_mode)
1015 {
1016 efl_access_added(item->layout);
1017 efl_access_children_changed_added_signal_emit(obj, item->layout);
1018 }
1019
1020 evt.child = item->model;
1021 evt.layout = item->layout;
1022 evt.index = EFL_UI_TREE_VIEW_SEG_ARRAY_POS_GET(item);
1023 efl_event_callback_call(obj, EFL_UI_TREE_VIEW_EVENT_ITEM_REALIZED, &evt);
1024
1025 item->layout_request = NULL;
1026 efl_ui_tree_view_relayout_content_created(pd->layouter, item);
1027
1028 efl_ui_focus_composition_dirty(obj);
1029 evas_object_show(item->layout);
1030
1031 return value;
1032}
1033
1034static void
1035_clean_request(Eo *obj EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
1036{
1037 Efl_Ui_Tree_View_Layout_Item_Tracking *tracking = data;
1038
1039 tracking->item->layout_request = NULL;
1040 free(tracking);
1041}
1042
1043EOLIAN static Efl_Ui_Tree_View_Item *
1044_efl_ui_tree_view_efl_ui_tree_view_model_realize(Eo *obj, Efl_Ui_Tree_View_Data *pd, Efl_Ui_Tree_View_Item *item)
1045{
1046
1047 Efl_Ui_Tree_View_Layout_Item_Tracking *tracking;
1048 EINA_SAFETY_ON_NULL_RETURN_VAL(item->model, item);
1049
1050 if (item->layout_request) eina_future_cancel(item->layout_request);
1051
1052 tracking = calloc(1, sizeof (Efl_Ui_Tree_View_Layout_Item_Tracking));
1053 if (!tracking) return item;
1054
1055 tracking->item = item;
1056 tracking->pd = pd;
1057
1058 item->layout_request = efl_ui_view_factory_create_with_event(pd->factory, item->model, obj);
1059 item->layout_request = efl_future_then(obj, item->layout_request,
1060 .success = _content_created,
1061 .success_type = EINA_VALUE_TYPE_OBJECT,
1062 .data = tracking,
1063 .free = _clean_request);
1064 return item;
1065}
1066
1067EOLIAN static void
1068_efl_ui_tree_view_efl_ui_tree_view_model_unrealize(Eo *obj, Efl_Ui_Tree_View_Data *pd, Efl_Ui_Tree_View_Item *item)
1069{
1070 Efl_Ui_Tree_View_Item_Event evt;
1071 EINA_SAFETY_ON_NULL_RETURN(item);
1072
1073 if (!item->layout)
1074 return;
1075
1076 // First check if the item has been fully realized
1077 if (item->layout_request)
1078 {
1079 eina_future_cancel(item->layout_request);
1080 return ;
1081 }
1082
1083 evas_object_event_callback_del_full(item->layout, EVAS_CALLBACK_MOUSE_UP, _on_item_mouse_up, item);
1084 if (elm_object_focus_allow_get(item->layout))
1085 {
1086 if (efl_ui_focus_object_focus_get(item->layout))
1087 efl_ui_focus_object_focus_set(item->layout, EINA_FALSE);
1088 efl_ui_focus_manager_calc_unregister(obj, item->layout);
1089 }
1090 evas_object_hide(item->layout);
1091 evas_object_move(item->layout, -9999, -9999);
1092
1093 evt.child = item->model;
1094 evt.layout = item->layout;
1095 evt.index = EFL_UI_TREE_VIEW_SEG_ARRAY_POS_GET(item);
1096 efl_event_callback_call(obj, EFL_UI_TREE_VIEW_EVENT_ITEM_UNREALIZED, &evt);
1097
1098 efl_ui_factory_release(pd->factory, item->layout);
1099 evas_object_smart_member_del(item->layout);
1100 item->layout = NULL;
1101}
1102
1103EOLIAN static void
1104_efl_ui_tree_view_efl_ui_tree_view_model_expand(Eo *obj, Efl_Ui_Tree_View_Data *pd, Efl_Ui_Tree_View_Item *item, int first, int count)
1105{
1106 Tree_View_Slice_Callback_Data *slice;
1107 Eina_Future *f;
1108
1109 if (item->expanded) return;
1110
1111 item->expanded = EINA_TRUE;
1112 slice = calloc(1, sizeof(Tree_View_Slice_Callback_Data));
1113 slice->private = pd;
1114 slice->parent_item = item;
1115 slice->first = first;
1116 f = efl_model_children_slice_get(item->model, first, count);
1117 f = eina_future_then(f, _expand_children_slice_then, slice, NULL);
1118 slice->future = efl_future_then(obj, f);
1119}
1120
1121EOLIAN static void
1122_efl_ui_tree_view_efl_ui_tree_view_model_contract(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd EINA_UNUSED, Efl_Ui_Tree_View_Item *item EINA_UNUSED)
1123{
1124 //TODO
1125}
1126
1127EOLIAN static void
1128_efl_ui_tree_view_efl_ui_tree_view_model_load_range_set(Eo* obj, Efl_Ui_Tree_View_Data* pd, int first, int count)
1129{
1130 if (pd->slice.future) return ; //FIXME: why ignore a new range set?
1131
1132 pd->slice.start = first;
1133 pd->slice.count = count;
1134
1135 if (efl_model_children_count_get(pd->model))
1136 {
1137 Eina_Future *f = efl_model_children_slice_get(pd->model, first, count);
1138 f = eina_future_then(f, _children_slice_then, pd, NULL);
1139 pd->slice.future = efl_future_then(obj, f);
1140 }
1141}
1142
1143EOLIAN static int
1144_efl_ui_tree_view_efl_ui_tree_view_model_model_size_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Data *pd)
1145{
1146 return efl_model_children_count_get(pd->model);
1147}
1148
1149ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_tree_view, Efl_Ui_Tree_View_Data)
1150
1151/* Internal EO APIs and hidden overrides */
1152
1153#define EFL_UI_TREE_VIEW_EXTRA_OPS \
1154 EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_tree_view)
1155
1156#include "efl_ui_tree_view.eo.c"
1157#include "efl_ui_tree_view_relayout.eo.c"
1158#include "efl_ui_tree_view_model.eo.c"
diff --git a/src/lib/elementary/efl_ui_tree_view.eo b/src/lib/elementary/efl_ui_tree_view.eo
new file mode 100644
index 0000000000..0c7a9f03cc
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view.eo
@@ -0,0 +1,96 @@
1import elm_general;
2
3struct Efl.Ui.Tree_View_Item_Event
4{
5 layout: Efl.Ui.Layout;
6 child: Efl.Model;
7 index: int; [[index of the item in thee layout]]
8 depth: int; [[depth of the item in tree layout]]
9}
10
11class Efl.Ui.Tree_View extends Efl.Ui.Layout implements Efl.Ui.Scrollable_Interactive, Efl.Ui.Scrollbar,
12 Efl.Access.Widget.Action, Efl.Access.Selection, Efl.Ui.Focus.Composition, Efl.Ui.Focus.Manager_Sub,
13 Efl.Ui.Clickable, Efl.Ui.Selectable, Efl.Ui.Tree_View_Model, Efl.Ui.Widget_Focus_Manager
14{
15 methods {
16 @property relayout {
17 get {}
18 set {}
19 values {
20 object: Efl.Ui.Tree_View_Relayout;
21 }
22 }
23 @property layout_factory {
24 [[Treeview layout factory set.]]
25 set {}
26 get {}
27 values {
28 factory: Efl.Ui.Factory; [[The factory.]]
29 }
30 }
31 @property show_root {
32 get {
33 [[Get if root is visible.]]
34 }
35 set {
36 [[Enable/Disable root visiblity.]]
37 }
38 values {
39 show: bool; [[Default is Disabled.]]
40 }
41 }
42 }
43 events {
44 item,realized : Efl.Ui.Tree_View_Item_Event;
45 item,unrealized : Efl.Ui.Tree_View_Item_Event;
46 item,focused : Efl.Ui.Tree_View_Item_Event;
47 item,unfocused : Efl.Ui.Tree_View_Item_Event;
48 item,selected : Efl.Ui.Tree_View_Item_Event;
49 item,unselected : Efl.Ui.Tree_View_Item_Event;
50 item,expanded : Efl.Ui.Tree_View_Item_Event;
51 item,unexpanded : Efl.Ui.Tree_View_Item_Event;
52 }
53
54 implements {
55 Efl.Object.constructor;
56 Efl.Object.finalize;
57 Efl.Object.destructor;
58 Efl.Gfx.Entity.position { set; }
59 Efl.Gfx.Entity.size { set; }
60 // Smart obj
61 Efl.Canvas.Group.group_member_add;
62 Efl.Canvas.Group.group_calculate;
63
64 Efl.Ui.Tree_View_Model.load_range { set;}
65 Efl.Ui.Tree_View_Model.realize;
66 Efl.Ui.Tree_View_Model.unrealize;
67 Efl.Ui.Tree_View_Model.expand;
68 Efl.Ui.Tree_View_Model.contract;
69 Efl.Ui.Tree_View_Model.model_size { get; }
70 Efl.Ui.Tree_View_Model.min_size { get; set; }
71
72 // Widget
73 Efl.Ui.Widget_Focus_Manager.focus_manager_create;
74 Efl.Ui.Widget.widget_event;
75 Efl.Ui.Widget.focus_state_apply;
76 Efl.Ui.Focus.Composition.prepare;
77 Efl.Ui.View.model { get; set; }
78
79 Efl.Ui.Scrollable_Interactive.viewport_geometry { get; }
80 Efl.Ui.Scrollable_Interactive.content_pos { get; set; }
81 Efl.Ui.Scrollable_Interactive.content_size { get; }
82 Efl.Ui.Scrollable_Interactive.scroll;
83 Efl.Ui.Scrollbar.bar_mode { get; set; }
84 Efl.Layout.Signal.signal_callback_add;
85 Efl.Layout.Signal.signal_callback_del;
86 Efl.Access.Object.access_children { get; }
87 Efl.Access.Selection.selected_children_count { get; }
88 Efl.Access.Selection.selected_child { get; }
89 Efl.Access.Selection.selected_child_deselect;
90 Efl.Access.Selection.child_select;
91 Efl.Access.Selection.child_deselect;
92 Efl.Access.Selection.is_child_selected;
93 Efl.Access.Selection.all_children_select;
94 Efl.Access.Selection.access_selection_clear;
95 }
96}
diff --git a/src/lib/elementary/efl_ui_tree_view_layouter.c b/src/lib/elementary/efl_ui_tree_view_layouter.c
new file mode 100644
index 0000000000..a8df96bf94
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_layouter.c
@@ -0,0 +1,722 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Elementary.h>
6
7#include <assert.h>
8
9#include "elm_priv.h"
10#include "efl_ui_tree_view_seg_array.h"
11
12#define MY_CLASS EFL_UI_TREE_VIEW_LAYOUTER_CLASS
13
14typedef struct _Efl_Ui_Tree_View_Layouter_Data
15{
16 Efl_Ui_Tree_View_Seg_Array *segarray;
17 Efl_Ui_Tree_View_Model *modeler;
18 Ecore_Job *calc_job;
19 Efl_Model* model;
20 Eina_Size2D min;
21 int count_total;
22 int count_segarray;
23
24 Eina_Bool initialized : 1;
25 Eina_Bool recalc : 1;
26 Eina_Bool resize : 1;
27} Efl_Ui_Tree_View_Layouter_Data;
28
29typedef struct _Efl_Ui_Tree_View_Layouter_Node_Data
30{
31 Eina_Size2D min;
32 Eina_Size2D size;
33 Eina_Bool realized : 1;
34 Eina_Bool expanded : 1;
35} Efl_Ui_Tree_View_Layouter_Node_Data;
36
37typedef struct _Efl_Ui_Tree_View_Layouter_Callback_Data
38{
39 Efl_Ui_Tree_View_Layouter_Data *pd;
40 Efl_Ui_Tree_View_Item *item;
41} Efl_Ui_Tree_View_Layouter_Callback_Data;
42
43typedef struct _Request Request;
44struct _Request
45{
46 Efl_Ui_Tree_View_Layouter_Data *pd;
47 unsigned int index;
48};
49
50typedef struct _Draw_Data
51{
52 Eina_Rect vgmt;
53 Eina_Position2D spos;
54 int extra;
55 int rounding;
56 double cur_pos;
57} Draw_Data;
58
59#include "efl_ui_tree_view_layouter.eo.h"
60
61static void
62_item_size_calc(Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Ui_Tree_View_Item* item)
63{
64 int boxx, boxy, boxw, boxh, boxl, boxr, boxt, boxb, pad[4];
65 double align[2];
66 Eina_Size2D max;
67
68 efl_gfx_size_hint_margin_get(item->layout, &pad[0], &pad[1], &pad[2], &pad[3]);
69 evas_object_geometry_get(pd->modeler, &boxx, &boxy, &boxw, &boxh);
70 efl_gfx_size_hint_margin_get(pd->modeler, &boxl, &boxr, &boxt, &boxb);
71 efl_gfx_size_hint_align_get(item->layout, &align[0], &align[1]);
72 max = efl_gfx_size_hint_max_get(item->layout);
73
74 // box outer margin
75 boxw -= boxl + boxr;
76 boxh -= boxt + boxb;
77 boxx += boxl;
78 boxy += boxt;
79
80 if (align[0] < 0) align[0] = -1;
81 if (align[1] < 0) align[1] = -1;
82 if (align[0] > 1) align[0] = 1;
83 if (align[1] > 1) align[1] = 1;
84
85 if (max.w <= 0) max.w = INT_MAX;
86 if (max.h <= 0) max.h = INT_MAX;
87 if (max.w < item->min.w) max.w = item->min.w;
88 if (max.h < item->min.h) max.h = item->min.h;
89
90 // horizontally
91 if (max.w < INT_MAX)
92 {
93 item->size.w = MIN(MAX(item->min.w - pad[0] - pad[1], max.w), boxw);
94 item->pos.x = boxx + pad[0];
95 }
96 else if (align[0] < 0)
97 {
98 // fill x
99 item->size.w = boxw - pad[0] - pad[1];
100 item->pos.x = boxx + pad[0];
101 }
102 else
103 {
104 item->size.w = item->min.w - pad[0] - pad[1];
105 item->pos.x = boxx + ((boxw - item->size.w) * align[0]) + pad[0];
106 }
107
108 // vertically
109 if (max.h < INT_MAX)
110 {
111 item->size.h = MIN(MAX(item->min.h - pad[2] - pad[3], max.h), boxh);
112 item->pos.y = boxy + pad[2];
113 }
114 else if (align[1] < 0)
115 {
116 // fill y
117 item->size.h = item->min.h - pad[2] - pad[3];
118 item->pos.y = boxy + pad[2];
119 }
120 else
121 {
122 item->size.h = item->min.h - pad[2] - pad[3];
123 item->pos.y = boxy + ((item->min.h - item->size.h) * align[1]) + pad[2];
124 }
125}
126
127static void
128_node_size_fix(Efl_Ui_Tree_View_Item* item, int sizediff)
129{
130 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata;
131 Efl_Ui_Tree_View_Seg_Array_Node *node;
132 Efl_Ui_Tree_View_Item *parent;
133
134 if (!item || !item->parent)
135 return;
136
137 parent = item->parent;
138 node = parent->tree_node;
139 if (node && node->layout_data)
140 {
141 nodedata = node->layout_data;
142 nodedata->min.h += sizediff;
143 }
144
145 parent->children_min.h += sizediff;
146 if (parent->children_min.h < 0) parent->children_min.h = 0;
147
148 _node_size_fix(parent, sizediff);
149}
150
151static void
152_item_min_calc(Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Ui_Tree_View_Item* item
153 , Eina_Size2D min, Efl_Ui_Tree_View_Seg_Array_Node *itemnode
154 , Efl_Ui_Tree_View_Seg_Array *segarray)
155{
156 EINA_SAFETY_ON_NULL_RETURN(pd);
157 EINA_SAFETY_ON_NULL_RETURN(item);
158 EINA_SAFETY_ON_NULL_RETURN(itemnode);
159 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata = itemnode->layout_data;
160 Efl_Ui_Tree_View_Item *litem;
161 int i, pad[4];
162
163 efl_gfx_size_hint_margin_get(item->layout, &pad[0], &pad[1], &pad[2], &pad[3]);
164 min.w += pad[0] + pad[1];
165 min.h += pad[2] + pad[3];
166
167 if (item->min.h == min.h && item->min.w == min.w)
168 return;
169
170 pd->min.h += min.h - item->min.h;
171 nodedata->min.h += min.h - item->min.h;
172
173 if (nodedata->min.w <= min.w)
174 nodedata->min.w = min.w;
175 else if (nodedata->min.w == item->min.w)
176 {
177 nodedata->min.w = 0;
178 for (i = 0; i != itemnode->length; ++i)
179 {
180 litem = (Efl_Ui_Tree_View_Item *)itemnode->pointers[i];
181 if (nodedata->min.w < litem->min.w)
182 nodedata->min.w = litem->min.w;
183 if (item->min.w == litem->min.w)
184 break;
185 }
186 }
187
188 if (pd->min.w <= min.w)
189 pd->min.w = min.w;
190 else if (pd->min.w == item->min.w)
191 {
192 Efl_Ui_Tree_View_Seg_Array_Node *node2;
193 Eina_Accessor *nodes = efl_ui_tree_view_seg_array_node_accessor_get(segarray);
194 pd->min.w = min.w;
195
196 EINA_ACCESSOR_FOREACH(nodes, i, node2)
197 {
198 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata2 = node2->layout_data;
199 if (pd->min.w < nodedata2->min.w)
200 pd->min.w = nodedata2->min.w;
201
202 if (item->min.w == nodedata2->min.w)
203 break;
204 }
205 eina_accessor_free(nodes);
206 }
207
208 _node_size_fix(item, (min.h - item->min.h));
209
210 item->min.w = min.w;
211 item->min.h = min.h;
212 _item_size_calc(pd, item);
213}
214
215static void
216_on_item_size_hint_change(void *data, Evas *e EINA_UNUSED,
217 Evas_Object *obj, void *event_info EINA_UNUSED)
218{
219 Efl_Ui_Tree_View_Layouter_Callback_Data *cb_data = data;
220 EINA_SAFETY_ON_NULL_RETURN(cb_data);
221 Efl_Ui_Tree_View_Layouter_Data *pd = cb_data->pd;
222 EINA_SAFETY_ON_NULL_RETURN(pd);
223 Efl_Ui_Tree_View_Item *item = cb_data->item;;
224 EINA_SAFETY_ON_NULL_RETURN(item);
225 Efl_Ui_Tree_View_Seg_Array_Node *node = item->tree_node;
226 EINA_SAFETY_ON_NULL_RETURN(node);
227 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata = node->layout_data;
228 EINA_SAFETY_ON_NULL_RETURN(nodedata);
229
230 Eina_Size2D min = efl_gfx_size_hint_combined_min_get(obj);
231 if (item->parent)
232 {
233 Efl_Ui_Tree_View_Item *parent = item->parent;
234 _item_min_calc(pd, item, min, node, parent->segarray);
235 }
236 else
237 _item_min_calc(pd, item, min, node, pd->segarray);
238
239 if (!nodedata->realized)
240 free(evas_object_event_callback_del(item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change));
241}
242
243static Eina_Value
244_children_get(void *data, Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
245{
246 Efl_Model *children;
247 unsigned int i, len;
248 Request *r = data;
249
250 if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ERROR)
251 goto on_error;
252
253 if (eina_value_type_get(&v) == EINA_VALUE_TYPE_OBJECT)
254 {
255 children = eina_value_object_get(&v);
256 efl_ui_tree_view_seg_array_insert(r->pd->segarray, NULL, r->index, children);
257 }
258 else if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ARRAY)
259 {
260 EINA_VALUE_ARRAY_FOREACH(&v, len, i, children)
261 {
262 unsigned int idx = r->index + i;
263 efl_ui_tree_view_seg_array_insert(r->pd->segarray, NULL, idx, children);
264 }
265 }
266
267 r->pd->recalc = EINA_TRUE;
268 evas_object_smart_changed(r->pd->modeler);
269
270 on_error:
271 free(r);
272 return v;
273}
274
275static void
276_on_modeler_resize(void *data, Evas *e EINA_UNUSED,
277 Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
278{
279 Efl_Ui_Tree_View_Layouter_Data *pd = data;
280 pd->resize = EINA_TRUE;
281}
282
283static void
284_child_added_cb(void *data, const Efl_Event *event)
285{
286 Efl_Model_Children_Event* evt = event->info;
287 Efl_Ui_Tree_View_Layouter_Data *pd = data;
288 Eina_Future *f;
289 Request *r;
290
291 r = calloc(1, sizeof (Request));
292 if (!r) return;
293
294 r->index = evt->index;
295 r->pd = pd;
296
297 f = efl_model_children_slice_get(pd->model, evt->index, 1);
298 f = eina_future_then(f, _children_get, r, NULL);
299}
300
301static void
302_node_realize(Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Ui_Tree_View_Seg_Array_Node *node)
303{
304 Efl_Ui_Tree_View_Item* item;
305 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata = node->layout_data;
306 int i;
307
308 EINA_SAFETY_ON_NULL_RETURN(nodedata);
309 if (nodedata->realized)
310 return;
311
312 nodedata->realized = EINA_TRUE;
313
314 for (i = 0; i != node->length; ++i)
315 {
316 item = (Efl_Ui_Tree_View_Item *)node->pointers[i];
317 efl_ui_tree_view_model_realize(pd->modeler, item);
318 }
319}
320
321void
322_node_unrealize(Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Ui_Tree_View_Seg_Array_Node *node, Eina_Bool is_free)
323{
324 Efl_Ui_Tree_View_Seg_Array_Node *s_node;
325 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata;
326 Efl_Ui_Tree_View_Item* item;
327 int i, j;
328
329 EINA_SAFETY_ON_NULL_RETURN(node);
330 EINA_SAFETY_ON_NULL_RETURN(node->layout_data);
331
332 nodedata = node->layout_data;
333 if (!nodedata->realized)
334 return;
335
336 nodedata->realized = EINA_FALSE;
337 for (i = 0; i != node->length; ++i)
338 {
339 item = (Efl_Ui_Tree_View_Item *)node->pointers[i];
340 if (item->expanded && item->segarray)
341 {
342 Eina_Accessor *nodes = efl_ui_tree_view_seg_array_node_accessor_get(item->segarray);
343 EINA_ACCESSOR_FOREACH(nodes, j, s_node)
344 {
345 _node_unrealize(pd, s_node, is_free);
346 }
347 eina_accessor_free(nodes);
348 }
349
350 if (item->layout)
351 {
352 free(evas_object_event_callback_del(item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change));
353 efl_ui_tree_view_model_unrealize(pd->modeler, item);
354 }
355 }
356
357 if (is_free)
358 {
359 free(node->layout_data);
360 node->layout_data = NULL;
361 }
362}
363
364static void
365_child_count_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
366{
367 Efl_Ui_Tree_View_Layouter_Data *pd = data;
368 pd->count_total = efl_model_children_count_get(pd->model);
369 if (pd->count_total)
370 efl_event_callback_del(pd->model, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, _child_count_changed_cb, pd);
371}
372
373static Eina_Bool
374_initilize(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Ui_Tree_View_Model *modeler)
375{
376 if (pd->initialized)
377 return EINA_TRUE;
378
379 efl_replace(&pd->modeler, modeler);
380
381 if (!pd->model || !pd->modeler)
382 return EINA_FALSE;
383
384 pd->recalc = EINA_TRUE;
385 pd->initialized = EINA_TRUE;
386
387 efl_ui_tree_view_model_load_range_set(pd->modeler, 0, pd->count_total); // load all
388 efl_event_callback_add(pd->model, EFL_MODEL_EVENT_CHILD_ADDED, _child_added_cb, pd);
389
390 evas_object_event_callback_add(pd->modeler, EVAS_CALLBACK_RESIZE, _on_modeler_resize, pd);
391 pd->min.w = 0;
392 pd->min.h = 0;
393
394 return EINA_TRUE;
395}
396
397static void
398_finalize(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Layouter_Data *pd)
399{
400 Efl_Ui_Tree_View_Seg_Array_Node* node;
401 int i;
402
403 if (pd->segarray)
404 {
405 Eina_Accessor *nodes = efl_ui_tree_view_seg_array_node_accessor_get(pd->segarray);
406 EINA_ACCESSOR_FOREACH(nodes, i, node)
407 {
408 _node_unrealize(pd, node, EINA_TRUE);
409 }
410 eina_accessor_free(nodes);
411 }
412
413 if (pd->model)
414 {
415 efl_event_callback_del(pd->model, EFL_MODEL_EVENT_CHILD_ADDED, _child_added_cb, pd);
416 pd->count_total = 0;
417 }
418
419 if (pd->modeler)
420 {
421 evas_object_event_callback_del_full(pd->modeler, EVAS_CALLBACK_RESIZE, _on_modeler_resize, pd);
422 efl_ui_tree_view_model_min_size_set(pd->modeler, pd->min);
423 }
424
425 pd->min.w = 0;
426 pd->min.h = 0;
427 efl_replace(&pd->modeler, NULL);
428 pd->segarray = NULL;
429 pd->initialized = EINA_FALSE;
430 pd->recalc = EINA_TRUE;
431}
432
433static void
434_calc_range(Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Ui_Tree_View_Seg_Array *segarray, Evas_Coord cur_pos)
435{
436 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata;
437 Efl_Ui_Tree_View_Seg_Array_Node *node;
438 Eina_Position2D spos;
439 Evas_Coord ny;
440 Eina_Rect vgmt;
441 int i;
442
443 vgmt = efl_ui_scrollable_viewport_geometry_get(pd->modeler);
444 spos = efl_ui_scrollable_content_pos_get(pd->modeler);
445 ny = spos.y - (vgmt.h / 2);
446 if (ny < 0) spos.y = 0;
447 else spos.y = ny;
448 vgmt.h *= 2;
449
450 Eina_Accessor *nodes = efl_ui_tree_view_seg_array_node_accessor_get(segarray);
451 EINA_ACCESSOR_FOREACH(nodes, i, node)
452 {
453 nodedata = node->layout_data;
454 if (!nodedata || !nodedata->min.h)
455 continue;
456
457 if ((cur_pos > spos.y || nodedata->min.h + cur_pos > spos.y) && (cur_pos < (spos.y + vgmt.h) || nodedata->min.h + cur_pos < spos.y + vgmt.h))
458 _node_realize(pd, node);
459 else
460 _node_unrealize(pd, node, EINA_FALSE);
461
462 cur_pos += nodedata->min.h;
463 }
464 eina_accessor_free(nodes);
465}
466
467static void
468_calc_size_segarray(Efl_Ui_Tree_View_Layouter_Data* pd, Efl_Ui_Tree_View_Seg_Array *segarray)
469{
470 EINA_SAFETY_ON_NULL_RETURN(pd);
471 EINA_SAFETY_ON_NULL_RETURN(segarray);
472 Efl_Ui_Tree_View_Seg_Array_Node *node;
473 Efl_Ui_Tree_View_Item *item;
474 int i, j = 0, count;
475
476 Eina_Accessor *nodes = efl_ui_tree_view_seg_array_node_accessor_get(segarray);
477 while (eina_accessor_data_get(nodes, j, (void **)&node))
478 {
479 ++j;
480 if (!node->layout_data)
481 node->layout_data = calloc(1, sizeof(Efl_Ui_Tree_View_Layouter_Node_Data));
482
483 if (j == 1)
484 {
485 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata = node->layout_data;
486 nodedata->realized = EINA_TRUE;
487 }
488
489 for (i = 0; i != node->length; ++i)
490 {
491 item = (Efl_Ui_Tree_View_Item *)node->pointers[i];
492 EINA_SAFETY_ON_NULL_RETURN(item);
493
494 // cache size of new items
495 if ((item->min.w == 0) && (item->min.h == 0) && !item->layout)
496 efl_ui_tree_view_model_realize(pd->modeler, item);
497/*
498 count = efl_model_children_count_get(item->model);
499 if (count && !item->expanded)
500 {
501 efl_ui_tree_view_model_expand(pd->modeler, item, 0, count);
502 }
503 else if (item->expanded && item->segarray)
504 {
505 _calc_size_segarray (pd, item->segarray);
506 } */
507 }
508 }
509 eina_accessor_free(nodes);
510}
511
512static void
513_calc_size_job(void *data)
514{
515 Efl_Ui_Tree_View_Layouter_Data *pd;
516 Eo *obj = data;
517 /* double start_time = ecore_time_get(); */
518
519 EINA_SAFETY_ON_NULL_RETURN(data);
520 pd = efl_data_scope_get(obj, MY_CLASS);
521 if (EINA_UNLIKELY(!pd)) return;
522
523 _calc_size_segarray(pd, pd->segarray);
524
525 pd->calc_job = NULL;
526 pd->recalc = EINA_FALSE;
527
528 evas_object_smart_changed(pd->modeler);
529}
530
531EOLIAN static Efl_Object *
532_efl_ui_tree_view_layouter_efl_object_constructor(Eo *obj, Efl_Ui_Tree_View_Layouter_Data *pd)
533{
534 obj = efl_constructor(efl_super(obj, MY_CLASS));
535 pd->initialized = EINA_FALSE;
536
537 return obj;
538}
539
540EOLIAN static void
541_efl_ui_tree_view_layouter_efl_ui_tree_view_relayout_content_created(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Ui_Tree_View_Item *item)
542{
543 Efl_Ui_Tree_View_Layouter_Callback_Data *cb_data;
544 EINA_SAFETY_ON_NULL_RETURN(item);
545 EINA_SAFETY_ON_NULL_RETURN(item->layout);
546 Efl_Ui_Tree_View_Seg_Array_Node *node = item->tree_node;
547 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata = node->layout_data;
548
549 Eina_Size2D min = efl_gfx_size_hint_combined_min_get(item->layout);
550 _item_min_calc(pd, item, min, node, pd->segarray);
551
552 if (min.w && min.h && !nodedata->realized)
553 {
554 efl_ui_tree_view_model_unrealize(pd->modeler, item);
555 return;
556 }
557
558 cb_data = calloc(1, sizeof(Efl_Ui_Tree_View_Layouter_Callback_Data));
559 cb_data->pd = pd;
560 cb_data->item = item;
561 evas_object_event_callback_add(item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change, cb_data);
562
563 _item_size_calc(pd, item);
564}
565
566EOLIAN static Eina_List *
567_efl_ui_tree_view_layouter_efl_ui_tree_view_relayout_elements_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Layouter_Data *pd)
568{
569 Eina_List *elements_order = NULL;
570 Efl_Ui_Tree_View_Item* item;
571 Efl_Ui_Tree_View_Seg_Array_Node *items_node;
572 int i, j;
573
574 Eina_Accessor *nodes = efl_ui_tree_view_seg_array_node_accessor_get(pd->segarray);
575 EINA_ACCESSOR_FOREACH(nodes, i, items_node)
576 {
577 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata = items_node->layout_data;
578 if (!nodedata || !nodedata->realized)
579 continue;
580
581 for (j = 0; j != items_node->length; ++j)
582 {
583 item = (Efl_Ui_Tree_View_Item *)items_node->pointers[j];
584 if (item->layout)
585 elements_order = eina_list_append(elements_order, item->layout);
586 }
587 }
588 eina_accessor_free(nodes);
589 return elements_order;
590}
591
592EOLIAN static void
593_efl_ui_tree_view_layouter_efl_ui_tree_view_relayout_model_set(Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Model *model)
594{
595 _finalize(obj, pd);
596
597 efl_replace(&pd->model, model);
598 if (pd->model)
599 {
600 pd->count_total = efl_model_children_count_get(pd->model);
601 if (pd->count_total && pd->modeler)
602 efl_ui_tree_view_model_load_range_set(pd->modeler, 0, pd->count_total); // load all
603 else
604 efl_event_callback_add(pd->model, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, _child_count_changed_cb, pd);
605 }
606}
607
608static void
609_node_draw(Efl_Ui_Tree_View_Layouter_Data *pd, Efl_Ui_Tree_View_Seg_Array *segarray, Draw_Data *drawdata)
610{
611 Efl_Ui_Tree_View_Seg_Array_Node *items_node;
612 Efl_Ui_Tree_View_Item* item;
613 int i, j;
614
615 _calc_range(pd, segarray, drawdata->cur_pos);
616
617 Eina_Accessor *nodes = efl_ui_tree_view_seg_array_node_accessor_get(segarray);
618 EINA_SAFETY_ON_NULL_RETURN(nodes);
619 EINA_ACCESSOR_FOREACH(nodes, i, items_node)
620 {
621 Efl_Ui_Tree_View_Layouter_Node_Data *nodedata = items_node->layout_data;
622 if (!nodedata) continue;
623
624 if (nodedata->realized)
625 for (j = 0; j != items_node->length;++j)
626 {
627 double x, y, w, h;
628 double weight_x, weight_y;
629 item = (Efl_Ui_Tree_View_Item *)items_node->pointers[j];
630 EINA_SAFETY_ON_NULL_RETURN(item);
631
632 if (item->layout)
633 {
634 if (pd->resize)
635 _item_size_calc(pd, item);
636
637 efl_gfx_size_hint_weight_get(item->layout, &weight_x, &weight_y);
638 // extra rounding up (compensate cumulative error)
639 if ((i == (pd->count_total - 1)) && (drawdata->cur_pos - floor(drawdata->cur_pos) >= 0.5))
640 drawdata->rounding = 1;
641
642 x = item->pos.x;
643 y = item->pos.y + drawdata->cur_pos;
644 w = item->size.w;
645 h = item->size.h + drawdata->rounding + weight_y * drawdata->extra;
646 drawdata->cur_pos += h;
647
648 if (w < pd->min.w) w = pd->min.w;
649 if (w > drawdata->vgmt.w) w = drawdata->vgmt.w;
650
651 evas_object_geometry_set(item->layout, (x + 0 - drawdata->spos.x), (y + 0 - drawdata->spos.y), w, h);
652 }
653 else
654 {
655 drawdata->cur_pos += item->size.h;
656 }
657
658 if (item->expanded && item->segarray)
659 _node_draw(pd, item->segarray, drawdata);
660 }
661 else
662 drawdata->cur_pos += nodedata->min.h;
663 }
664 eina_accessor_free(nodes);
665}
666
667static void
668_efl_ui_tree_view_relayout_layout_do(Efl_Ui_Tree_View_Layouter_Data *pd)
669{
670 int boxx, boxy, boxw, boxh;
671 int boxl = 0, boxr = 0, boxt = 0, boxb = 0;
672 Draw_Data drawdata;
673 memset(&drawdata, 0, sizeof(drawdata));
674
675 evas_object_geometry_get(pd->modeler, &boxx, &boxy, &boxw, &boxh);
676 efl_gfx_size_hint_margin_get(pd->modeler, &boxl, &boxr, &boxt, &boxb);
677
678 // box outer margin
679 boxw -= boxl + boxr;
680 boxh -= boxt + boxb;
681 boxx += boxl;
682 boxy += boxt;
683
684 drawdata.extra = boxh - pd->min.h;
685 if (drawdata.extra < 0) drawdata.extra = 0;
686
687 efl_ui_tree_view_model_min_size_set(pd->modeler, pd->min);
688 drawdata.vgmt = efl_ui_scrollable_viewport_geometry_get(pd->modeler);
689 drawdata.spos = efl_ui_scrollable_content_pos_get(pd->modeler);
690
691 _node_draw(pd, pd->segarray, &drawdata);
692 pd->resize = EINA_FALSE;
693}
694
695EOLIAN static void
696_efl_ui_tree_view_layouter_efl_ui_tree_view_relayout_layout_do
697 (Eo *obj EINA_UNUSED, Efl_Ui_Tree_View_Layouter_Data *pd
698 , Efl_Ui_Tree_View_Model *modeler, int first EINA_UNUSED, Efl_Ui_Tree_View_Seg_Array *segarray)
699{
700 int count;
701
702 if (!_initilize(obj, pd, modeler))
703 return;
704
705 pd->segarray = segarray;
706 if (!pd->segarray)
707 return;
708
709 count = efl_ui_tree_view_seg_array_count(pd->segarray);
710
711 if ((pd->recalc && count > 0) || pd->count_segarray != count)
712 {
713 // cache size of new items
714 pd->count_segarray = count;
715 ecore_job_del(pd->calc_job);
716 pd->calc_job = ecore_job_add(_calc_size_job, obj);
717 return;
718 }
719 _efl_ui_tree_view_relayout_layout_do(pd);
720}
721
722#include "efl_ui_tree_view_layouter.eo.c"
diff --git a/src/lib/elementary/efl_ui_tree_view_layouter.eo b/src/lib/elementary/efl_ui_tree_view_layouter.eo
new file mode 100644
index 0000000000..a4db60757b
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_layouter.eo
@@ -0,0 +1,10 @@
1class Efl.Ui.Tree_View_Layouter extends Efl.Object implements Efl.Ui.Tree_View_Relayout
2{
3 implements {
4 Efl.Object.constructor;
5 Efl.Ui.Tree_View_Relayout.layout_do;
6 Efl.Ui.Tree_View_Relayout.content_created;
7 Efl.Ui.Tree_View_Relayout.model { set; }
8 Efl.Ui.Tree_View_Relayout.elements { get; }
9 }
10}
diff --git a/src/lib/elementary/efl_ui_tree_view_model.eo b/src/lib/elementary/efl_ui_tree_view_model.eo
new file mode 100644
index 0000000000..a39b9977a5
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_model.eo
@@ -0,0 +1,68 @@
1struct Efl.Ui.Tree_View_Item {
2 layout: Efl.Ui.Layout;
3 layout_request: future<Efl.Ui.Layout>;
4 model: Efl.Model;
5 linearized_offset: int; [[model index]]
6 shallow_offset: int;
7 depth: int;
8 children_count: int; [[ Number of indirect children ]]
9 children_min: Eina.Size2D;
10 children_size: Eina.Size2D;
11 parent: void_ptr; [[Efl.Ui.Tree_View_Item parent]]
12 tree_node: void_ptr;
13 segarray: ptr(Efl_Ui_Tree_View_Seg_Array);
14 expanded: bool;
15 min: Eina.Size2D;
16 size: Eina.Size2D;
17 pos: Eina.Position2D;
18}
19
20interface Efl.Ui.Tree_View_Model extends Efl.Interface
21{
22 methods {
23 @property load_range {
24 set {}
25 values {
26 first: int;
27 count: int;
28 }
29 }
30 realize {
31 params {
32 item: ptr(Efl.Ui.Tree_View_Item);
33 }
34 return: ptr(Efl.Ui.Tree_View_Item);
35 }
36 unrealize {
37 params {
38 item: ptr(Efl.Ui.Tree_View_Item);
39 }
40 }
41 expand {
42 params {
43 item: ptr(Efl.Ui.Tree_View_Item);
44 first: int;
45 count: int;
46 }
47 }
48 contract {
49 params {
50 item: ptr(Efl.Ui.Tree_View_Item);
51 }
52 }
53 @property model_size {
54 get {}
55 values {
56 s: int;
57 }
58 }
59 @property min_size {
60 [[Minimal content size.]]
61 set {}
62 get {}
63 values {
64 min: Eina.Size2D;
65 }
66 }
67 }
68}
diff --git a/src/lib/elementary/efl_ui_tree_view_pan.eo b/src/lib/elementary/efl_ui_tree_view_pan.eo
new file mode 100644
index 0000000000..90ef89470c
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_pan.eo
@@ -0,0 +1,12 @@
1class Efl.Ui.Tree_View_Pan extends Efl.Ui.Pan
2{
3 [[Elementary Efl_Ui_Tree_View pan class]]
4 implements {
5 Efl.Object.destructor;
6 Efl.Ui.Pan.content_size { get; }
7 Efl.Ui.Pan.pan_position { get; set; }
8 Efl.Ui.Pan.pan_position_min { get; }
9 Efl.Ui.Pan.pan_position_max { get; }
10 Efl.Canvas.Group.group_calculate;
11 }
12}
diff --git a/src/lib/elementary/efl_ui_tree_view_private.h b/src/lib/elementary/efl_ui_tree_view_private.h
new file mode 100644
index 0000000000..bb99f1253f
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_private.h
@@ -0,0 +1,73 @@
1#ifndef EFL_UI_TREE_VIEW_PRIVATE_H
2#define EFL_UI_TREE_VIEW_PRIVATE_H
3
4#ifdef HAVE_CONFIG_H
5# include "elementary_config.h"
6#endif
7
8#include <Elementary.h>
9#include "elm_priv.h"
10
11#include "efl_ui_tree_view.eo.h"
12#include "efl_ui_tree_view_layouter.eo.h"
13
14#include <assert.h>
15
16typedef struct _Efl_Ui_Tree_View_Data Efl_Ui_Tree_View_Data;
17#include "efl_ui_tree_view_seg_array.h"
18
19struct _Efl_Ui_Tree_View_Data
20{
21 Eo *obj;
22 Eo *scrl_mgr;
23 Efl_Ui_Tree_View_Pan *pan_obj;
24 Efl_Model *model;
25
26 struct {
27 Eina_Future *future;
28
29 int start;
30 int count;
31 } slice;
32
33 Efl_Ui_Layout_Factory *factory;
34 Eina_List *selected_items;
35 Efl_Ui_Focus_Manager *manager;
36 Efl_Ui_Tree_View_Relayout *layouter;
37 Efl_Ui_Tree_View_Seg_Array *segarray;
38 int segarray_first;
39
40 Eina_Size2D min;
41 Eina_Bool scrl_freeze : 1;
42 Eina_Bool show_root: 1;
43};
44
45typedef struct _Efl_Ui_Tree_View_Pan_Data Efl_Ui_Tree_View_Pan_Data;
46struct _Efl_Ui_Tree_View_Pan_Data
47{
48 Eo *wobj;
49 Eina_Rect gmt;
50};
51
52#define EFL_UI_TREE_VIEW_DATA_GET(o, ptr) \
53 Efl_Ui_Tree_View_Data * ptr = efl_data_scope_get(o, EFL_UI_TREE_VIEW_CLASS)
54
55#define EFL_UI_TREE_VIEW_DATA_GET_OR_RETURN(o, ptr) \
56 EFL_UI_TREE_VIEW_DATA_GET(o, ptr); \
57 if (EINA_UNLIKELY(!ptr)) \
58 { \
59 ERR("No widget data for object %p (%s)", \
60 o, evas_object_type_get(o)); \
61 return; \
62 }
63
64#define EFL_UI_TREE_VIEW_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
65 EFL_UI_TREE_VIEW_DATA_GET(o, ptr); \
66 if (EINA_UNLIKELY(!ptr)) \
67 { \
68 ERR("No widget data for object %p (%s)", \
69 o, evas_object_type_get(o)); \
70 return val; \
71 }
72
73#endif
diff --git a/src/lib/elementary/efl_ui_tree_view_relayout.eo b/src/lib/elementary/efl_ui_tree_view_relayout.eo
new file mode 100644
index 0000000000..1188456aa6
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_relayout.eo
@@ -0,0 +1,30 @@
1interface Efl.Ui.Tree_View_Relayout extends Efl.Interface
2{
3 methods {
4 layout_do {
5 params {
6 modeler: Efl.Ui.Tree_View_Model;
7 first: int;
8 children: ptr(Efl_Ui_Tree_View_Seg_Array);
9 }
10 }
11 content_created {
12 params {
13 item: ptr(Efl.Ui.Tree_View_Item);
14 }
15 }
16 @property model {
17 [[Model that is/will be ]]
18 set {}
19 values {
20 model: Efl.Model; [[Efl model]]
21 }
22 }
23 @property elements {
24 get {}
25 values {
26 elements: list<Efl.Gfx.Entity>; [[The order to use]]
27 }
28 }
29 }
30}
diff --git a/src/lib/elementary/efl_ui_tree_view_seg_array.c b/src/lib/elementary/efl_ui_tree_view_seg_array.c
new file mode 100644
index 0000000000..07c2034d4d
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_seg_array.c
@@ -0,0 +1,469 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Efl.h>
6#include <assert.h>
7
8#include <Elementary.h>
9#include "elm_priv.h"
10
11#define MY_CLASS EFL_UI_TREE_VIEW_SEG_ARRAY_CLASS
12#define MY_CLASS_NAME "Efl.Ui.Tree_View_Seg_Array"
13
14#include "efl_ui_tree_view_seg_array.h"
15
16static int _shallow_search_lookup_cb(Eina_Rbtree const* rbtree, const void* key, int length EINA_UNUSED, void* data EINA_UNUSED)
17{
18 Efl_Ui_Tree_View_Seg_Array_Node const* node = (void const*)rbtree;
19 int index = *(int*)key;
20 if (index < node->shallow_first_index)
21 {
22 return 1;
23 }
24 else if (index < node->shallow_first_index + node->length)
25 {
26 return 0;
27 }
28 else
29 {
30 return -1;
31 }
32}
33
34static Eina_Rbtree_Direction _shallow_rbtree_compare(Efl_Ui_Tree_View_Seg_Array_Node const* left,
35 Efl_Ui_Tree_View_Seg_Array_Node const* right, void* data EINA_UNUSED)
36{
37 if (left->shallow_first_index < right->shallow_first_index)
38 return EINA_RBTREE_LEFT;
39 else
40 return EINA_RBTREE_RIGHT;
41}
42
43static void
44_free_node(Efl_Ui_Tree_View_Seg_Array_Node* node, void* data EINA_UNUSED)
45{
46 int i = 0;
47
48 while (i < node->length)
49 {
50 Efl_Ui_Tree_View_Item* item = node->pointers[i];
51 if (item->segarray)
52 {
53 efl_ui_tree_view_seg_array_free(item->segarray);
54 }
55 efl_unref(item->model);
56 free(item);
57 ++i;
58 }
59
60 free(node);
61}
62
63static Efl_Ui_Tree_View_Seg_Array_Node*
64_alloc_node(Efl_Ui_Tree_View_Seg_Array* seg_array, int shallow_first_index, int linearized_first_index)
65{
66 Efl_Ui_Tree_View_Seg_Array_Node* node;
67 node = calloc(1, sizeof(Efl_Ui_Tree_View_Seg_Array_Node) + seg_array->step_size*sizeof(Efl_Ui_Tree_View_Item*));
68 node->linearized_first_index = linearized_first_index;
69 node->shallow_first_index = shallow_first_index;
70 node->max = seg_array->step_size;
71 node->seg_array = seg_array;
72 seg_array->root = (void*)eina_rbtree_inline_insert(EINA_RBTREE_GET(seg_array->root), EINA_RBTREE_GET(node),
73 EINA_RBTREE_CMP_NODE_CB(&_shallow_rbtree_compare), NULL);
74 seg_array->node_count++;
75 return node;
76}
77
78static Efl_Ui_Tree_View_Item* _create_item_partial(Efl_Model* model, Efl_Ui_Tree_View_Item* parent)
79{
80 Eina_Value *v;
81 Efl_Ui_Tree_View_Item* item;
82
83 item = calloc(1, sizeof(Efl_Ui_Tree_View_Item));
84 item->parent = parent;
85 item->depth = 1;
86
87 if (parent)
88 item->depth += parent->depth;
89
90 v = eina_value_uint_new(item->depth);
91 item->model = efl_new(EFL_UI_TREE_VIEW_SEG_ARRAY_DEPTH_MODEL_CLASS,
92 efl_ui_view_model_set(efl_added, model),
93 efl_model_property_set(efl_added, "depth", v));
94 eina_value_free(v);
95
96 return item;
97}
98
99static void
100_efl_ui_tree_view_seg_array_insert_at_node(Efl_Ui_Tree_View_Seg_Array* seg_array, int shallow_index, Efl_Ui_Tree_View_Item* item, Efl_Ui_Tree_View_Seg_Array_Node* node)
101{
102 Efl_Ui_Tree_View_Seg_Array_Node* before_node;
103 int shallow_index_pred, pos = 0;
104 Eina_Iterator* iterator;
105
106 assert (item->shallow_offset == 0);
107 assert (item->linearized_offset == 0);
108
109 if (node && node->length != node->max && (shallow_index - node->shallow_first_index) <= node->length)
110 {
111 assert(node->length != node->max);
112
113 pos = shallow_index - node->shallow_first_index;
114 item->tree_node = node;
115 item->shallow_offset = pos;
116
117 assert(pos == node->length);
118 if (pos < node->length)
119 memmove(&node->pointers[pos], &node->pointers[pos+1], sizeof(node->pointers[pos])*(node->length - pos));
120
121 node->pointers[pos] = item;
122 if (pos)
123 item->linearized_offset = node->pointers[pos-1]->linearized_offset + node->pointers[pos-1]->children_count + 1;
124
125 node->length++;
126 }
127 else
128 {
129 node = _alloc_node(seg_array, shallow_index, 0u);
130 node->pointers[0] = item;
131 node->length++;
132 item->shallow_offset = 0;
133 item->tree_node = node;
134
135 shallow_index_pred = shallow_index ? shallow_index - 1 : 0;
136
137 before_node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(seg_array->root),
138 &shallow_index_pred, sizeof(shallow_index_pred),
139 &_shallow_search_lookup_cb, NULL);
140 if (before_node == node)
141 {
142 node->linearized_first_index = 0u;
143 assert (node->shallow_first_index == 0);
144 }
145 else
146 {
147 assert (node->shallow_first_index > before_node->shallow_first_index);
148 assert (node->shallow_first_index == before_node->shallow_first_index
149 + before_node->pointers[before_node->length-1]->shallow_offset + 1);
150 node->linearized_first_index = before_node->linearized_first_index;
151 if (before_node->length)
152 node->linearized_first_index += before_node->pointers[before_node->length-1]->linearized_offset
153 + before_node->pointers[before_node->length-1]->children_count + 1;
154 }
155 }
156
157 int i = node->linearized_first_index;
158 iterator = eina_rbtree_iterator_infix((void*)seg_array->root);
159 while (eina_iterator_next(iterator, (void**)&node))
160 if (node->linearized_first_index > i)
161 {
162 node->shallow_first_index++;
163 node->linearized_first_index++;
164 }
165 eina_iterator_free(iterator);
166 seg_array->count++;
167}
168
169typedef struct _Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow
170{
171 Eina_Accessor vtable;
172 Efl_Ui_Tree_View_Seg_Array* segarray;
173} Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow;
174
175static Eina_Bool
176_efl_ui_tree_view_seg_array_accessor_shallow_get_at(Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow* acc,
177 int idx, void** data)
178{
179 Efl_Ui_Tree_View_Seg_Array_Node* node;
180 node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(acc->segarray->root),
181 &idx, sizeof(idx), &_shallow_search_lookup_cb, NULL);
182 if (node && (node->shallow_first_index <= idx && node->shallow_first_index + node->length > idx))
183 {
184 int i = idx - node->shallow_first_index;
185 Efl_Ui_Tree_View_Item* item = node->pointers[i];
186 *data = item;
187 return EINA_TRUE;
188 }
189 return EINA_FALSE;
190}
191
192static void*
193_efl_ui_tree_view_seg_array_accessor_shallow_get_container(Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow* acc EINA_UNUSED)
194{
195 return NULL;
196}
197
198static void
199_efl_ui_tree_view_seg_array_accessor_shallow_free(Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow* acc EINA_UNUSED)
200{
201 free(acc);
202}
203
204static Eina_Bool
205_efl_ui_tree_view_seg_array_accessor_shallow_lock(Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow* acc EINA_UNUSED)
206{
207 return EINA_FALSE;
208}
209
210static Eina_Bool
211_efl_ui_tree_view_seg_array_accessor_shallow_unlock(Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow* acc EINA_UNUSED)
212{
213 return EINA_FALSE;
214}
215
216static Eina_Accessor*
217_efl_ui_tree_view_seg_array_accessor_shallow_clone(Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow* acc EINA_UNUSED)
218{
219 return &acc->vtable;
220}
221
222static void
223_efl_ui_tree_view_seg_array_accessor_shallow_setup(Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow* acc, Efl_Ui_Tree_View_Seg_Array* segarray)
224{
225 EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR);
226 acc->vtable.version = EINA_ACCESSOR_VERSION;
227 acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(_efl_ui_tree_view_seg_array_accessor_shallow_get_at);
228 acc->vtable.get_container = FUNC_ACCESSOR_GET_CONTAINER(_efl_ui_tree_view_seg_array_accessor_shallow_get_container);
229 acc->vtable.free = FUNC_ACCESSOR_FREE(_efl_ui_tree_view_seg_array_accessor_shallow_free);
230 acc->vtable.lock = FUNC_ACCESSOR_LOCK(_efl_ui_tree_view_seg_array_accessor_shallow_lock);
231 acc->vtable.unlock = FUNC_ACCESSOR_LOCK(_efl_ui_tree_view_seg_array_accessor_shallow_unlock);
232 acc->vtable.clone = FUNC_ACCESSOR_CLONE(_efl_ui_tree_view_seg_array_accessor_shallow_clone);
233 acc->segarray = segarray;
234}
235
236typedef struct _Efl_Ui_Tree_View_Segarray_Node_Accessor
237{
238 Eina_Accessor vtable;
239 Efl_Ui_Tree_View_Seg_Array* segarray;
240 Eina_Iterator* pre_iterator;
241 Efl_Ui_Tree_View_Seg_Array_Node* current_node;
242 int current_index;
243} Efl_Ui_Tree_View_Segarray_Node_Accessor;
244
245static Eina_Bool
246_efl_ui_tree_view_seg_array_node_accessor_get_at(Efl_Ui_Tree_View_Segarray_Node_Accessor* acc,
247 int idx, void** data)
248{
249 if (idx == acc->current_index && acc->current_node)
250 {
251 (*data) = acc->current_node;
252 }
253 else
254 {
255 if (acc->current_index >= idx || !acc->current_node)
256 {
257 eina_iterator_free(acc->pre_iterator);
258 acc->pre_iterator = NULL;
259 acc->current_node = NULL;
260 acc->current_index = -1;
261 }
262
263 if (!acc->pre_iterator)
264 acc->pre_iterator = eina_rbtree_iterator_infix((void*)acc->segarray->root);
265
266 for (;acc->current_index != idx;++acc->current_index)
267 {
268 if (!eina_iterator_next(acc->pre_iterator, (void**)&acc->current_node))
269 {
270 --acc->current_index;
271 return EINA_FALSE;
272 }
273 }
274
275 (*data) = acc->current_node;
276 return EINA_TRUE;
277 }
278 return EINA_FALSE;
279}
280
281static void*
282_efl_ui_tree_view_seg_array_node_accessor_get_container(Efl_Ui_Tree_View_Segarray_Node_Accessor* acc EINA_UNUSED)
283{
284 return NULL;
285}
286
287static void
288_efl_ui_tree_view_seg_array_node_accessor_free(Efl_Ui_Tree_View_Segarray_Node_Accessor* acc EINA_UNUSED)
289{
290 if (acc->pre_iterator)
291 eina_iterator_free(acc->pre_iterator);
292 free(acc);
293}
294
295static Eina_Bool
296_efl_ui_tree_view_seg_array_node_accessor_lock(Efl_Ui_Tree_View_Segarray_Node_Accessor* acc EINA_UNUSED)
297{
298 return EINA_FALSE;
299}
300
301static Eina_Bool
302_efl_ui_tree_view_seg_array_node_accessor_unlock(Efl_Ui_Tree_View_Segarray_Node_Accessor* acc EINA_UNUSED)
303{
304 return EINA_FALSE;
305}
306
307static Eina_Accessor*
308_efl_ui_tree_view_seg_array_node_accessor_clone(Efl_Ui_Tree_View_Segarray_Node_Accessor* acc EINA_UNUSED)
309{
310 return &acc->vtable;
311}
312
313static void
314_efl_ui_tree_view_seg_array_node_accessor_setup(Efl_Ui_Tree_View_Segarray_Node_Accessor* acc, Efl_Ui_Tree_View_Seg_Array* segarray)
315{
316 EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR);
317 acc->vtable.version = EINA_ACCESSOR_VERSION;
318 acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(_efl_ui_tree_view_seg_array_node_accessor_get_at);
319 acc->vtable.get_container = FUNC_ACCESSOR_GET_CONTAINER(_efl_ui_tree_view_seg_array_node_accessor_get_container);
320 acc->vtable.free = FUNC_ACCESSOR_FREE(_efl_ui_tree_view_seg_array_node_accessor_free);
321 acc->vtable.lock = FUNC_ACCESSOR_LOCK(_efl_ui_tree_view_seg_array_node_accessor_lock);
322 acc->vtable.unlock = FUNC_ACCESSOR_LOCK(_efl_ui_tree_view_seg_array_node_accessor_unlock);
323 acc->vtable.clone = FUNC_ACCESSOR_CLONE(_efl_ui_tree_view_seg_array_node_accessor_clone);
324 acc->segarray = segarray;
325 acc->pre_iterator = NULL;
326 acc->current_index = -1;
327 acc->current_node = NULL;
328}
329
330int efl_ui_tree_view_item_index_get(Efl_Ui_Tree_View_Item* item)
331{
332 Efl_Ui_Tree_View_Seg_Array_Node* node = item->tree_node;
333 return item->shallow_offset + node->shallow_first_index;
334}
335
336static void
337_efl_ui_tree_view_seg_array_fix_offset (Efl_Ui_Tree_View_Item* current)
338{
339 Efl_Ui_Tree_View_Seg_Array_Node *node;
340 Efl_Ui_Tree_View_Item* item;
341 Eina_Iterator* iterator;
342 int i;
343 EINA_SAFETY_ON_NULL_RETURN(current);
344
345 // need to fix size
346 current->children_count++;
347 node = current->tree_node;
348
349 EINA_SAFETY_ON_NULL_RETURN(node);
350 EINA_SAFETY_ON_NULL_RETURN(node->seg_array);
351
352 i = current->shallow_offset + 1;
353 while (i < node->length)
354 {
355 item = node->pointers[i];
356 item->linearized_offset++;
357 i++;
358 }
359
360 i = node->linearized_first_index;
361 iterator = eina_rbtree_iterator_infix((void*)node->seg_array->root);
362 while (eina_iterator_next(iterator, (void**)&node))
363 if (node->linearized_first_index > i)
364 node->linearized_first_index++;
365
366 eina_iterator_free(iterator);
367 if (current->parent)
368 _efl_ui_tree_view_seg_array_fix_offset(current->parent);
369}
370
371/* External methods */
372
373Efl_Ui_Tree_View_Seg_Array*
374efl_ui_tree_view_seg_array_setup(int size)
375{
376
377 Efl_Ui_Tree_View_Seg_Array *seg_array = calloc(1, sizeof(Efl_Ui_Tree_View_Seg_Array));
378 seg_array->step_size = size;
379
380 return seg_array;
381}
382
383void
384efl_ui_tree_view_seg_array_free(Efl_Ui_Tree_View_Seg_Array *seg_array)
385{
386 if (seg_array->root)
387 eina_rbtree_delete(EINA_RBTREE_GET(seg_array->root), EINA_RBTREE_FREE_CB(_free_node), NULL);
388
389 free(seg_array);
390}
391
392void
393efl_ui_tree_view_seg_array_flush(Efl_Ui_Tree_View_Seg_Array *seg_array)
394{
395 if (seg_array->root)
396 eina_rbtree_delete(EINA_RBTREE_GET(seg_array->root), EINA_RBTREE_FREE_CB(_free_node), NULL);
397
398 seg_array->root = NULL;
399 seg_array->node_count = 0;
400 seg_array->count = 0;
401}
402
403int
404efl_ui_tree_view_seg_array_count(Efl_Ui_Tree_View_Seg_Array *seg_array)
405{
406 return seg_array->count;
407}
408
409void
410efl_ui_tree_view_seg_array_insert(Efl_Ui_Tree_View_Seg_Array *seg_array, Efl_Ui_Tree_View_Item *parent, int shallow_index, Efl_Model *model)
411{
412 Efl_Ui_Tree_View_Seg_Array_Node *next, *node = NULL;
413 Efl_Ui_Tree_View_Seg_Array* priv = seg_array;
414 Efl_Ui_Tree_View_Item* item;
415 Eina_Iterator* iterator;
416
417 item = _create_item_partial(model, parent);
418
419 if (parent)
420 {
421 if (!parent->segarray)
422 parent->segarray = efl_ui_tree_view_seg_array_setup(seg_array->step_size);
423
424 _efl_ui_tree_view_seg_array_fix_offset (parent);
425 seg_array->count++;
426 priv = parent->segarray;
427 }
428
429 iterator = eina_rbtree_iterator_infix((void*)priv->root);
430 while (eina_iterator_next(iterator, (void**)&next))
431 {
432 if (next->shallow_first_index > shallow_index)
433 break;
434 node = next;
435 }
436 eina_iterator_free(iterator);
437
438 _efl_ui_tree_view_seg_array_insert_at_node(priv, shallow_index, item, node);
439}
440
441/* TODO */
442Efl_Ui_Tree_View_Item*
443efl_ui_tree_view_seg_array_remove(Efl_Ui_Tree_View_Seg_Array *seg_array EINA_UNUSED, int index EINA_UNUSED)
444{
445 return NULL;
446}
447
448Eina_Accessor*
449efl_ui_tree_view_seg_array_shallow_accessor_get(Efl_Ui_Tree_View_Seg_Array *seg_array)
450{
451 Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow* acc = calloc(1, sizeof(Efl_Ui_Tree_View_Segarray_Eina_Accessor_Shallow));
452 _efl_ui_tree_view_seg_array_accessor_shallow_setup(acc, seg_array);
453 return &acc->vtable;
454}
455
456Eina_Accessor*
457efl_ui_tree_view_seg_array_linearized_accessor_get(Efl_Ui_Tree_View_Seg_Array *seg_array)
458{
459 return efl_ui_tree_view_seg_array_shallow_accessor_get(seg_array);
460}
461
462Eina_Accessor*
463efl_ui_tree_view_seg_array_node_accessor_get(Efl_Ui_Tree_View_Seg_Array *seg_array)
464{
465 Efl_Ui_Tree_View_Segarray_Node_Accessor* acc = calloc(1, sizeof(Efl_Ui_Tree_View_Segarray_Node_Accessor));
466 _efl_ui_tree_view_seg_array_node_accessor_setup(acc, seg_array);
467 return &acc->vtable;
468}
469
diff --git a/src/lib/elementary/efl_ui_tree_view_seg_array.h b/src/lib/elementary/efl_ui_tree_view_seg_array.h
new file mode 100644
index 0000000000..a4169c6481
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_seg_array.h
@@ -0,0 +1,50 @@
1#ifndef EFL_UI_TREE_SEG_ARRAY_H
2#define EFL_UI_TREE_SEG_ARRAY_H
3
4#include <Elementary.h>
5
6typedef struct _Efl_Ui_Tree_View_Item Efl_Ui_Tree_View_Item;
7typedef struct _Efl_Ui_Tree_View_Seg_Array_Node Efl_Ui_Tree_View_Seg_Array_Node;
8
9typedef struct _Efl_Ui_Tree_View_Seg_Array
10{
11 Efl_Ui_Tree_View_Seg_Array_Node* root;
12
13 int step_size;
14 int node_count;
15 int count;
16} Efl_Ui_Tree_View_Seg_Array;
17
18struct _Efl_Ui_Tree_View_Seg_Array_Node
19{
20 EINA_RBTREE;
21
22 int length;
23 int max;
24 int linearized_first_index, shallow_first_index;
25
26 void* layout_data;
27 Efl_Ui_Tree_View_Seg_Array* seg_array;
28 Efl_Ui_Tree_View_Item* pointers[0];
29};
30
31
32Efl_Ui_Tree_View_Seg_Array* efl_ui_tree_view_seg_array_setup(int size);
33void efl_ui_tree_view_seg_array_free(Efl_Ui_Tree_View_Seg_Array *seg_array);
34void efl_ui_tree_view_seg_array_flush(Efl_Ui_Tree_View_Seg_Array *seg_array);
35int efl_ui_tree_view_seg_array_count(Efl_Ui_Tree_View_Seg_Array *seg_array);
36
37void efl_ui_tree_view_seg_array_insert(Efl_Ui_Tree_View_Seg_Array *seg_array, Efl_Ui_Tree_View_Item *parent, int shallow_index, Efl_Model *model);
38Efl_Ui_Tree_View_Item* efl_ui_tree_view_seg_array_remove(Efl_Ui_Tree_View_Seg_Array *seg_array, int index);
39
40Eina_Accessor* efl_ui_tree_view_seg_array_shallow_accessor_get(Efl_Ui_Tree_View_Seg_Array *seg_array);
41Eina_Accessor* efl_ui_tree_view_seg_array_linearized_accessor_get(Efl_Ui_Tree_View_Seg_Array *seg_array);
42Eina_Accessor* efl_ui_tree_view_seg_array_node_accessor_get(Efl_Ui_Tree_View_Seg_Array *seg_array);
43
44#define EFL_UI_TREE_VIEW_SEG_ARRAY_POS_GET(_item) \
45 _item->shallow_offset + ((Efl_Ui_Tree_View_Seg_Array_Node*)_item->tree_node)->shallow_first_index
46
47#define EFL_UI_TREE_VIEW_SEG_ARRAY_LINEAR_POS_GET(_item) \
48 _item->linearized_offset + ((Efl_Ui_Tree_View_Seg_Array_Node*)_item->tree_node)->linearized_first_index
49
50#endif
diff --git a/src/lib/elementary/efl_ui_tree_view_seg_array_depth_model.c b/src/lib/elementary/efl_ui_tree_view_seg_array_depth_model.c
new file mode 100644
index 0000000000..4b6caceb1c
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_seg_array_depth_model.c
@@ -0,0 +1,79 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include "Eina.h"
6#include <Efl.h>
7#include <Ecore.h>
8#include "Eo.h"
9#include <assert.h>
10
11#define MY_CLASS EFL_UI_TREE_VIEW_SEG_ARRAY_DEPTH_MODEL_CLASS
12#define MY_CLASS_NAME "Efl.Ui.Tree_View_Seg_Array_Depth_Model"
13
14#include "efl_ui_tree_view_seg_array_depth_model.eo.h"
15#include "efl_model_accessor_view_private.h"
16#include "efl_composite_model_private.h"
17
18typedef struct _Efl_Ui_Tree_View_Seg_Array_Depth_Model_Data
19{
20 unsigned int depth;
21 Eina_Bool readonly;
22
23} Efl_Ui_Tree_View_Seg_Array_Depth_Model_Data;
24
25EOLIAN static Efl_Object *
26_efl_ui_tree_view_seg_array_depth_model_efl_object_constructor(Eo *obj, Efl_Ui_Tree_View_Seg_Array_Depth_Model_Data *pd)
27{
28 obj = efl_constructor(efl_super(obj, MY_CLASS));
29 pd->readonly = EINA_FALSE;
30
31 return obj;
32}
33
34EOLIAN static Efl_Object *
35_efl_ui_tree_view_seg_array_depth_model_efl_object_finalize(Eo *obj, Efl_Ui_Tree_View_Seg_Array_Depth_Model_Data *pd)
36{
37 pd->readonly = EINA_TRUE;
38
39 return obj;
40}
41
42EOLIAN static Eina_Value *
43_efl_ui_tree_view_seg_array_depth_model_efl_model_property_get(const Eo *obj,
44 Efl_Ui_Tree_View_Seg_Array_Depth_Model_Data *pd,
45 const char *property)
46{
47 if (strcmp("depth", property))
48 return efl_model_property_get(efl_super(obj, MY_CLASS), property);
49
50 return eina_value_uint_new(pd->depth);
51}
52
53EOLIAN static Eina_Future *
54_efl_ui_tree_view_seg_array_depth_model_efl_model_property_set(Eo *obj,
55 Efl_Ui_Tree_View_Seg_Array_Depth_Model_Data *pd,
56 const char *property, Eina_Value *value)
57{
58 if (strcmp("depth", property))
59 return efl_model_property_set(efl_super(obj, MY_CLASS), property, value);
60
61 if (pd->readonly)
62 return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_READ_ONLY);
63
64 eina_value_uint_get(value, &pd->depth);
65 return efl_loop_future_resolved(obj, eina_value_uint_init(pd->depth));
66}
67
68static Eina_Iterator *
69_efl_ui_tree_view_seg_array_depth_model_efl_model_properties_get(const Eo *obj,
70 Efl_Ui_Tree_View_Seg_Array_Depth_Model_Data *pd EINA_UNUSED)
71{
72 EFL_COMPOSITE_MODEL_PROPERTIES_SUPER(props,
73 obj, MY_CLASS,
74 NULL,
75 "depth");
76 return props;
77}
78
79#include "efl_ui_tree_view_seg_array_depth_model.eo.c"
diff --git a/src/lib/elementary/efl_ui_tree_view_seg_array_depth_model.eo b/src/lib/elementary/efl_ui_tree_view_seg_array_depth_model.eo
new file mode 100644
index 0000000000..203aec7a95
--- /dev/null
+++ b/src/lib/elementary/efl_ui_tree_view_seg_array_depth_model.eo
@@ -0,0 +1,11 @@
1import efl_ui_tree_view_model;
2
3class Efl.Ui.Tree_View_Seg_Array_Depth_Model extends Efl.Composite_Model
4{
5 implements {
6 Efl.Object.constructor;
7 Efl.Object.finalize;
8 Efl.Model.properties { get; }
9 Efl.Model.property { get; set; }
10 }
11}
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index cb12e6dd95..de36d816db 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -194,6 +194,7 @@ pub_eo_files = [
194 'efl_ui_focus_util.eo', 194 'efl_ui_focus_util.eo',
195 'efl_ui_flip_part.eo', 195 'efl_ui_flip_part.eo',
196 'efl_ui_layout_factory.eo', 196 'efl_ui_layout_factory.eo',
197 'efl_ui_tree_factory.eo',
197 'efl_ui_layout_part.eo', 198 'efl_ui_layout_part.eo',
198 'efl_ui_layout_part_box.eo', 199 'efl_ui_layout_part_box.eo',
199 'efl_ui_layout_part_content.eo', 200 'efl_ui_layout_part_content.eo',
@@ -204,6 +205,9 @@ pub_eo_files = [
204 'efl_ui_list_view.eo', 205 'efl_ui_list_view.eo',
205 'efl_ui_list_view_model.eo', 206 'efl_ui_list_view_model.eo',
206 'efl_ui_list_view_pan.eo', 207 'efl_ui_list_view_pan.eo',
208 'efl_ui_tree_view.eo',
209 'efl_ui_tree_view_model.eo',
210 'efl_ui_tree_view_pan.eo',
207 'efl_ui_item.eo', 211 'efl_ui_item.eo',
208 'efl_ui_list_item.eo', 212 'efl_ui_list_item.eo',
209 'efl_ui_list_default_item_part_icon.eo', 213 'efl_ui_list_default_item_part_icon.eo',
@@ -341,6 +345,9 @@ priv_eo_files = [
341 'efl_ui_homogeneous_model.eo', 345 'efl_ui_homogeneous_model.eo',
342 'efl_ui_exact_model.eo', 346 'efl_ui_exact_model.eo',
343 'efl_ui_average_model.eo', 347 'efl_ui_average_model.eo',
348 'efl_ui_tree_view_seg_array_depth_model.eo',
349 'efl_ui_tree_view_relayout.eo',
350 'efl_ui_tree_view_layouter.eo',
344] 351]
345 352
346priv_eo_file_target = [] 353priv_eo_file_target = []
@@ -456,6 +463,8 @@ elementary_headers_unstable = [
456 'efl_ui_grid_private.h', 463 'efl_ui_grid_private.h',
457 'efl_ui_list_view_private.h', 464 'efl_ui_list_view_private.h',
458 'efl_ui_list_view_seg_array.h', 465 'efl_ui_list_view_seg_array.h',
466 'efl_ui_tree_view_private.h',
467 'efl_ui_tree_view_seg_array.h',
459 'elm_widget_web.h', 468 'elm_widget_web.h',
460 'efl_ui_clock.h', 469 'efl_ui_clock.h',
461 'elm_code.h', 470 'elm_code.h',
@@ -887,6 +896,11 @@ elementary_src = [
887 'efl_ui_list_view_precise_layouter.c', 896 'efl_ui_list_view_precise_layouter.c',
888 'efl_ui_list_view_seg_array.c', 897 'efl_ui_list_view_seg_array.c',
889 'efl_ui_layout_factory.c', 898 'efl_ui_layout_factory.c',
899 'efl_ui_tree_view.c',
900 'efl_ui_tree_view_layouter.c',
901 'efl_ui_tree_view_seg_array.c',
902 'efl_ui_tree_view_seg_array_depth_model.c',
903 'efl_ui_tree_factory.c',
890 'efl_ui_scroller.c', 904 'efl_ui_scroller.c',
891 'efl_ui_scroll_manager.c', 905 'efl_ui_scroll_manager.c',
892 'efl_ui_pan.c', 906 'efl_ui_pan.c',