cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=c910679917bbd27e0cfd07bbd3c58fe89f9b77c2

commit c910679917bbd27e0cfd07bbd3c58fe89f9b77c2
Author: Cedric BAIL <[email protected]>
Date:   Fri Jan 18 18:01:23 2019 -0800

    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 <[email protected]>
    Reviewed-by: Larry Lira <[email protected]>
    Differential Revision: https://phab.enlightenment.org/D7705
---
 src/lib/elementary/efl_ui_caching_factory.c  | 182 ++++++++++++++++++++++-----
 src/lib/elementary/efl_ui_caching_factory.eo |  18 ++-
 src/lib/elementary/efl_ui_image_factory.c    |   2 +-
 src/lib/elementary/efl_ui_layout_factory.c   |   2 +-
 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 b25d6ba829..49a316e01e 100644
--- a/src/lib/elementary/efl_ui_caching_factory.c
+++ b/src/lib/elementary/efl_ui_caching_factory.c
@@ -6,18 +6,33 @@
 #include "elm_priv.h"
 
 typedef struct _Efl_Ui_Caching_Factory_Data Efl_Ui_Caching_Factory_Data;
+typedef struct _Efl_Ui_Caching_Factory_Request Efl_Ui_Caching_Factory_Request;
+
 struct _Efl_Ui_Caching_Factory_Data
 {
    const Efl_Class *klass;
 
+   Eina_Stringshare *style;
+
    // Simple list of ready-to-use objects. They are all equal so it does not 
matter from which
    // end of the list objects are added and removed.
    Eina_List *cache;
+   Eina_Hash *lookup;
 
    struct {
       unsigned int memory;
       unsigned int items;
    } limit, current;
+
+   Eina_Bool invalidated : 1;
+};
+
+struct _Efl_Ui_Caching_Factory_Request
+{
+   Efl_Ui_Caching_Factory_Data *pd;
+
+   Eo *parent;
+   Efl_Model *model;
 };
 
 // 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
 }
 
 static void
-_efl_ui_caching_factory_flush(Efl_Ui_Caching_Factory_Data *pd)
+_efl_ui_caching_factory_item_del(Eo *obj, Efl_Ui_Caching_Factory_Data *pd,
+                                 Efl_Gfx_Entity *entity)
+{
+   if (pd->klass) efl_del(entity);
+   else efl_ui_factory_release(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), 
entity);
+}
+
+static void
+_efl_ui_caching_factory_flush(Eo *obj, Efl_Ui_Caching_Factory_Data *pd)
 {
    while (pd->limit.items != 0 &&
           pd->current.items > pd->limit.items)
@@ -43,8 +66,8 @@ _efl_ui_caching_factory_flush(Efl_Ui_Caching_Factory_Data *pd)
         entity = eina_list_data_get(eina_list_last(pd->cache));
 
         _efl_ui_caching_factory_remove(pd, eina_list_last(pd->cache), entity);
-
-        efl_del(entity);
+        if (pd->lookup) eina_hash_del(pd->lookup, 
efl_ui_widget_style_get(entity), entity);
+        _efl_ui_caching_factory_item_del(obj, pd, entity);
      }
 
    while (pd->limit.memory != 0 &&
@@ -55,9 +78,49 @@ _efl_ui_caching_factory_flush(Efl_Ui_Caching_Factory_Data 
*pd)
         entity = eina_list_data_get(eina_list_last(pd->cache));
 
         _efl_ui_caching_factory_remove(pd, eina_list_last(pd->cache), entity);
+        if (pd->lookup) eina_hash_del(pd->lookup, 
efl_ui_widget_style_get(entity), entity);
+        _efl_ui_caching_factory_item_del(obj, pd, entity);
+     }
+}
+
+static Eina_Value
+_efl_ui_caching_factory_create_then(Eo *obj EINA_UNUSED, void *data, const 
Eina_Value v)
+{
+   Efl_Ui_Caching_Factory_Request *r = data;
+   Efl_Ui_Widget *w;
+   const char *string = NULL;
 
-        efl_del(entity);
+   if (!eina_value_string_get(&v, &string))
+     return eina_value_error_init(EFL_MODEL_ERROR_NOT_SUPPORTED);
+
+   w = eina_hash_find(r->pd->lookup, string);
+   if (!w)
+     {
+        Eina_Future *f;
+
+        // No object of that style in the cache, need to create a new one
+        f = efl_ui_factory_create(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS),
+                                  r->model, r->parent);
+        return eina_future_as_value(f);
      }
