tasn pushed a commit to branch master.

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

commit 537b138a2328008c16cf54401dc442bd6c8d11c5
Author: Tom Hacohen <t...@stosb.com>
Date:   Thu May 5 16:08:08 2016 +0100

    Eo composite: change composite objects to not be tied to parent
    
    This commit breaks behaviour!
    Re-parenting no longer detaches composite objects, so watch out.
    
    Now you can have an object be a composite object of an object although
    it's not its child. This allows widgets to do things like having an
    object as the child of a child object while still making it a composite
    object to the main object.
    
    With this change, composite objects don't keep a reference to the child,
    but instead composite "bonds" are implicitly removed when either the
    parent or the child are destructed.
---
 src/lib/eo/eo_base_class.c           | 62 +++++++++++++++++++++++++-----------
 src/lib/eo/eo_private.h              |  1 -
 src/tests/eo/suite/eo_test_general.c | 18 +++++++++--
 3 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 1cbb644..f8f1814 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -19,6 +19,7 @@ typedef struct
 {
    const char                *id;
    const char                *comment;
+   Eo                        *composite_parent;
    Eina_Inlist               *generic_data;
    Eo                      ***wrefs;
 } Eo_Base_Extension;
@@ -82,7 +83,7 @@ _eo_base_extension_noneed(Eo_Base_Data *pd)
 {
    Eo_Base_Extension *ext = pd->ext;
    if ((!ext) || (ext->id) || (ext->comment) || (ext->generic_data) ||
-       (ext->wrefs)) return;
+       (ext->wrefs) || (ext->composite_parent)) return;
    _eo_base_extension_free(pd->ext);
    pd->ext = NULL;
 }
@@ -478,11 +479,6 @@ _eo_base_parent_set(Eo *obj, Eo_Base_Data *pd, Eo 
*parent_id)
    if (pd->parent == parent_id)
      return;
 
-   if (eo_composite_part_is(obj) && pd->parent)
-     {
-        eo_composite_detach(pd->parent, obj);
-     }
-
    if (pd->parent)
      {
         Eo_Base_Data *old_parent_pd;
@@ -1236,23 +1232,34 @@ _eo_base_composite_attach(Eo *parent_id, Eo_Base_Data 
*pd EINA_UNUSED, Eo *comp_
    EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
    EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE);
 
-   if (!eo_isa(parent_id, _eo_class_id_get(comp_obj->klass))) return 
EINA_FALSE;
+   if (!eo_isa(parent_id, _eo_class_id_get(comp_obj->klass)))
+     {
+        return EINA_FALSE;
+     }
 
+   Eo_Base_Data *comp_pd = eo_data_scope_get(comp_obj_id, EO_BASE_CLASS);
+   /* Don't composite if we already have a composite object of this type */
      {
         Eina_List *itr;
         Eo *emb_obj_id;
         EINA_LIST_FOREACH(parent->composite_objects, itr, emb_obj_id)
           {
              EO_OBJ_POINTER_RETURN_VAL(emb_obj_id, emb_obj, EINA_FALSE);
-             if(emb_obj->klass == comp_obj->klass)
+             if (emb_obj->klass == comp_obj->klass)
                return EINA_FALSE;
           }
      }
 
-   comp_obj->composite = EINA_TRUE;
-   parent->composite_objects = eina_list_prepend(parent->composite_objects, 
comp_obj_id);
+   if (eo_composite_part_is(comp_obj_id))
+     {
+        eo_composite_detach(comp_pd->ext->composite_parent, comp_obj_id);
+     }
+
+   /* Set the parent comp on the child. */
+   _eo_base_extension_need(comp_pd);
+   comp_pd->ext->composite_parent = parent_id;
 
-   eo_parent_set(comp_obj_id, parent_id);
+   parent->composite_objects = eina_list_prepend(parent->composite_objects, 
comp_obj_id);
 
    return EINA_TRUE;
 }
