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 <mail@marcel-hollerbach.de>

Reviewed-by: Marcel Hollerbach <mail@marcel-hollerbach.de>
Differential Revision: https://phab.enlightenment.org/D9953
This commit is contained in:
Cedric Bail 2019-09-15 20:50:05 -07:00 committed by Marcel Hollerbach
parent 759ac54e7f
commit 892c26f906
12 changed files with 74 additions and 64 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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.]]
}

View File

@ -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]]
}

View File

@ -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_Ui_Caching_Factory_Data *pd = data;
// 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;
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);
obj = efl_finalize(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS));
if (!obj) return NULL;
efl_parent_set(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), parent);
// 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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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;