+
+   eina_hash_del(r->pd->lookup, string, w);
+   _efl_ui_caching_factory_remove(r->pd, r->pd->cache, w);
+
+   efl_parent_set(w, r->parent);
+   efl_ui_view_model_set(w, r->model);
+
+   return eina_value_object_init(w);
+}
+
+static void
+_efl_ui_caching_factory_create_cleanup(Eo *o EINA_UNUSED, void *data, const 
Eina_Future *dead_future EINA_UNUSED)
+{
+   Efl_Ui_Caching_Factory_Request *r = data;
+
+   efl_unref(r->model);
+   efl_unref(r->parent);
+   free(r);
 }
 
 static Eina_Future *
@@ -65,59 +128,88 @@ _efl_ui_caching_factory_efl_ui_factory_create(Eo *obj,
                                               Efl_Ui_Caching_Factory_Data *pd,
                                               Efl_Model *model, Efl_Gfx_Entity 
*parent)
 {
-   Efl_Gfx_Entity *r;
+   Efl_Gfx_Entity *w = NULL;
 
    if (pd->cache)
      {
-        r = eina_list_data_get(pd->cache);
+        if (pd->style && !pd->klass)
+          {
+             Efl_Ui_Caching_Factory_Request *r;
 
-        _efl_ui_caching_factory_remove(pd, pd->cache, r);
+             r = calloc(1, sizeof (Efl_Ui_Caching_Factory_Request));
+             if (!r) return efl_loop_future_rejected(obj, ENOMEM);
 
-        efl_parent_set(r, parent);
+             r->pd = pd;
+             r->parent = efl_ref(parent);
+             r->model = efl_ref(model);
+
+             return efl_future_then(obj, efl_model_property_ready_get(obj, 
pd->style),
+                                    .success = 
_efl_ui_caching_factory_create_then,
+                                    .data = r,
+                                    .free = 
_efl_ui_caching_factory_create_cleanup);
+          }
+
+        w = eina_list_data_get(pd->cache);
+
+        _efl_ui_caching_factory_remove(pd, pd->cache, w);
+
+        efl_parent_set(w, parent);
      }
-   else
+
+   if (!w)
      {
-        r = efl_add(pd->klass, parent);
+        if (pd->klass) w = efl_add(pd->klass, parent);
+        else return efl_ui_factory_create(efl_super(obj, 
EFL_UI_CACHING_FACTORY_CLASS),
+                                          model, parent);
      }
 
-   efl_ui_view_model_set(r, model);
+   efl_ui_view_model_set(w, model);
 
-   return efl_loop_future_resolved(obj, eina_value_object_init(r));
+   return efl_loop_future_resolved(obj, eina_value_object_init(w));
 }
 
 static void
-_efl_ui_caching_factory_item_class_set(Eo *obj,
-                                       Efl_Ui_Caching_Factory_Data *pd,
-                                       const Efl_Object *klass)
+_efl_ui_caching_factory_efl_ui_widget_factory_item_class_set(Eo *obj,
+                                                             
Efl_Ui_Caching_Factory_Data *pd,
+                                                             const Efl_Object 
*klass)
 {
-   if (!efl_isa(klass, EFL_GFX_ENTITY_INTERFACE) ||
-       !efl_isa(klass, EFL_UI_VIEW_INTERFACE))
+   if (efl_isa(klass, EFL_UI_VIEW_INTERFACE) &&
+       !efl_isa(klass, EFL_UI_WIDGET_CLASS))
      {
-        ERR("Provided class '%s' for factory '%s' doesn't implement '%s' and 
'%s' interfaces.",
-            efl_class_name_get(klass),
-            efl_class_name_get(obj),
-            efl_class_name_get(EFL_GFX_ENTITY_INTERFACE),
-            efl_class_name_get(EFL_UI_VIEW_INTERFACE));
-        return ;
+        if (!efl_isa(klass, EFL_GFX_ENTITY_INTERFACE) ||
+            !efl_isa(klass, EFL_UI_VIEW_INTERFACE))
+          {
+             ERR("Provided class '%s' for factory '%s' doesn't implement '%s' 
and '%s' interfaces nor '%s' and '%s' interfaces.",
+                 efl_class_name_get(klass),
+                 efl_class_name_get(obj),
+                 efl_class_name_get(EFL_GFX_ENTITY_INTERFACE),
+                 efl_class_name_get(EFL_UI_VIEW_INTERFACE),
+                 efl_class_name_get(EFL_UI_WIDGET_CLASS),
+                 efl_class_name_get(EFL_UI_VIEW_INTERFACE));
+             return ;
+          }
+        pd->klass = klass;
+        return;
      }
-   pd->klass = klass;
+   efl_ui_widget_factory_item_class_set(efl_super(obj, 
EFL_UI_CACHING_FACTORY_CLASS), klass);
 }
 
 static const Efl_Object *
