From 0248d504b34f5f4324102ae406b848c2c8fe28c4 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Thu, 15 Aug 2019 20:45:09 -0700 Subject: [PATCH] elementary: switch Efl.Ui.Factory API to a batch API and update all class using it. Reviewed-by: Lauro Neto > Differential Revision: https://phab.enlightenment.org/D9579 --- src/lib/efl/Efl.h | 4 +- src/lib/efl/interfaces/efl_interfaces_main.c | 15 +- src/lib/efl/interfaces/efl_ui_factory.eo | 2 +- src/lib/elementary/efl_ui_caching_factory.c | 173 +++++++++++++++---- src/lib/elementary/efl_ui_image_factory.c | 15 +- src/lib/elementary/efl_ui_layout.c | 29 ++-- src/lib/elementary/efl_ui_layout_factory.c | 26 +-- src/lib/elementary/efl_ui_list_view.c | 11 +- src/lib/elementary/efl_ui_widget_factory.c | 107 ++++++++---- 9 files changed, 267 insertions(+), 115 deletions(-) diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h index a75b683b52..e1cfe4156e 100644 --- a/src/lib/efl/Efl.h +++ b/src/lib/efl/Efl.h @@ -211,13 +211,13 @@ EAPI Efl_Object *efl_part(const Eo *obj, const char *name); * @param[in] parent The parent of the newly created item * @return A future that will resolve with the newly created item. * - * @since 1.22 + * @since 1.23 * @note This exists as we always want to trigger the event once all the logic * of every factory in the chain has done what it planned to do. Basically we * want the inverse of inheritance call like efl_super. So we do setup the future * in this way. */ -EAPI Eina_Future *efl_ui_view_factory_create_with_event(Efl_Ui_Factory *factory, Efl_Model *model, Efl_Gfx_Entity *parent); +EAPI Eina_Future *efl_ui_view_factory_create_with_event(Efl_Ui_Factory *factory, Eina_Iterator *models, Efl_Gfx_Entity *parent); #else diff --git a/src/lib/efl/interfaces/efl_interfaces_main.c b/src/lib/efl/interfaces/efl_interfaces_main.c index 47c143c120..4e85ab6bbc 100644 --- a/src/lib/efl/interfaces/efl_interfaces_main.c +++ b/src/lib/efl/interfaces/efl_interfaces_main.c @@ -119,19 +119,22 @@ static Eina_Value _efl_ui_view_factory_item_created(Eo *factory, void *data EINA_UNUSED, const Eina_Value v) { Efl_Ui_Factory_Item_Created_Event event = { NULL, NULL }; + int len, i; - eina_value_pget(&v, &event.item); - event.model = efl_ui_view_model_get(event.item); + EINA_VALUE_ARRAY_FOREACH(&v, len, i, event.item) + { + event.model = efl_ui_view_model_get(event.item); - efl_event_callback_call(factory, EFL_UI_FACTORY_EVENT_CREATED, &event); + efl_event_callback_call(factory, EFL_UI_FACTORY_EVENT_CREATED, &event); + } return v; } EAPI Eina_Future * -efl_ui_view_factory_create_with_event(Efl_Ui_Factory *factory, Efl_Model *model, Efl_Gfx_Entity *parent) +efl_ui_view_factory_create_with_event(Efl_Ui_Factory *factory, Eina_Iterator *models, Efl_Gfx_Entity *parent) { - return efl_future_then(factory, efl_ui_factory_create(factory, model, parent), - .success_type = EINA_VALUE_TYPE_OBJECT, + return efl_future_then(factory, efl_ui_factory_create(factory, models, parent), + .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 e2c2ae3318..38bb51455a 100644 --- a/src/lib/efl/interfaces/efl_ui_factory.eo +++ b/src/lib/efl/interfaces/efl_ui_factory.eo @@ -11,7 +11,7 @@ interface @beta Efl.Ui.Factory extends Efl.Ui.Property_Bind, Efl.Ui.Factory_Bind create { [[Create a UI object from the necessary properties in the specified model.]] params { - model: Efl.Model; [[Efl model]] + models: iterator; [[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; [[Created UI object]] diff --git a/src/lib/elementary/efl_ui_caching_factory.c b/src/lib/elementary/efl_ui_caching_factory.c index bea7a3360c..a7fb277356 100644 --- a/src/lib/elementary/efl_ui_caching_factory.c +++ b/src/lib/elementary/efl_ui_caching_factory.c @@ -7,6 +7,7 @@ typedef struct _Efl_Ui_Caching_Factory_Data Efl_Ui_Caching_Factory_Data; typedef struct _Efl_Ui_Caching_Factory_Request Efl_Ui_Caching_Factory_Request; +typedef struct _Efl_Ui_Caching_Factory_Group_Request Efl_Ui_Caching_Factory_Group_Request; struct _Efl_Ui_Caching_Factory_Data { @@ -31,8 +32,13 @@ struct _Efl_Ui_Caching_Factory_Request { Efl_Ui_Caching_Factory_Data *pd; + Efl_Ui_Caching_Factory *factory; Eo *parent; - Efl_Model *model; +}; + +struct _Efl_Ui_Caching_Factory_Group_Request +{ + Eina_Value done; }; // Clear the cache until it meet the constraint @@ -84,88 +90,179 @@ _efl_ui_caching_factory_flush(Eo *obj, Efl_Ui_Caching_Factory_Data *pd) } static Eina_Value -_efl_ui_caching_factory_create_then(Eo *obj EINA_UNUSED, void *data, const Eina_Value v) +_efl_ui_caching_factory_uncap_then(Eo *model EINA_UNUSED, + void *data EINA_UNUSED, + const Eina_Value v) +{ + Efl_Ui_Widget *widget = NULL; + + if (eina_value_array_count(&v) != 1) return eina_value_error_init(EINVAL); + + eina_value_array_get(&v, 0, &widget); + + return eina_value_object_init(widget); +} + +static Eina_Value +_efl_ui_caching_factory_create_then(Eo *model, void *data, const Eina_Value v) { Efl_Ui_Caching_Factory_Request *r = data; Efl_Ui_Widget *w; - const char *string = NULL; + const char *style = NULL; - if (!eina_value_string_get(&v, &string)) + if (!eina_value_string_get(&v, &style)) return eina_value_error_init(EFL_MODEL_ERROR_NOT_SUPPORTED); - w = eina_hash_find(r->pd->lookup, string); + w = eina_hash_find(r->pd->lookup, style); if (!w) { Eina_Future *f; + Eo *models[1] = { model }; // 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); + // 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); + f = efl_future_then(r->factory, f, + .success = _efl_ui_caching_factory_uncap_then, + .success_type = EINA_VALUE_TYPE_ARRAY); 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); + 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, r->model); + efl_ui_view_model_set(w, 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_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->factory); efl_unref(r->parent); free(r); } +static Eina_Value +_efl_ui_caching_factory_group_create_then(Eo *obj EINA_UNUSED, + void *data, + const Eina_Value v) +{ + Efl_Ui_Caching_Factory_Group_Request *gr = data; + int len, i; + Efl_Ui_Widget *widget; + + EINA_VALUE_ARRAY_FOREACH(&v, len, i, widget) + eina_value_array_append(&gr->done, widget); + + return eina_value_reference_copy(&gr->done); +} + +static void +_efl_ui_caching_factory_group_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED) +{ + Efl_Ui_Caching_Factory_Group_Request *gr = data; + + eina_value_flush(&gr->done); + free(gr); +} + static Eina_Future * _efl_ui_caching_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Caching_Factory_Data *pd, - Efl_Model *model, Efl_Gfx_Entity *parent) + Eina_Iterator *models, Efl_Gfx_Entity *parent) { + Efl_Ui_Caching_Factory_Group_Request *gr; Efl_Gfx_Entity *w = NULL; + Efl_Model *model; + Eina_Future *f; - if (pd->cache) + if (pd->cache && pd->style && !pd->klass) { - if (pd->style && !pd->klass) + Efl_Ui_Caching_Factory_Request *r; + Eina_Future **all; + int count = 0; + + r = calloc(1, sizeof (Efl_Ui_Caching_Factory_Request)); + 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 *)); + if (!all) return efl_loop_future_rejected(obj, ENOMEM); + + EINA_ITERATOR_FOREACH(models, model) { - Efl_Ui_Caching_Factory_Request *r; + all[count++] = efl_future_then(model, + efl_model_property_ready_get(model, pd->style), + .success = _efl_ui_caching_factory_create_then, + .data = r); - r = calloc(1, sizeof (Efl_Ui_Caching_Factory_Request)); - if (!r) return efl_loop_future_rejected(obj, ENOMEM); + all = realloc(all, (count + 1) * sizeof (Eina_Future *)); + if (!all) return efl_loop_future_rejected(obj, ENOMEM); + } + eina_iterator_free(models); - r->pd = pd; - r->parent = efl_ref(parent); - r->model = efl_ref(model); + all[count] = EINA_FUTURE_SENTINEL; - 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); + return efl_future_then(obj, eina_future_all_array(all), + .data = r, + .free = _efl_ui_caching_factory_cleanup); + } + + gr = calloc(1, sizeof (Efl_Ui_Caching_Factory_Group_Request)); + if (!gr) return efl_loop_future_rejected(obj, ENOMEM); + + eina_value_array_setup(&gr->done, EINA_VALUE_TYPE_OBJECT, 4); + + // First get as much object from the cache as possible + if (pd->cache) + EINA_ITERATOR_FOREACH(models, model) + { + 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); + + eina_value_array_append(&gr->done, w); + + if (!pd->cache) break; + } + + // Now create object on the fly that are missing from the cache + if (pd->klass) + { + EINA_ITERATOR_FOREACH(models, model) + { + w = efl_add(pd->klass, parent, + efl_ui_view_model_set(efl_added, model)); + eina_value_array_append(&gr->done, w); } - w = eina_list_data_get(pd->cache); + f = efl_loop_future_resolved(obj, gr->done); - _efl_ui_caching_factory_remove(pd, pd->cache, w); + eina_value_flush(&gr->done); + free(gr); - efl_parent_set(w, parent); + return f; } - if (!w) - { - 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(w, model); - - return efl_loop_future_resolved(obj, eina_value_object_init(w)); + f = efl_ui_factory_create(efl_super(obj, EFL_UI_CACHING_FACTORY_CLASS), + models, parent); + return efl_future_then(obj, f, + .success = _efl_ui_caching_factory_group_create_then, + .success_type = EINA_VALUE_TYPE_ARRAY, + .data = gr, + .free = _efl_ui_caching_factory_group_cleanup); } static void diff --git a/src/lib/elementary/efl_ui_image_factory.c b/src/lib/elementary/efl_ui_image_factory.c index 9bf9f39a9c..4ea556e507 100644 --- a/src/lib/elementary/efl_ui_image_factory.c +++ b/src/lib/elementary/efl_ui_image_factory.c @@ -36,28 +36,29 @@ _efl_ui_image_factory_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Ui_Image_Fa static Eina_Value _efl_ui_image_factory_bind(Eo *obj EINA_UNUSED, void *data, const Eina_Value value) { - Efl_Gfx_Entity *entity = NULL; Efl_Ui_Image_Factory_Data *pd = data; + Efl_Gfx_Entity *entity; + int len, i; - eina_value_pget(&value, &entity); - - efl_ui_property_bind(entity, "filename", pd->property); + EINA_VALUE_ARRAY_FOREACH(&value, len, i, entity) + efl_ui_property_bind(entity, "filename", pd->property); return value; } EOLIAN static Eina_Future * -_efl_ui_image_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Image_Factory_Data *pd, Efl_Model *model, Efl_Gfx_Entity *parent) +_efl_ui_image_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Image_Factory_Data *pd, + Eina_Iterator *models, Efl_Gfx_Entity *parent) { Eina_Future *f; 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); - f = efl_ui_factory_create(efl_super(obj, EFL_UI_IMAGE_FACTORY_CLASS), model, parent); + f = efl_ui_factory_create(efl_super(obj, EFL_UI_IMAGE_FACTORY_CLASS), models, parent); return efl_future_then(obj, f, - .success_type = EINA_VALUE_TYPE_OBJECT, + .success_type = EINA_VALUE_TYPE_ARRAY, .success = _efl_ui_image_factory_bind, .data = pd); } diff --git a/src/lib/elementary/efl_ui_layout.c b/src/lib/elementary/efl_ui_layout.c index 224ca32321..5ae0403331 100644 --- a/src/lib/elementary/efl_ui_layout.c +++ b/src/lib/elementary/efl_ui_layout.c @@ -2184,15 +2184,17 @@ _content_created(Eo *obj, void *data, const Eina_Value value) Efl_Ui_Layout_Factory_Request *request = data; Efl_Gfx_Entity *content = NULL; Efl_Gfx_Entity *old_content; + int len, i; - eina_value_get(&value, &content); + EINA_VALUE_ARRAY_FOREACH(&value, len, i, content) + { + // Recycle old content + old_content = efl_content_get(efl_part(obj, request->key)); + if (old_content) efl_ui_factory_release(request->factory, old_content); - // Recycle old content - old_content = efl_content_get(efl_part(obj, request->key)); - if (old_content) efl_ui_factory_release(request->factory, old_content); - - // Set new content - efl_content_set(efl_part(obj, request->key), content); + // Set new content + efl_content_set(efl_part(obj, request->key), content); + } return value; } @@ -2211,10 +2213,11 @@ _clean_request(Eo *obj EINA_UNUSED, void *data, const Eina_Future *dead_future E static void _efl_ui_layout_view_model_content_update(Efl_Ui_Layout_Data *pd, Efl_Ui_Layout_Factory_Tracking *tracking, const char *key) { - Efl_Ui_Layout_Factory_Request *request = calloc(1, sizeof (Efl_Ui_Layout_Factory_Request)); + Efl_Ui_Layout_Factory_Request *request; Eina_Future *f; - Efl_Model *model; + Efl_Model *models[1]; + request = calloc(1, sizeof (Efl_Ui_Layout_Factory_Request)); if (!request) return ; if (tracking->in_flight) eina_future_cancel(tracking->in_flight); @@ -2224,11 +2227,13 @@ _efl_ui_layout_view_model_content_update(Efl_Ui_Layout_Data *pd, Efl_Ui_Layout_F request->factory = efl_ref(tracking->factory); request->tracking = tracking; - model = efl_ui_view_model_get(pd->obj); - f = efl_ui_view_factory_create_with_event(tracking->factory, model, pd->obj); + 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_future_then(pd->obj, f, .success = _content_created, - .success_type = EINA_VALUE_TYPE_OBJECT, + .success_type = EINA_VALUE_TYPE_ARRAY, .data = request, .free = _clean_request); } diff --git a/src/lib/elementary/efl_ui_layout_factory.c b/src/lib/elementary/efl_ui_layout_factory.c index 310bc5224a..4ab6d19fe9 100644 --- a/src/lib/elementary/efl_ui_layout_factory.c +++ b/src/lib/elementary/efl_ui_layout_factory.c @@ -73,30 +73,32 @@ _efl_ui_layout_factory_bind(Eo *obj EINA_UNUSED, void *data, const Eina_Value va { Efl_Ui_Layout_Factory_Data *pd = data; Efl_Gfx_Entity *layout; + int len, i; - eina_value_pget(&value, &layout); + EINA_VALUE_ARRAY_FOREACH(&value, len, i, layout) + { + efl_ui_layout_theme_set(layout, pd->klass, pd->group, pd->style); - efl_ui_layout_theme_set(layout, pd->klass, pd->group, pd->style); + eina_hash_foreach(pd->bind.properties, _property_bind, layout); + eina_hash_foreach(pd->bind.factories, _factory_bind, layout); - eina_hash_foreach(pd->bind.properties, _property_bind, layout); - eina_hash_foreach(pd->bind.factories, _factory_bind, layout); - - evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, 0); - evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, 0); + evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL); + } return value; } EOLIAN static Eina_Future * _efl_ui_layout_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Layout_Factory_Data *pd, - Efl_Model *model, Efl_Gfx_Entity *parent) + Eina_Iterator *models, Efl_Gfx_Entity *parent) { Eina_Future *f; - f = efl_ui_factory_create(efl_super(obj, EFL_UI_LAYOUT_FACTORY_CLASS), model, parent); + f = efl_ui_factory_create(efl_super(obj, EFL_UI_LAYOUT_FACTORY_CLASS), models, parent); return efl_future_then(obj, f, - .success_type = EINA_VALUE_TYPE_OBJECT, + .success_type = EINA_VALUE_TYPE_ARRAY, .success = _efl_ui_layout_factory_bind, .data = pd); } @@ -148,8 +150,8 @@ _efl_ui_layout_factory_efl_ui_property_bind_property_bind(Eo *obj EINA_UNUSED, E } EOLIAN static void -_efl_ui_layout_factory_theme_config(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Factory_Data *pd - , const char *klass, const char *group, const char *style) +_efl_ui_layout_factory_theme_config(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Factory_Data *pd, + const char *klass, const char *group, const char *style) { eina_stringshare_replace(&pd->klass, klass); eina_stringshare_replace(&pd->group, group); diff --git a/src/lib/elementary/efl_ui_list_view.c b/src/lib/elementary/efl_ui_list_view.c index 78812853ae..4f8495fd9a 100644 --- a/src/lib/elementary/efl_ui_list_view.c +++ b/src/lib/elementary/efl_ui_list_view.c @@ -904,7 +904,8 @@ _content_created(Eo *obj, void *data, const Eina_Value value) Efl_Ui_List_View_Layout_Item *item = tracking->item; Efl_Ui_List_View_Item_Event evt; - eina_value_pget(&value, &item->layout); + if (eina_value_array_count(&value) != 1) return eina_value_error_init(EINVAL); + eina_value_array_get(&value, 0, &item->layout); evas_object_smart_member_add(item->layout, tracking->pd->pan_obj); evas_object_event_callback_add(item->layout, EVAS_CALLBACK_MOUSE_UP, _on_item_mouse_up, item); @@ -942,6 +943,7 @@ EOLIAN static Efl_Ui_List_View_Layout_Item * _efl_ui_list_view_efl_ui_list_view_model_realize(Eo *obj, Efl_Ui_List_View_Data *pd, Efl_Ui_List_View_Layout_Item *item) { Efl_Ui_List_View_Layout_Item_Tracking *tracking; + Efl_Model *childrens[1]; EINA_SAFETY_ON_NULL_RETURN_VAL(item->children, item); if (!item->children) return item; @@ -953,11 +955,14 @@ _efl_ui_list_view_efl_ui_list_view_model_realize(Eo *obj, Efl_Ui_List_View_Data tracking->item = item; tracking->pd = pd; + childrens[0] = item->children; - item->layout_request = efl_ui_view_factory_create_with_event(pd->factory, item->children, obj); + item->layout_request = efl_ui_view_factory_create_with_event(pd->factory, + EINA_C_ARRAY_ITERATOR_NEW(childrens), + obj); item->layout_request = efl_future_then(obj, item->layout_request, .success = _content_created, - .success_type = EINA_VALUE_TYPE_OBJECT, + .success_type = EINA_VALUE_TYPE_ARRAY, .data = tracking, .free = _clean_request); diff --git a/src/lib/elementary/efl_ui_widget_factory.c b/src/lib/elementary/efl_ui_widget_factory.c index 371b81984e..1ae33b2cf2 100644 --- a/src/lib/elementary/efl_ui_widget_factory.c +++ b/src/lib/elementary/efl_ui_widget_factory.c @@ -40,7 +40,6 @@ struct _Efl_Ui_Widget_Factory_Request { Efl_Ui_Widget_Factory_Data *pd; Eo *parent; - Efl_Model *model; }; static void @@ -67,8 +66,38 @@ _efl_ui_widget_factory_item_class_get(const Eo *obj EINA_UNUSED, return pd->klass; } +static Efl_Ui_Widget * +_efl_ui_widget_create(const Efl_Class *klass, Eo *parent, + const char *style, Efl_Model *model, + const Eina_Hash *parts) +{ + Efl_Ui_Bind_Part_Data *bpd; + Eina_Iterator *it; + Efl_Ui_Widget *w; + + w = efl_add(klass, parent, + style ? efl_ui_widget_style_set(efl_added, style) : (void) 0, + efl_ui_view_model_set(efl_added, model)); + if (!parts) return w; + + it = eina_hash_iterator_data_new(parts); + EINA_ITERATOR_FOREACH(it, bpd) + { + Efl_Ui_Property_Bind_Data *bppd; + Eina_List *l; + + EINA_LIST_FOREACH(bpd->properties, l, bppd) + efl_ui_property_bind(efl_part(w, bpd->part), + bppd->part_property, + bppd->model_property); + } + eina_iterator_free(it); + + return w; +} + static Eina_Value -_efl_ui_widget_factory_create_then(Eo *obj EINA_UNUSED, void *data, const Eina_Value v) +_efl_ui_widget_factory_create_then(Eo *model, void *data, const Eina_Value v) { Efl_Ui_Widget_Factory_Request *r = data; Efl_Ui_Widget *w; @@ -77,48 +106,34 @@ _efl_ui_widget_factory_create_then(Eo *obj EINA_UNUSED, void *data, const Eina_V if (!eina_value_string_get(&v, &string)) return eina_value_error_init(EFL_MODEL_ERROR_NOT_SUPPORTED); - w = efl_add(r->pd->klass, r->parent, - efl_ui_widget_style_set(efl_added, string), - efl_ui_view_model_set(efl_added, r->model)); - - if (r->pd->parts) - { - Efl_Ui_Bind_Part_Data *bpd; - Eina_Iterator *it; - - it = eina_hash_iterator_data_new(r->pd->parts); - - EINA_ITERATOR_FOREACH(it, bpd) - { - Efl_Ui_Property_Bind_Data *bppd; - Eina_List *l; - - EINA_LIST_FOREACH(bpd->properties, l, bppd) - efl_ui_property_bind(efl_part(w, bpd->part), - bppd->part_property, - bppd->model_property); - } - eina_iterator_free(it); - } - + w = _efl_ui_widget_create(r->pd->klass, r->parent, string, model, r->pd->parts); + if (!w) return eina_value_error_init(ENOMEM); return eina_value_object_init(w); } +static void +_efl_ui_widget_factory_single_cleanup(Eo *model, void *data EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED) +{ + efl_unref(model); +} + static void _efl_ui_widget_factory_create_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED) { Efl_Ui_Widget_Factory_Request *r = data; - efl_unref(r->model); 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, - Efl_Model *model, Efl_Gfx_Entity *parent) + Eina_Iterator *models, Efl_Gfx_Entity *parent) { Efl_Ui_Widget_Factory_Request *r; + Eina_Future **f; + Efl_Model *model; + int count = 0; if (!pd->klass) return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); @@ -126,10 +141,20 @@ _efl_ui_widget_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Widget_Factory_Data if (!pd->style) { Efl_Ui_Widget *w; + Eina_Value r; - w = efl_add(pd->klass, parent, - efl_ui_view_model_set(efl_added, model)); - return efl_loop_future_resolved(obj, eina_value_object_init(w)); + eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 4); + + EINA_ITERATOR_FOREACH(models, model) + { + w = _efl_ui_widget_create(pd->klass, parent, NULL, model, pd->parts); + + if (!w) return efl_loop_future_rejected(obj, ENOMEM); + eina_value_array_append(&r, w); + } + eina_iterator_free(models); + + return efl_loop_future_resolved(obj, r); } r = calloc(1, sizeof (Efl_Ui_Widget_Factory_Request)); @@ -137,10 +162,24 @@ _efl_ui_widget_factory_efl_ui_factory_create(Eo *obj, Efl_Ui_Widget_Factory_Data 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_widget_factory_create_then, + f = calloc(count + 1, sizeof (Eina_Future *)); + if (!f) return efl_loop_future_rejected(obj, ENOMEM); + + EINA_ITERATOR_FOREACH(models, model) + { + f[count++] = efl_future_then(efl_ref(model), efl_model_property_ready_get(model, pd->style), + .success = _efl_ui_widget_factory_create_then, + .free = _efl_ui_widget_factory_single_cleanup); + + f = realloc(f, (count + 1) * sizeof (Eina_Future *)); + if (!f) return efl_loop_future_rejected(obj, ENOMEM); + } + eina_iterator_free(models); + + f[count] = EINA_FUTURE_SENTINEL; + + return efl_future_then(obj, eina_future_all_array(f), .data = r, .free = _efl_ui_widget_factory_create_cleanup); }