@@ -1263,22 +1270,25 @@ _eo_base_composite_detach(Eo *parent_id, Eo_Base_Data 
*pd EINA_UNUSED, Eo *comp_
    EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
    EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE);
 
-   if (!comp_obj->composite)
+   if (!eo_composite_part_is(comp_obj_id))
       return EINA_FALSE;
 
-   comp_obj->composite = EINA_FALSE;
    parent->composite_objects = eina_list_remove(parent->composite_objects, 
comp_obj_id);
-   eo_parent_set(comp_obj_id, NULL);
+   /* Clear the comp parent on the child. */
+     {
+        Eo_Base_Data *comp_pd = eo_data_scope_get(comp_obj_id, EO_BASE_CLASS);
+        comp_pd->ext->composite_parent = NULL;
+
+        _eo_base_extension_noneed(comp_pd);
+     }
 
    return EINA_TRUE;
 }
 
 EOLIAN static Eina_Bool
-_eo_base_composite_part_is(Eo *comp_obj_id, Eo_Base_Data *pd EINA_UNUSED)
+_eo_base_composite_part_is(Eo *comp_obj_id EINA_UNUSED, Eo_Base_Data *pd)
 {
-   EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
-
-   return comp_obj->composite;
+   return pd->ext && pd->ext->composite_parent;
 }
 
 /* Eo_Dbg */
@@ -1408,6 +1418,22 @@ _eo_base_destructor(Eo *obj, Eo_Base_Data *pd)
         eo_parent_set(child, NULL);
      }
 
+   /* If we are a composite object, detach children */
+     {
+        EO_OBJ_POINTER_RETURN(obj, obj_data);
+        Eina_List *itr;
+        Eo *emb_obj_id;
+        EINA_LIST_FOREACH(obj_data->composite_objects, itr, emb_obj_id)
+          {
+             eo_composite_detach(obj, emb_obj_id);
+          }
+     }
+
+   if (pd->ext && pd->ext->composite_parent)
+     {
+        eo_composite_detach(pd->ext->composite_parent, obj);
+     }
+
    if (pd->parent)
      {
         ERR("Object '%p' still has a parent at the time of destruction.", obj);
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index 323fc02..4f60740 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -103,7 +103,6 @@ struct _Eo_Object
      Eina_Bool condtor_done:1;
      Eina_Bool finalized:1;
 
-     Eina_Bool composite:1;
      Eina_Bool del_triggered:1;
      Eina_Bool destructed:1;
      Eina_Bool manual_free:1;
diff --git a/src/tests/eo/suite/eo_test_general.c 
b/src/tests/eo/suite/eo_test_general.c
index 51b1ac4..6578864 100644
--- a/src/tests/eo/suite/eo_test_general.c
+++ b/src/tests/eo/suite/eo_test_general.c
@@ -299,12 +299,24 @@ START_TEST(eo_composite_tests)
    fail_if(!obj);
    Eo *obj2 = eo_add(SIMPLE_CLASS, NULL);
    fail_if(!obj2);
+   Eo *obj3 = eo_add(SIMPLE_CLASS, NULL);
+   fail_if(!obj3);
 
    eo_composite_attach(obj, obj2);
-   eo_parent_set(obj2, NULL);
-   fail_if(eo_composite_part_is(obj2));
+   fail_if(!eo_composite_part_is(obj2));
+
+   /* Check swapping attachments works. */
+   eo_composite_attach(obj3, obj2);
+   fail_if(!eo_composite_part_is(obj2));
+
+   /* Check that a deletion of a child detaches from the parent. */
+   eo_del(obj2);
+   fail_if(!eo_composite_attach(obj3, obj));
+
+   /* Check that a deletion of the parent detaches the child. */
+   eo_del(obj3);
+   fail_if(eo_composite_part_is(obj));
 
-   eo_unref(obj2);
    eo_unref(obj);
 
    eo_shutdown();

-- 


Reply via email to