-_efl_ui_caching_factory_item_class_get(const Eo *obj EINA_UNUSED,
-                                       Efl_Ui_Caching_Factory_Data *pd)
+_efl_ui_caching_factory_efl_ui_widget_factory_item_class_get(const Eo *obj,
+                                                             
Efl_Ui_Caching_Factory_Data *pd)
 {
-   return pd->klass;
+   if (pd->klass) return pd->klass;
+   return efl_ui_widget_factory_item_class_get(efl_super(obj, 
EFL_UI_CACHING_FACTORY_CLASS));
 }
 
 static void
-_efl_ui_caching_factory_memory_limit_set(Eo *obj EINA_UNUSED,
+_efl_ui_caching_factory_memory_limit_set(Eo *obj,
                                          Efl_Ui_Caching_Factory_Data *pd,
                                          unsigned int limit)
 {
    pd->limit.memory = limit;
 
-   _efl_ui_caching_factory_flush(pd);
+   _efl_ui_caching_factory_flush(obj, pd);
 }
 
 static unsigned int
@@ -128,13 +220,13 @@ _efl_ui_caching_factory_memory_limit_get(const Eo *obj 
EINA_UNUSED,
 }
 
 static void
-_efl_ui_caching_factory_items_limit_set(Eo *obj EINA_UNUSED,
+_efl_ui_caching_factory_items_limit_set(Eo *obj,
                                         Efl_Ui_Caching_Factory_Data *pd,
                                         unsigned int limit)
 {
    pd->limit.items = limit;
 
-   _efl_ui_caching_factory_flush(pd);
+   _efl_ui_caching_factory_flush(obj, pd);
 }
 
 static unsigned int
@@ -149,6 +241,13 @@ _efl_ui_caching_factory_efl_ui_factory_release(Eo *obj,
                                                Efl_Ui_Caching_Factory_Data *pd,
                                                Efl_Gfx_Entity *ui_view)
 {
+   // Are we invalidated ?
+   if (pd->invalidated)
+     {
+        _efl_ui_caching_factory_item_del(obj, pd, ui_view);
+        return;
+     }
+
    // Change parent, disconnect the object and make it invisible
    efl_parent_set(ui_view, obj);
    efl_gfx_entity_visible_set(ui_view, EINA_FALSE);
@@ -161,8 +260,15 @@ _efl_ui_caching_factory_efl_ui_factory_release(Eo *obj,
    if (efl_isa(ui_view, EFL_CACHED_ITEM_INTERFACE))
      pd->current.memory += efl_cached_item_memory_size_get(ui_view);
 
+   // Fill lookup
+   if (!pd->klass && efl_ui_widget_style_get(ui_view))
+     {
+        if (!pd->lookup) pd->lookup = eina_hash_string_djb2_new(NULL);
+        eina_hash_direct_add(pd->lookup, efl_ui_widget_style_get(ui_view), 
ui_view);
+     }
+
    // And check if the cache need some triming
-   _efl_ui_caching_factory_flush(pd);
+   _efl_ui_caching_factory_flush(obj, pd);
 }
 
 static void
@@ -171,6 +277,9 @@ _efl_ui_caching_factory_efl_object_invalidate(Eo *obj 
EINA_UNUSED,
 {
    // As all the objects in the cache have the factory as parent, there's no 
need to unparent them
    pd->cache = eina_list_free(pd->cache);
+   eina_hash_free(pd->lookup);
+   pd->lookup = NULL;
+   pd->invalidated = EINA_TRUE;
 }
 
 static Efl_App *
@@ -215,4 +324,13 @@ _efl_ui_caching_factory_efl_object_parent_set(Eo *obj, 
Efl_Ui_Caching_Factory_Da
    if (a) efl_event_callback_add(a, EFL_APP_EVENT_PAUSE, 
_efl_ui_caching_factory_pause, pd);
 }
 
+static void
+_efl_ui_caching_factory_efl_ui_model_connect_connect(Eo *obj, 
Efl_Ui_Caching_Factory_Data *pd,
+                                                     const char *name, const 
char *property)
+{
+   if (!strcmp(name, "style"))
+     eina_stringshare_replace(&pd->style, property);
+   efl_ui_model_connect(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), name, 
property);
+}
+
 #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 c7e2f2b743..ad97a12c88 100644
--- a/src/lib/elementary/efl_ui_caching_factory.eo
+++ b/src/lib/elementary/efl_ui_caching_factory.eo
@@ -1,9 +1,11 @@
-class Efl.Ui.Caching_Factory extends Efl.Loop_Consumer implements 
Efl.Ui.Factory
+class Efl.Ui.Caching_Factory extends Efl.Ui.Widget_Factory
 {
    [[Efl Ui Factory that provides object caching.
 
-     This factory handles caching of one type of object and automatically 
empties the cache
-     when the application goes into pause.
+     This factory handles caching of one type of object that must be an 
@Efl.Gfx.Entity with an @Efl.Ui.View interface defined.
+     This factory will rely on its parent class @Efl.Ui.Widget_Factory for 
creating the subset of class that match @Efl.Ui.Widget
+     interface.
+     The factory will automatically empties the cache when the application 
goes into pause.
 
      Creating objects is costly and time consuming, keeping a few on hand for 
when you next will need them helps a lot.
      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
      The cache might decide to flush itself when the application event pause 
is triggered.
    ]]
    methods {
-      @property item_class {
-         [[Define the class of the item returned by this factory.]]
-         get {}
-         set {}
-         values {
-            klass: const(Efl.Class); [[The class identifier to create item 
from.]]
-         }
-      }
       @property memory_limit {
          [[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.]]
          get {}
@@ -42,6 +36,8 @@ class Efl.Ui.Caching_Factory extends Efl.Loop_Consumer 
implements Efl.Ui.Factory
    implements {
       Efl.Ui.Factory.create;
       Efl.Ui.Factory.release;
+      Efl.Ui.Model.Connect.connect;
+      Efl.Ui.Widget_Factory.item_class { get; set; }
       Efl.Object.invalidate;
       Efl.Object.parent { set; }
    }
diff --git a/src/lib/elementary/efl_ui_image_factory.c 
b/src/lib/elementary/efl_ui_image_factory.c
index ce4d892dfa..4cd08cd5f5 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 *
 _efl_ui_image_factory_efl_object_constructor(Eo *obj, 
Efl_Ui_Image_Factory_Data *pd)
 {
    obj = efl_constructor(efl_super(obj, MY_CLASS));
-   efl_ui_caching_factory_item_class_set(obj, EFL_UI_IMAGE_CLASS);
+   efl_ui_widget_factory_item_class_set(obj, EFL_UI_IMAGE_CLASS);
 
    pd->property = NULL;
 
diff --git a/src/lib/elementary/efl_ui_layout_factory.c 
b/src/lib/elementary/efl_ui_layout_factory.c
index 150fd67aa0..0d81136114 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
 {
    obj = efl_constructor(efl_super(obj, MY_CLASS));
 
-   efl_ui_caching_factory_item_class_set(obj, EFL_UI_LAYOUT_CLASS);
+   efl_ui_widget_factory_item_class_set(obj, EFL_UI_LAYOUT_CLASS);
 
    pd->connects = 
eina_hash_stringshared_new(EINA_FREE_CB(eina_stringshare_del));
    pd->factory_connects = eina_hash_stringshared_new(EINA_FREE_CB(efl_unref));

-- 


Reply via email to