diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index 9e9ebc8ea2..f8fca13520 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -133,6 +133,7 @@ elm_public_eolian_files = \ lib/elementary/efl_ui_widget_focus_manager.eo \ lib/elementary/efl_ui_text_part.eo \ lib/elementary/efl_ui_caching_factory.eo \ + lib/elementary/efl_ui_widget_factory.eo \ $(NULL) # More public files -- FIXME @@ -884,6 +885,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_tab_page.c \ lib/elementary/efl_ui_widget_focus_manager.c \ lib/elementary/efl_ui_caching_factory.c \ + lib/elementary/efl_ui_widget_factory.c \ $(NULL) diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h index c1387290e2..34db59a475 100644 --- a/src/lib/elementary/Efl_Ui.h +++ b/src/lib/elementary/Efl_Ui.h @@ -210,6 +210,7 @@ EAPI void efl_ui_focus_relation_free(Efl_Ui_Focus_Relations *rel); # include # include "efl_ui_caching_factory.eo.h" +# include "efl_ui_widget_factory.eo.h" /* FIXME: Multibuttonentry must not use elm_widget_item */ diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index 3854a3e2a9..5bb8374e3a 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -346,6 +346,7 @@ EAPI void efl_ui_focus_relation_free(Efl_Ui_Focus_Relations *rel); # include # include # include +# include # include # include # include diff --git a/src/lib/elementary/efl_ui_widget_factory.c b/src/lib/elementary/efl_ui_widget_factory.c new file mode 100644 index 0000000000..b83a0a79aa --- /dev/null +++ b/src/lib/elementary/efl_ui_widget_factory.c @@ -0,0 +1,131 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#define EFL_UI_WIDGET_PROTECTED + +#include +#include "elm_priv.h" + +typedef struct _Efl_Ui_Widget_Factory_Data Efl_Ui_Widget_Factory_Data; +typedef struct _Efl_Ui_Widget_Factory_Request Efl_Ui_Widget_Factory_Request; + +struct _Efl_Ui_Widget_Factory_Data +{ + const Efl_Class *klass; + + Eina_Stringshare *style; +}; + +struct _Efl_Ui_Widget_Factory_Request +{ + Efl_Ui_Widget_Factory_Data *pd; + Eo *parent; + Efl_Model *model; +}; + +static void +_efl_ui_widget_factory_item_class_set(Eo *obj, Efl_Ui_Widget_Factory_Data *pd, + const Efl_Class *klass) +{ + 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_UI_WIDGET_CLASS), + efl_class_name_get(EFL_UI_VIEW_INTERFACE)); + return ; + } + pd->klass = klass; +} + +static const Efl_Class * +_efl_ui_widget_factory_item_class_get(const Eo *obj EINA_UNUSED, + Efl_Ui_Widget_Factory_Data *pd) +{ + return pd->klass; +} + +static Eina_Value +_efl_ui_widget_factory_create_then(Eo *obj EINA_UNUSED, void *data, const Eina_Value v) +{ + Efl_Ui_Widget_Factory_Request *r = data; + Efl_Ui_Widget *w; + const char *string = NULL; + + 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)); + + return eina_value_object_init(w); +} + +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) +{ + Efl_Ui_Widget_Factory_Request *r; + + if (!pd->klass) + return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); + + if (!pd->style) + { + Efl_Ui_Widget *w; + + 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)); + } + + r = calloc(1, sizeof (Efl_Ui_Widget_Factory_Request)); + if (!r) return efl_loop_future_rejected(obj, ENOMEM); + + 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, + .data = r, + .free = _efl_ui_widget_factory_create_cleanup); +} + +static void +_efl_ui_widget_factory_efl_ui_factory_release(Eo *obj EINA_UNUSED, + Efl_Ui_Widget_Factory_Data *pd EINA_UNUSED, + Efl_Gfx_Entity *ui_view) +{ + // We do not cache or track this item, just get rid of them asap + efl_del(ui_view); +} + +static void +_efl_ui_widget_factory_efl_ui_model_connect_connect(Eo *obj, Efl_Ui_Widget_Factory_Data *pd, + const char *name, const char *property) +{ + if (!strcmp(name, "style")) + { + eina_stringshare_replace(&pd->style, property); + return ; + } + + efl_ui_model_connect(efl_super(obj, EFL_UI_WIDGET_FACTORY_CLASS), name, property); +} + +#include "efl_ui_widget_factory.eo.c" diff --git a/src/lib/elementary/efl_ui_widget_factory.eo b/src/lib/elementary/efl_ui_widget_factory.eo new file mode 100644 index 0000000000..3652010735 --- /dev/null +++ b/src/lib/elementary/efl_ui_widget_factory.eo @@ -0,0 +1,28 @@ +class Efl.Ui.Widget_Factory extends Efl.Loop_Consumer implements Efl.Ui.Factory +{ + [[Efl Ui Factory that provides @Efl.Ui.Widget. + + This factory is designed to build @Efl.Ui.Widget and optionally set their + @Efl.Ui.Widget.style if it was connected with @Efl.Ui.Model.Connect.connect "$style". + + ]] + 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.]] + } + } + } + + implements { + Efl.Ui.Factory.create; + Efl.Ui.Factory.release; + Efl.Ui.Model.Connect.connect; + } + constructors { + .item_class; + } +} \ No newline at end of file diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build index 0c7c9cb166..fa5b42b4a1 100644 --- a/src/lib/elementary/meson.build +++ b/src/lib/elementary/meson.build @@ -278,6 +278,7 @@ pub_eo_files = [ 'elm_widget_item.eo', 'efl_ui_text_part.eo', 'efl_ui_caching_factory.eo', + 'efl_ui_widget_factory.eo', ] foreach eo_file : pub_eo_files @@ -903,7 +904,8 @@ elementary_src = [ 'efl_ui_tab_bar.c', 'efl_ui_tab_page.c', 'efl_ui_widget_focus_manager.c', - 'efl_ui_caching_factory.c' + 'efl_ui_caching_factory.c', + 'efl_ui_widget_factory.c' ] elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl]