bu5hm4n pushed a commit to branch master.

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

commit 892c26f906d23595b709b834dde6b032bdd6d89d
Author: Cedric Bail <cedric.b...@free.fr>
Date:   Sun Sep 15 20:50:05 2019 -0700

    efl: simplify logic for widget created by factory.
    
    In an attempt to make things more complex than they should have been,
    I tried to change the inheritance tree on the fly and assume widget would
    rely on autodeleting its children. This is way more complex of a solution
    than to let the View actually release all the child manually and just set
    the window as the default parent.h
    
    Co-authored-by: Marcel Hollerbach <m...@marcel-hollerbach.de>
    
    Reviewed-by: Marcel Hollerbach <m...@marcel-hollerbach.de>
    Differential Revision: https://phab.enlightenment.org/D9953
---
 src/examples/elementary/layout_property_bind.c |  2 +-
 src/lib/efl/interfaces/efl_interfaces_main.c   |  7 ++-
 src/lib/efl/interfaces/efl_ui_factory.eo       |  1 -
 src/lib/efl/interfaces/efl_ui_view_factory.eo  |  1 -
 src/lib/elementary/efl_ui_caching_factory.c    | 76 +++++++++++++-------------
 src/lib/elementary/efl_ui_caching_factory.eo   |  2 +-
 src/lib/elementary/efl_ui_image_factory.c      |  6 +-
 src/lib/elementary/efl_ui_layout.c             |  4 +-
 src/lib/elementary/efl_ui_list_view.c          |  4 +-
 src/lib/elementary/efl_ui_widget_factory.c     | 32 ++++++++---
 src/lib/elementary/efl_ui_widget_factory.eo    |  1 +
 src/lib/elementary/elm_priv.h                  |  2 +
 12 files changed, 74 insertions(+), 64 deletions(-)

diff --git a/src/examples/elementary/layout_property_bind.c 
b/src/examples/elementary/layout_property_bind.c
index da4c5e6020..f9c5cf979e 100644
--- a/src/examples/elementary/layout_property_bind.c
+++ b/src/examples/elementary/layout_property_bind.c
@@ -169,7 +169,7 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
    efl_ui_property_bind(img_factory, "", "path"); //connect to "path" property
    efl_ui_factory_bind(priv->bt, "icon", img_factory);
 
-   efl_future_then(win, efl_ui_view_factory_create_with_event(img_factory, 
NULL, bxr),
+   efl_future_then(win, efl_ui_view_factory_create_with_event(img_factory, 
NULL),
                    .success = _wait_for_image,
                    .data = priv);
 
diff --git a/src/lib/efl/interfaces/efl_interfaces_main.c 
b/src/lib/efl/interfaces/efl_interfaces_main.c
index 4f144bebcf..91b7ff1775 100644
--- a/src/lib/efl/interfaces/efl_interfaces_main.c
+++ b/src/lib/efl/interfaces/efl_interfaces_main.c
@@ -127,10 +127,11 @@ _efl_ui_view_factory_item_created(Eo *factory, void *data 
EINA_UNUSED, const Ein
    return v;
 }
 
-static Eina_Future *
-_efl_ui_view_factory_create_with_event(Efl_Ui_Factory *factory, Eina_Iterator 
*models, Efl_Gfx_Entity *parent)
+EOLIAN static Eina_Future *
+_efl_ui_view_factory_create_with_event(Efl_Ui_Factory *factory, Eina_Iterator 
*models)
 {
-   return efl_future_then(factory, efl_ui_factory_create(factory, models, 
parent),
+   EINA_SAFETY_ON_NULL_RETURN_VAL(factory, NULL);
+   return efl_future_then(factory, efl_ui_factory_create(factory, models),
                           .success_type = EINA_VALUE_TYPE_ARRAY,
                           .success = _efl_ui_view_factory_item_created);
 }
diff --git a/src/lib/efl/interfaces/efl_ui_factory.eo 
b/src/lib/efl/interfaces/efl_ui_factory.eo
index bd3d84f11b..7eda0c6c84 100644
--- a/src/lib/efl/interfaces/efl_ui_factory.eo
+++ b/src/lib/efl/interfaces/efl_ui_factory.eo
@@ -23,7 +23,6 @@ interface @beta Efl.Ui.Factory extends Efl.Ui.Property_Bind, 
Efl.Ui.Factory_Bind
          params {
             models: iterator<Efl.Model>; [[Efl iterator providing the model to 
be associated to the new item.
                                            It should remain valid until the 
end of the function call.]]
-            parent: Efl.Gfx.Entity; [[Efl canvas.]]
          }
          return: future<Efl.Gfx.Entity>; [[Created UI object.]]
       }
diff --git a/src/lib/efl/interfaces/efl_ui_view_factory.eo 
b/src/lib/efl/interfaces/efl_ui_view_factory.eo
index bb1e4a44c3..728c25907c 100644
--- a/src/lib/efl/interfaces/efl_ui_view_factory.eo
+++ b/src/lib/efl/interfaces/efl_ui_view_factory.eo
@@ -12,7 +12,6 @@ class @beta Efl.Ui.View_Factory
                                  event onto.]]
             models: iterator<Efl.Model>; [[Efl iterator providing the model to 
be associated to the new item. It should
                                      remain valid until the end of the 
function call.]]
-            parent: Efl.Gfx.Entity; [[Efl canvas]]
          }
          return: future<Efl.Gfx.Entity>; [[Created UI object]]
       }
diff --git a/src/lib/elementary/efl_ui_caching_factory.c 
b/src/lib/elementary/efl_ui_caching_factory.c
index 843871ebe1..3035c308b4 100644
--- a/src/lib/elementary/efl_ui_caching_factory.c
+++ b/src/lib/elementary/efl_ui_caching_factory.c
@@ -125,7 +125,7 @@ _efl_ui_caching_factory_create_then(Eo *model, void *data, 
const Eina_Value v)
         // This is not ideal, we would want to gather all the request in one 
swoop here,
         // left for later improvement.
         f = efl_ui_factory_create(efl_super(r->factory, 
EFL_UI_CACHING_FACTORY_CLASS),
-                                  EINA_C_ARRAY_ITERATOR_NEW(models), 
r->parent);
+                                  EINA_C_ARRAY_ITERATOR_NEW(models));
         f = efl_future_then(r->factory, f,
                             .success = _efl_ui_caching_factory_uncap_then,
                             .success_type = EINA_VALUE_TYPE_ARRAY);
@@ -135,7 +135,6 @@ _efl_ui_caching_factory_create_then(Eo *model, void *data, 
const Eina_Value v)
    eina_hash_del(r->pd->lookup, style, w);
    _efl_ui_caching_factory_remove(r->pd, eina_list_data_find(r->pd->cache, w), 
w);
 
-   efl_parent_set(w, r->parent);
    efl_ui_view_model_set(w, model);
 
    return eina_value_object_init(w);
@@ -178,7 +177,7 @@ _efl_ui_caching_factory_group_cleanup(Eo *o EINA_UNUSED, 
void *data, const Eina_
 static Eina_Future *
 _efl_ui_caching_factory_efl_ui_factory_create(Eo *obj,
                                               Efl_Ui_Caching_Factory_Data *pd,
-                                              Eina_Iterator *models, 
Efl_Gfx_Entity *parent)
+                                              Eina_Iterator *models)
 {
    Efl_Ui_Caching_Factory_Request *r;
    Efl_Ui_Caching_Factory_Group_Request *gr;
@@ -195,7 +194,6 @@ _efl_ui_caching_factory_efl_ui_factory_create(Eo *obj,
         if (!r) return efl_loop_future_rejected(obj, ENOMEM);
 
         r->pd = pd;
-        r->parent = efl_ref(parent);
         r->factory = efl_ref(obj);
 
         all = calloc(1, sizeof (Eina_Future *));
@@ -231,7 +229,6 @@ _efl_ui_caching_factory_efl_ui_factory_create(Eo *obj,
        {
           w = eina_list_data_get(pd->cache);
           _efl_ui_caching_factory_remove(pd, pd->cache, w);
-          efl_parent_set(w, parent);
 
           efl_ui_view_model_set(w, model);
 
@@ -243,9 +240,11 @@ _efl_ui_caching_factory_efl_ui_factory_create(Eo *obj,
    // Now create object on the fly that are missing from the cache
    if (pd->klass)
      {
+        Efl_Ui_Widget *widget = efl_ui_widget_factory_widget_get(obj);
+
         EINA_ITERATOR_FOREACH(models, model)
           {
-             w = efl_add(pd->klass, parent,
+             w = efl_add(pd->klass, widget,
                          efl_ui_view_model_set(efl_added, model),
                          efl_event_callback_call(obj, 
EFL_UI_FACTORY_EVENT_ITEM_CONSTRUCTING, efl_added));
              efl_event_callback_call(obj, EFL_UI_FACTORY_EVENT_ITEM_BUILDING, 
w);
@@ -260,8 +259,7 @@ _efl_ui_caching_factory_efl_ui_factory_create(Eo *obj,
         return f;
      }
 
-   f = efl_ui_factory_create(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS),
-                             models, parent);
+   f = efl_ui_factory_create(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), 
models);
    return efl_future_then(obj, f,
                           .success = _efl_ui_caching_factory_group_create_then,
                           .success_type = EINA_VALUE_TYPE_ARRAY,
@@ -357,7 +355,6 @@ _efl_ui_caching_factory_efl_ui_factory_release(Eo *obj,
      }
 
    // Change parent, disconnect the object and make it invisible
-   efl_parent_set(ui_view, obj);
    efl_gfx_entity_visible_set(ui_view, EINA_FALSE);
    efl_ui_view_model_set(ui_view, NULL);
 
@@ -379,29 +376,6 @@ _efl_ui_caching_factory_efl_ui_factory_release(Eo *obj,
    _efl_ui_caching_factory_flush(obj, pd);
 }
 
-static void
-_efl_ui_caching_factory_efl_object_invalidate(Eo *obj EINA_UNUSED,
-                                              Efl_Ui_Caching_Factory_Data *pd)
-{
-   // 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 *
-_efl_ui_caching_factory_app_get(Eo *obj)
-{
-   Efl_Object *p;
-
-   p = efl_parent_get(obj);
-   if (!p) return NULL;
-
-   // It is acceptable to just have a loop as parent and not an app
-   return efl_provider_find(obj, EFL_APP_CLASS);
-}
-
 static void
 _efl_ui_caching_factory_pause(void *data, const Efl_Event *event EINA_UNUSED)
 {
@@ -418,18 +392,42 @@ _efl_ui_caching_factory_pause(void *data, const Efl_Event 
*event EINA_UNUSED)
 }
 
 static void
-_efl_ui_caching_factory_efl_object_parent_set(Eo *obj, 
Efl_Ui_Caching_Factory_Data *pd, Efl_Object *parent)
+_invalidate(void *data, const Efl_Event *event EINA_UNUSED)
 {
-   Efl_App *a;
+   Efl_Ui_Caching_Factory_Data *pd = data;
 
-   a = _efl_ui_caching_factory_app_get(obj);
-   if (a) efl_event_callback_del(a, EFL_APP_EVENT_PAUSE, 
_efl_ui_caching_factory_pause, pd);
+   // 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_Object *
+_efl_ui_caching_factory_efl_object_finalize(Eo *obj, 
Efl_Ui_Caching_Factory_Data *pd)
+{
+   Efl_App *a;
 
-   efl_parent_set(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), parent);
+   obj = efl_finalize(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS));
+   if (!obj) return NULL;
 
-   // We are fetching the parent again, just in case the update was denied
-   a = _efl_ui_caching_factory_app_get(obj);
+   a = efl_provider_find(obj, EFL_APP_CLASS);
    if (a) efl_event_callback_add(a, EFL_APP_EVENT_PAUSE, 
_efl_ui_caching_factory_pause, pd);
+
+   // The order of the invalidate event is guaranteed to happen before any 
children is invalidated
+   // this is not the case for the children invalidate function, which can 
happen in random order.
+   efl_event_callback_add(efl_ui_widget_factory_widget_get(obj), 
EFL_EVENT_INVALIDATE, _invalidate, pd);
+
+   return obj;
+}
+
+static void
+_efl_ui_caching_factory_efl_object_invalidate(Eo *obj,
+                                              Efl_Ui_Caching_Factory_Data *pd)
+{
+   efl_event_callback_del(efl_ui_widget_factory_widget_get(obj), 
EFL_EVENT_INVALIDATE, _invalidate, pd);
+
+   efl_invalidate(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS));
 }
 
 static Eina_Error
diff --git a/src/lib/elementary/efl_ui_caching_factory.eo 
b/src/lib/elementary/efl_ui_caching_factory.eo
index f0a5aae443..9907da7e05 100644
--- a/src/lib/elementary/efl_ui_caching_factory.eo
+++ b/src/lib/elementary/efl_ui_caching_factory.eo
@@ -41,6 +41,6 @@ class @beta Efl.Ui.Caching_Factory extends 
Efl.Ui.Widget_Factory
       Efl.Ui.Property_Bind.property_bind;
       Efl.Ui.Widget_Factory.item_class { get; set; }
       Efl.Object.invalidate;
-      Efl.Object.parent { set; }
+      Efl.Object.finalize;
    }
 }
diff --git a/src/lib/elementary/efl_ui_image_factory.c 
b/src/lib/elementary/efl_ui_image_factory.c
index 615f202d38..f8034040aa 100644
--- a/src/lib/elementary/efl_ui_image_factory.c
+++ b/src/lib/elementary/efl_ui_image_factory.c
@@ -47,13 +47,11 @@ _efl_ui_image_factory_efl_object_destructor(Eo *obj 
EINA_UNUSED, Efl_Ui_Image_Fa
 }
 
 EOLIAN static Eina_Future *
-_efl_ui_image_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Image_Factory_Data 
*pd,
-                                            Eina_Iterator *models, 
Efl_Gfx_Entity *parent)
+_efl_ui_image_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Image_Factory_Data 
*pd, Eina_Iterator *models)
 {
-   if (!parent) return efl_loop_future_rejected(obj, 
EFL_FACTORY_ERROR_NOT_SUPPORTED);
    if (!pd->property) return efl_loop_future_rejected(obj, 
EFL_FACTORY_ERROR_NOT_SUPPORTED);
 
-   return efl_ui_factory_create(efl_super(obj, EFL_UI_IMAGE_FACTORY_CLASS), 
models, parent);
+   return efl_ui_factory_create(efl_super(obj, EFL_UI_IMAGE_FACTORY_CLASS), 
models);
 }
 
 EOLIAN static Eina_Error
diff --git a/src/lib/elementary/efl_ui_layout.c 
b/src/lib/elementary/efl_ui_layout.c
index bcc947ba22..e0b8250f63 100644
--- a/src/lib/elementary/efl_ui_layout.c
+++ b/src/lib/elementary/efl_ui_layout.c
@@ -2238,9 +2238,7 @@ 
_efl_ui_layout_view_model_content_update(Efl_Ui_Layout_Data *pd, Efl_Ui_Layout_F
    request->tracking = tracking;
 
    models[0] = efl_ui_view_model_get(pd->obj);
-   f = efl_ui_view_factory_create_with_event(tracking->factory,
-                                             EINA_C_ARRAY_ITERATOR_NEW(models),
-                                             pd->obj);
+   f = efl_ui_view_factory_create_with_event(tracking->factory, 
EINA_C_ARRAY_ITERATOR_NEW(models));
    f = efl_future_then(pd->obj, f,
                        .success = _content_created,
                        .success_type = EINA_VALUE_TYPE_ARRAY,
diff --git a/src/lib/elementary/efl_ui_list_view.c 
b/src/lib/elementary/efl_ui_list_view.c
index e74e15c792..8329301579 100644
--- a/src/lib/elementary/efl_ui_list_view.c
+++ b/src/lib/elementary/efl_ui_list_view.c
@@ -959,9 +959,7 @@ _efl_ui_list_view_efl_ui_list_view_model_realize(Eo *obj, 
Efl_Ui_List_View_Data
    tracking->pd = pd;
    childrens[0] = item->children;
 
-   item->layout_request = efl_ui_view_factory_create_with_event(pd->factory,
-                                                                
EINA_C_ARRAY_ITERATOR_NEW(childrens),
-                                                                obj);
+   item->layout_request = efl_ui_view_factory_create_with_event(pd->factory, 
EINA_C_ARRAY_ITERATOR_NEW(childrens));
    item->layout_request = efl_future_then(obj, item->layout_request,
                                           .success = _content_created,
                                           .success_type = 
EINA_VALUE_TYPE_ARRAY,
diff --git a/src/lib/elementary/efl_ui_widget_factory.c 
b/src/lib/elementary/efl_ui_widget_factory.c
index 0d6f64194a..a485edfe7b 100644
--- a/src/lib/elementary/efl_ui_widget_factory.c
+++ b/src/lib/elementary/efl_ui_widget_factory.c
@@ -32,6 +32,8 @@ struct _Efl_Ui_Widget_Factory_Data
 {
    const Efl_Class *klass;
 
+   Efl_Ui_Widget *parenting_widget;
+
    Eina_Hash *parts;
 
    Eina_Stringshare *style;
@@ -41,9 +43,25 @@ struct _Efl_Ui_Widget_Factory_Request
 {
    Efl_Ui_Widget_Factory_Data *pd;
    Efl_Ui_Factory *factory;
-   Eo *parent;
 };
 
+static Efl_Object *
+_efl_ui_widget_factory_efl_object_finalize(Eo *obj, Efl_Ui_Widget_Factory_Data 
*pd)
+{
+   pd->parenting_widget = efl_provider_find(obj, EFL_UI_WIDGET_CLASS);
+   if (!pd->parenting_widget) return NULL;
+
+   return efl_finalize(efl_super(obj, EFL_UI_WIDGET_FACTORY_CLASS));
+}
+
+Efl_Ui_Win *
+efl_ui_widget_factory_widget_get(Efl_Ui_Widget_Factory *factory)
+{
+   Efl_Ui_Widget_Factory_Data *pd = efl_data_scope_get(factory, 
EFL_UI_WIDGET_FACTORY_CLASS);
+
+   return pd->parenting_widget;
+}
+
 static void
 _efl_ui_widget_factory_item_class_set(Eo *obj, Efl_Ui_Widget_Factory_Data *pd,
                                       const Efl_Class *klass)
@@ -151,7 +169,8 @@ 
_efl_ui_widget_factory_efl_object_constructor(Efl_Ui_Widget_Factory *obj,
 
 static Efl_Ui_Widget *
 _efl_ui_widget_create(const Efl_Ui_Factory *factory,
-                      const Efl_Class *klass, Eo *parent,
+                      const Efl_Class *klass,
+                      Efl_Ui_Widget *parent,
                       Efl_Model *model)
 {
    Efl_Ui_Widget *w;
@@ -169,7 +188,7 @@ _efl_ui_widget_factory_create_then(Eo *model, void *data, 
const Eina_Value v EIN
    Efl_Ui_Widget_Factory_Request *r = data;
    Efl_Ui_Widget *w;
 
-   w = _efl_ui_widget_create(r->factory, r->pd->klass, r->parent, model);
+   w = _efl_ui_widget_create(r->factory, r->pd->klass, 
r->pd->parenting_widget, model);
    if (!w) return eina_value_error_init(ENOMEM);
    return eina_value_object_init(w);
 }
@@ -186,13 +205,12 @@ _efl_ui_widget_factory_create_cleanup(Eo *o EINA_UNUSED, 
void *data, const Eina_
    Efl_Ui_Widget_Factory_Request *r = data;
 
    efl_unref(r->factory);
-   efl_unref(r->parent);
    free(r);
 }
 
 static Eina_Future *
 _efl_ui_widget_factory_efl_ui_factory_create(Eo *obj, 
Efl_Ui_Widget_Factory_Data *pd,
-                                             Eina_Iterator *models, 
Efl_Gfx_Entity *parent)
+                                             Eina_Iterator *models)
 {
    Efl_Ui_Widget_Factory_Request *r;
    Eina_Future **f;
@@ -211,7 +229,7 @@ _efl_ui_widget_factory_efl_ui_factory_create(Eo *obj, 
Efl_Ui_Widget_Factory_Data
 
         EINA_ITERATOR_FOREACH(models, model)
           {
-             w = _efl_ui_widget_create(obj, pd->klass, parent, model);
+             w = _efl_ui_widget_create(obj, pd->klass, pd->parenting_widget, 
model);
 
              if (!w) return efl_loop_future_rejected(obj, ENOMEM);
              eina_value_array_append(&r, w);
@@ -225,7 +243,6 @@ _efl_ui_widget_factory_efl_ui_factory_create(Eo *obj, 
Efl_Ui_Widget_Factory_Data
    if (!r) return efl_loop_future_rejected(obj, ENOMEM);
 
    r->pd = pd;
-   r->parent = efl_ref(parent);
    r->factory = efl_ref(obj);
 
    f = calloc(count + 1, sizeof (Eina_Future *));
@@ -249,7 +266,6 @@ _efl_ui_widget_factory_efl_ui_factory_create(Eo *obj, 
Efl_Ui_Widget_Factory_Data
                           .free = _efl_ui_widget_factory_create_cleanup);
 
 alloc_array_error:
-   efl_unref(r->parent);
    efl_unref(r->factory);
    free(r);
    eina_iterator_free(models);
diff --git a/src/lib/elementary/efl_ui_widget_factory.eo 
b/src/lib/elementary/efl_ui_widget_factory.eo
index c00775a224..82ce7292bd 100644
--- a/src/lib/elementary/efl_ui_widget_factory.eo
+++ b/src/lib/elementary/efl_ui_widget_factory.eo
@@ -22,6 +22,7 @@ class @beta Efl.Ui.Widget_Factory extends Efl.Loop_Consumer 
implements Efl.Ui.Fa
       Efl.Ui.Factory.release;
       Efl.Ui.Property_Bind.property_bind;
       Efl.Part.part_get;
+      Efl.Object.finalize;
    }
    constructors {
       .item_class @optional;
diff --git a/src/lib/elementary/elm_priv.h b/src/lib/elementary/elm_priv.h
index b94322c004..f1b959b69f 100644
--- a/src/lib/elementary/elm_priv.h
+++ b/src/lib/elementary/elm_priv.h
@@ -892,6 +892,8 @@ extern const char SIG_LAYOUT_UNFOCUSED[];
 
 extern Eina_Stringshare *_property_style_ss;
 
+Efl_Ui_Win *efl_ui_widget_factory_widget_get(Efl_Ui_Widget_Factory *factory);
+
 extern Eina_Bool _config_profile_lock;
 
 extern Eina_FreeQ *postponed_fq;

-- 


Reply via email to