summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2019-01-18 18:01:23 -0800
committerCedric BAIL <cedric.bail@free.fr>2019-01-30 11:29:31 -0800
commitc910679917bbd27e0cfd07bbd3c58fe89f9b77c2 (patch)
treeb02a3b288f610b77716f3cce92f10ee3f7b65b0a
parentaa0e89a5901b473502d23f6cff5e497c12308bbc (diff)
elementary: update Efl.Ui.Caching_Factory to rely on Efl.Ui.Widget_Factory for Efl.Ui.Widget.
I am not sure we really need Efl.Ui.Caching_Factory after this, but in case we want a Caching_Factory for non Efl.Ui.Widget, this is supported by this patch (And is the reason why most of the complexity). The benefit from inheriting from Efl.Ui.Widget_Factory allow to get the style of an Efl.Ui.Widget defined by an Efl.Model properly done at creation time. Reviewed-by: SangHyeon Jade Lee <sh10233.lee@samsung.com> Reviewed-by: Larry Lira <larry@expertisesolutions.com.br> Differential Revision: https://phab.enlightenment.org/D7705
-rw-r--r--src/lib/elementary/efl_ui_caching_factory.c182
-rw-r--r--src/lib/elementary/efl_ui_caching_factory.eo18
-rw-r--r--src/lib/elementary/efl_ui_image_factory.c2
-rw-r--r--src/lib/elementary/efl_ui_layout_factory.c2
4 files changed, 159 insertions, 45 deletions
diff --git a/src/lib/elementary/efl_ui_caching_factory.c b/src/lib/elementary/efl_ui_caching_factory.c
index b25d6ba..49a316e 100644
--- a/src/lib/elementary/efl_ui_caching_factory.c
+++ b/src/lib/elementary/efl_ui_caching_factory.c
@@ -6,18 +6,33 @@
6#include "elm_priv.h" 6#include "elm_priv.h"
7 7
8typedef struct _Efl_Ui_Caching_Factory_Data Efl_Ui_Caching_Factory_Data; 8typedef struct _Efl_Ui_Caching_Factory_Data Efl_Ui_Caching_Factory_Data;
9typedef struct _Efl_Ui_Caching_Factory_Request Efl_Ui_Caching_Factory_Request;
10
9struct _Efl_Ui_Caching_Factory_Data 11struct _Efl_Ui_Caching_Factory_Data
10{ 12{
11 const Efl_Class *klass; 13 const Efl_Class *klass;
12 14
15 Eina_Stringshare *style;
16
13 // Simple list of ready-to-use objects. They are all equal so it does not matter from which 17 // Simple list of ready-to-use objects. They are all equal so it does not matter from which
14 // end of the list objects are added and removed. 18 // end of the list objects are added and removed.
15 Eina_List *cache; 19 Eina_List *cache;
20 Eina_Hash *lookup;
16 21
17 struct { 22 struct {
18 unsigned int memory; 23 unsigned int memory;
19 unsigned int items; 24 unsigned int items;
20 } limit, current; 25 } limit, current;
26
27 Eina_Bool invalidated : 1;
28};
29
30struct _Efl_Ui_Caching_Factory_Request
31{
32 Efl_Ui_Caching_Factory_Data *pd;
33
34 Eo *parent;
35 Efl_Model *model;
21}; 36};
22 37
23// Clear the cache until it meet the constraint 38// Clear the cache until it meet the constraint
@@ -33,7 +48,15 @@ _efl_ui_caching_factory_remove(Efl_Ui_Caching_Factory_Data *pd, Eina_List *l, Ef
33} 48}
34 49
35static void 50static void
36_efl_ui_caching_factory_flush(Efl_Ui_Caching_Factory_Data *pd) 51_efl_ui_caching_factory_item_del(Eo *obj, Efl_Ui_Caching_Factory_Data *pd,
52 Efl_Gfx_Entity *entity)
53{
54 if (pd->klass) efl_del(entity);
55 else efl_ui_factory_release(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), entity);
56}
57
58static void
59_efl_ui_caching_factory_flush(Eo *obj, Efl_Ui_Caching_Factory_Data *pd)
37{ 60{
38 while (pd->limit.items != 0 && 61 while (pd->limit.items != 0 &&
39 pd->current.items > pd->limit.items) 62 pd->current.items > pd->limit.items)
@@ -43,8 +66,8 @@ _efl_ui_caching_factory_flush(Efl_Ui_Caching_Factory_Data *pd)
43 entity = eina_list_data_get(eina_list_last(pd->cache)); 66 entity = eina_list_data_get(eina_list_last(pd->cache));
44 67
45 _efl_ui_caching_factory_remove(pd, eina_list_last(pd->cache), entity); 68 _efl_ui_caching_factory_remove(pd, eina_list_last(pd->cache), entity);
46 69 if (pd->lookup) eina_hash_del(pd->lookup, efl_ui_widget_style_get(entity), entity);
47 efl_del(entity); 70 _efl_ui_caching_factory_item_del(obj, pd, entity);
48 } 71 }
49 72
50 while (pd->limit.memory != 0 && 73 while (pd->limit.memory != 0 &&
@@ -55,9 +78,49 @@ _efl_ui_caching_factory_flush(Efl_Ui_Caching_Factory_Data *pd)
55 entity = eina_list_data_get(eina_list_last(pd->cache)); 78 entity = eina_list_data_get(eina_list_last(pd->cache));
56 79
57 _efl_ui_caching_factory_remove(pd, eina_list_last(pd->cache), entity); 80 _efl_ui_caching_factory_remove(pd, eina_list_last(pd->cache), entity);
81 if (pd->lookup) eina_hash_del(pd->lookup, efl_ui_widget_style_get(entity), entity);
82 _efl_ui_caching_factory_item_del(obj, pd, entity);
83 }
84}
85
86static Eina_Value
87_efl_ui_caching_factory_create_then(Eo *obj EINA_UNUSED, void *data, const Eina_Value v)
88{
89 Efl_Ui_Caching_Factory_Request *r = data;
90 Efl_Ui_Widget *w;
91 const char *string = NULL;
58 92
59 efl_del(entity); 93 if (!eina_value_string_get(&v, &string))
94 return eina_value_error_init(EFL_MODEL_ERROR_NOT_SUPPORTED);
95
96 w = eina_hash_find(r->pd->lookup, string);
97 if (!w)
98 {
99 Eina_Future *f;
100
101 // No object of that style in the cache, need to create a new one
102 f = efl_ui_factory_create(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS),
103 r->model, r->parent);
104 return eina_future_as_value(f);
60 } 105 }
106
107 eina_hash_del(r->pd->lookup, string, w);
108 _efl_ui_caching_factory_remove(r->pd, r->pd->cache, w);
109
110 efl_parent_set(w, r->parent);
111 efl_ui_view_model_set(w, r->model);
112
113 return eina_value_object_init(w);
114}
115
116static void
117_efl_ui_caching_factory_create_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
118{
119 Efl_Ui_Caching_Factory_Request *r = data;
120
121 efl_unref(r->model);
122 efl_unref(r->parent);
123 free(r);
61} 124}
62 125
63static Eina_Future * 126static Eina_Future *
@@ -65,59 +128,88 @@ _efl_ui_caching_factory_efl_ui_factory_create(Eo *obj,
65 Efl_Ui_Caching_Factory_Data *pd, 128 Efl_Ui_Caching_Factory_Data *pd,
66 Efl_Model *model, Efl_Gfx_Entity *parent) 129 Efl_Model *model, Efl_Gfx_Entity *parent)
67{ 130{
68 Efl_Gfx_Entity *r; 131 Efl_Gfx_Entity *w = NULL;
69 132
70 if (pd->cache) 133 if (pd->cache)
71 { 134 {
72 r = eina_list_data_get(pd->cache); 135 if (pd->style && !pd->klass)
136 {
137 Efl_Ui_Caching_Factory_Request *r;
73 138
74 _efl_ui_caching_factory_remove(pd, pd->cache, r); 139 r = calloc(1, sizeof (Efl_Ui_Caching_Factory_Request));
140 if (!r) return efl_loop_future_rejected(obj, ENOMEM);
75 141
76 efl_parent_set(r, parent); 142 r->pd = pd;
143 r->parent = efl_ref(parent);
144 r->model = efl_ref(model);
145
146 return efl_future_then(obj, efl_model_property_ready_get(obj, pd->style),
147 .success = _efl_ui_caching_factory_create_then,
148 .data = r,
149 .free = _efl_ui_caching_factory_create_cleanup);
150 }
151
152 w = eina_list_data_get(pd->cache);
153
154 _efl_ui_caching_factory_remove(pd, pd->cache, w);
155
156 efl_parent_set(w, parent);
77 } 157 }
78 else 158
159 if (!w)
79 { 160 {
80 r = efl_add(pd->klass, parent); 161 if (pd->klass) w = efl_add(pd->klass, parent);
162 else return efl_ui_factory_create(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS),
163 model, parent);
81 } 164 }
82 165
83 efl_ui_view_model_set(r, model); 166 efl_ui_view_model_set(w, model);
84 167
85 return efl_loop_future_resolved(obj, eina_value_object_init(r)); 168 return efl_loop_future_resolved(obj, eina_value_object_init(w));
86} 169}
87 170
88static void 171static void
89_efl_ui_caching_factory_item_class_set(Eo *obj, 172_efl_ui_caching_factory_efl_ui_widget_factory_item_class_set(Eo *obj,
90 Efl_Ui_Caching_Factory_Data *pd, 173 Efl_Ui_Caching_Factory_Data *pd,
91 const Efl_Object *klass) 174 const Efl_Object *klass)
92{ 175{
93 if (!efl_isa(klass, EFL_GFX_ENTITY_INTERFACE) || 176 if (efl_isa(klass, EFL_UI_VIEW_INTERFACE) &&
94 !efl_isa(klass, EFL_UI_VIEW_INTERFACE)) 177 !efl_isa(klass, EFL_UI_WIDGET_CLASS))
95 { 178 {
96 ERR("Provided class '%s' for factory '%s' doesn't implement '%s' and '%s' interfaces.", 179 if (!efl_isa(klass, EFL_GFX_ENTITY_INTERFACE) ||
97 efl_class_name_get(klass), 180 !efl_isa(klass, EFL_UI_VIEW_INTERFACE))
98 efl_class_name_get(obj), 181 {
99 efl_class_name_get(EFL_GFX_ENTITY_INTERFACE), 182 ERR("Provided class '%s' for factory '%s' doesn't implement '%s' and '%s' interfaces nor '%s' and '%s' interfaces.",
100 efl_class_name_get(EFL_UI_VIEW_INTERFACE)); 183 efl_class_name_get(klass),
101 return ; 184 efl_class_name_get(obj),
185 efl_class_name_get(EFL_GFX_ENTITY_INTERFACE),
186 efl_class_name_get(EFL_UI_VIEW_INTERFACE),
187 efl_class_name_get(EFL_UI_WIDGET_CLASS),
188 efl_class_name_get(EFL_UI_VIEW_INTERFACE));
189 return ;
190 }
191 pd->klass = klass;
192 return;
102 } 193 }
103 pd->klass = klass; 194 efl_ui_widget_factory_item_class_set(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), klass);
104} 195}
105 196
106static const Efl_Object * 197static const Efl_Object *
107_efl_ui_caching_factory_item_class_get(const Eo *obj EINA_UNUSED, 198_efl_ui_caching_factory_efl_ui_widget_factory_item_class_get(const Eo *obj,
108 Efl_Ui_Caching_Factory_Data *pd) 199 Efl_Ui_Caching_Factory_Data *pd)
109{ 200{
110 return pd->klass; 201 if (pd->klass) return pd->klass;
202 return efl_ui_widget_factory_item_class_get(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS));
111} 203}
112 204
113static void 205static void
114_efl_ui_caching_factory_memory_limit_set(Eo *obj EINA_UNUSED, 206_efl_ui_caching_factory_memory_limit_set(Eo *obj,
115 Efl_Ui_Caching_Factory_Data *pd, 207 Efl_Ui_Caching_Factory_Data *pd,
116 unsigned int limit) 208 unsigned int limit)
117{ 209{
118 pd->limit.memory = limit; 210 pd->limit.memory = limit;
119 211
120 _efl_ui_caching_factory_flush(pd); 212 _efl_ui_caching_factory_flush(obj, pd);
121} 213}
122 214
123static unsigned int 215static unsigned int
@@ -128,13 +220,13 @@ _efl_ui_caching_factory_memory_limit_get(const Eo *obj EINA_UNUSED,
128} 220}
129 221
130static void 222static void
131_efl_ui_caching_factory_items_limit_set(Eo *obj EINA_UNUSED, 223_efl_ui_caching_factory_items_limit_set(Eo *obj,
132 Efl_Ui_Caching_Factory_Data *pd, 224 Efl_Ui_Caching_Factory_Data *pd,
133 unsigned int limit) 225 unsigned int limit)
134{ 226{
135 pd->limit.items = limit; 227 pd->limit.items = limit;
136 228
137 _efl_ui_caching_factory_flush(pd); 229 _efl_ui_caching_factory_flush(obj, pd);
138} 230}
139 231
140static unsigned int 232static unsigned int
@@ -149,6 +241,13 @@ _efl_ui_caching_factory_efl_ui_factory_release(Eo *obj,
149 Efl_Ui_Caching_Factory_Data *pd, 241 Efl_Ui_Caching_Factory_Data *pd,
150 Efl_Gfx_Entity *ui_view) 242 Efl_Gfx_Entity *ui_view)
151{ 243{
244 // Are we invalidated ?
245 if (pd->invalidated)
246 {
247 _efl_ui_caching_factory_item_del(obj, pd, ui_view);
248 return;
249 }
250
152 // Change parent, disconnect the object and make it invisible 251 // Change parent, disconnect the object and make it invisible
153 efl_parent_set(ui_view, obj); 252 efl_parent_set(ui_view, obj);
154 efl_gfx_entity_visible_set(ui_view, EINA_FALSE); 253 efl_gfx_entity_visible_set(ui_view, EINA_FALSE);
@@ -161,8 +260,15 @@ _efl_ui_caching_factory_efl_ui_factory_release(Eo *obj,
161 if (efl_isa(ui_view, EFL_CACHED_ITEM_INTERFACE)) 260 if (efl_isa(ui_view, EFL_CACHED_ITEM_INTERFACE))
162 pd->current.memory += efl_cached_item_memory_size_get(ui_view); 261 pd->current.memory += efl_cached_item_memory_size_get(ui_view);
163 262
263 // Fill lookup
264 if (!pd->klass && efl_ui_widget_style_get(ui_view))
265 {
266 if (!pd->lookup) pd->lookup = eina_hash_string_djb2_new(NULL);
267 eina_hash_direct_add(pd->lookup, efl_ui_widget_style_get(ui_view), ui_view);
268 }
269
164 // And check if the cache need some triming 270 // And check if the cache need some triming
165 _efl_ui_caching_factory_flush(pd); 271 _efl_ui_caching_factory_flush(obj, pd);
166} 272}
167 273
168static void 274static void
@@ -171,6 +277,9 @@ _efl_ui_caching_factory_efl_object_invalidate(Eo *obj EINA_UNUSED,
171{ 277{
172 // As all the objects in the cache have the factory as parent, there's no need to unparent them 278 // As all the objects in the cache have the factory as parent, there's no need to unparent them
173 pd->cache = eina_list_free(pd->cache); 279 pd->cache = eina_list_free(pd->cache);
280 eina_hash_free(pd->lookup);
281 pd->lookup = NULL;
282 pd->invalidated = EINA_TRUE;
174} 283}
175 284
176static Efl_App * 285static Efl_App *
@@ -215,4 +324,13 @@ _efl_ui_caching_factory_efl_object_parent_set(Eo *obj, Efl_Ui_Caching_Factory_Da
215 if (a) efl_event_callback_add(a, EFL_APP_EVENT_PAUSE, _efl_ui_caching_factory_pause, pd); 324 if (a) efl_event_callback_add(a, EFL_APP_EVENT_PAUSE, _efl_ui_caching_factory_pause, pd);
216} 325}
217 326
327static void
328_efl_ui_caching_factory_efl_ui_model_connect_connect(Eo *obj, Efl_Ui_Caching_Factory_Data *pd,
329 const char *name, const char *property)
330{
331 if (!strcmp(name, "style"))
332 eina_stringshare_replace(&pd->style, property);
333 efl_ui_model_connect(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), name, property);
334}
335
218#include "efl_ui_caching_factory.eo.c" 336#include "efl_ui_caching_factory.eo.c"
diff --git a/src/lib/elementary/efl_ui_caching_factory.eo b/src/lib/elementary/efl_ui_caching_factory.eo
index c7e2f2b..ad97a12 100644
--- a/src/lib/elementary/efl_ui_caching_factory.eo
+++ b/src/lib/elementary/efl_ui_caching_factory.eo
@@ -1,9 +1,11 @@
1class Efl.Ui.Caching_Factory extends Efl.Loop_Consumer implements Efl.Ui.Factory 1class Efl.Ui.Caching_Factory extends Efl.Ui.Widget_Factory
2{ 2{
3 [[Efl Ui Factory that provides object caching. 3 [[Efl Ui Factory that provides object caching.
4 4
5 This factory handles caching of one type of object and automatically empties the cache 5 This factory handles caching of one type of object that must be an @Efl.Gfx.Entity with an @Efl.Ui.View interface defined.
6 when the application goes into pause. 6 This factory will rely on its parent class @Efl.Ui.Widget_Factory for creating the subset of class that match @Efl.Ui.Widget
7 interface.
8 The factory will automatically empties the cache when the application goes into pause.
7 9
8 Creating objects is costly and time consuming, keeping a few on hand for when you next will need them helps a lot. 10 Creating objects is costly and time consuming, keeping a few on hand for when you next will need them helps a lot.
9 This is what this factory caching infrastructure provides. It will create the object from the class defined on it and 11 This is what this factory caching infrastructure provides. It will create the object from the class defined on it and
@@ -13,14 +15,6 @@ class Efl.Ui.Caching_Factory extends Efl.Loop_Consumer implements Efl.Ui.Factory
13 The cache might decide to flush itself when the application event pause is triggered. 15 The cache might decide to flush itself when the application event pause is triggered.
14 ]] 16 ]]
15 methods { 17 methods {
16 @property item_class {
17 [[Define the class of the item returned by this factory.]]
18 get {}
19 set {}
20 values {
21 klass: const(Efl.Class); [[The class identifier to create item from.]]
22 }
23 }
24 @property memory_limit { 18 @property memory_limit {
25 [[Define the maxium size in Bytes that all the object waiting on standby in the cache take. They must provide the @Efl.Cached.Item interface for an accurate accounting.]] 19 [[Define the maxium size in Bytes that all the object waiting on standby in the cache take. They must provide the @Efl.Cached.Item interface for an accurate accounting.]]
26 get {} 20 get {}
@@ -42,6 +36,8 @@ class Efl.Ui.Caching_Factory extends Efl.Loop_Consumer implements Efl.Ui.Factory
42 implements { 36 implements {
43 Efl.Ui.Factory.create; 37 Efl.Ui.Factory.create;
44 Efl.Ui.Factory.release; 38 Efl.Ui.Factory.release;
39 Efl.Ui.Model.Connect.connect;
40 Efl.Ui.Widget_Factory.item_class { get; set; }
45 Efl.Object.invalidate; 41 Efl.Object.invalidate;
46 Efl.Object.parent { set; } 42 Efl.Object.parent { set; }
47 } 43 }
diff --git a/src/lib/elementary/efl_ui_image_factory.c b/src/lib/elementary/efl_ui_image_factory.c
index ce4d892..4cd08cd 100644
--- a/src/lib/elementary/efl_ui_image_factory.c
+++ b/src/lib/elementary/efl_ui_image_factory.c
@@ -17,7 +17,7 @@ EOLIAN static Eo *
17_efl_ui_image_factory_efl_object_constructor(Eo *obj, Efl_Ui_Image_Factory_Data *pd) 17_efl_ui_image_factory_efl_object_constructor(Eo *obj, Efl_Ui_Image_Factory_Data *pd)
18{ 18{
19 obj = efl_constructor(efl_super(obj, MY_CLASS)); 19 obj = efl_constructor(efl_super(obj, MY_CLASS));
20 efl_ui_caching_factory_item_class_set(obj, EFL_UI_IMAGE_CLASS); 20 efl_ui_widget_factory_item_class_set(obj, EFL_UI_IMAGE_CLASS);
21 21
22 pd->property = NULL; 22 pd->property = NULL;
23 23
diff --git a/src/lib/elementary/efl_ui_layout_factory.c b/src/lib/elementary/efl_ui_layout_factory.c
index 150fd67..0d81136 100644
--- a/src/lib/elementary/efl_ui_layout_factory.c
+++ b/src/lib/elementary/efl_ui_layout_factory.c
@@ -45,7 +45,7 @@ _efl_ui_layout_factory_efl_object_constructor(Eo *obj, Efl_Ui_Layout_Factory_Dat
45{ 45{
46 obj = efl_constructor(efl_super(obj, MY_CLASS)); 46 obj = efl_constructor(efl_super(obj, MY_CLASS));
47 47
48 efl_ui_caching_factory_item_class_set(obj, EFL_UI_LAYOUT_CLASS); 48 efl_ui_widget_factory_item_class_set(obj, EFL_UI_LAYOUT_CLASS);
49 49
50 pd->connects = eina_hash_stringshared_new(EINA_FREE_CB(eina_stringshare_del)); 50 pd->connects = eina_hash_stringshared_new(EINA_FREE_CB(eina_stringshare_del));
51 pd->factory_connects = eina_hash_stringshared_new(EINA_FREE_CB(efl_unref)); 51 pd->factory_connects = eina_hash_stringshared_new(EINA_FREE_CB(efl_unref));