From ae26833fbd550ebb92f7305db118db50935c0d50 Mon Sep 17 00:00:00 2001 From: Larry Jr Date: Fri, 1 Jul 2016 20:45:30 -0300 Subject: [PATCH] elementary: add model connect in elm_layout add 2 new interfaces efl_ui_view and efl_ui_model_connect now elm_layout can update elements from model connectected efl_ui_view_model_set(layout, model) efl_ui_model_connect(layout, "part_name", "property") --- src/Makefile_Efl.am | 2 + src/lib/efl/Efl.h | 3 + src/lib/efl/interfaces/efl_interfaces_main.c | 2 + .../efl/interfaces/efl_ui_model_connect.eo | 11 ++ src/lib/efl/interfaces/efl_ui_view.eo | 12 ++ src/lib/elementary/elm_layout.c | 185 ++++++++++++++++++ src/lib/elementary/elm_layout.eo | 5 +- src/lib/elementary/elm_widget_layout.h | 3 + 8 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/lib/efl/interfaces/efl_ui_model_connect.eo create mode 100644 src/lib/efl/interfaces/efl_ui_view.eo diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am index ac5edda4e4..375adc6af6 100644 --- a/src/Makefile_Efl.am +++ b/src/Makefile_Efl.am @@ -42,6 +42,8 @@ efl_eolian_files = \ lib/efl/interfaces/efl_vpath_file_core.eo \ lib/efl/interfaces/efl_ui_spin.eo \ lib/efl/interfaces/efl_ui_progress.eo \ + lib/efl/interfaces/efl_ui_view.eo \ + lib/efl/interfaces/efl_ui_model_connect.eo \ lib/efl/interfaces/efl_event.eo \ lib/efl/interfaces/efl_input_interface.eo \ lib/efl/interfaces/efl_input_state.eo \ diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h index 3a00bb5b28..0105cdd329 100644 --- a/src/lib/efl/Efl.h +++ b/src/lib/efl/Efl.h @@ -114,6 +114,9 @@ EAPI extern const Eo_Event_Description _EFL_GFX_PATH_CHANGED; #include "interfaces/efl_canvas.eo.h" +#include "interfaces/efl_ui_view.eo.h" +#include "interfaces/efl_ui_model_connect.eo.h" + /* Packing & containers */ #include "interfaces/efl_container.eo.h" #include "interfaces/efl_pack.eo.h" diff --git a/src/lib/efl/interfaces/efl_interfaces_main.c b/src/lib/efl/interfaces/efl_interfaces_main.c index d497be9107..52cebf33ac 100644 --- a/src/lib/efl/interfaces/efl_interfaces_main.c +++ b/src/lib/efl/interfaces/efl_interfaces_main.c @@ -53,6 +53,8 @@ EAPI const Eo_Event_Description _EFL_GFX_PATH_CHANGED = #include "interfaces/efl_flipable.eo.c" #include "interfaces/efl_ui_spin.eo.c" #include "interfaces/efl_ui_progress.eo.c" +#include "interfaces/efl_ui_view.eo.c" +#include "interfaces/efl_ui_model_connect.eo.c" #include "interfaces/efl_event.eo.c" #include "interfaces/efl_input_state.eo.c" diff --git a/src/lib/efl/interfaces/efl_ui_model_connect.eo b/src/lib/efl/interfaces/efl_ui_model_connect.eo new file mode 100644 index 0000000000..e855e1d978 --- /dev/null +++ b/src/lib/efl/interfaces/efl_ui_model_connect.eo @@ -0,0 +1,11 @@ +interface Efl.Ui.Model.Connect +{ + methods { + connect { + params { + name: string; + properties: string; + } + } + } +} diff --git a/src/lib/efl/interfaces/efl_ui_view.eo b/src/lib/efl/interfaces/efl_ui_view.eo new file mode 100644 index 0000000000..e5957ee445 --- /dev/null +++ b/src/lib/efl/interfaces/efl_ui_view.eo @@ -0,0 +1,12 @@ +interface Efl.Ui.View () +{ + methods { + @property model { + [[Model that is/will be ]] + get {} set {} + values { + model: Efl.Model; + } + } + } +} diff --git a/src/lib/elementary/elm_layout.c b/src/lib/elementary/elm_layout.c index 97e7bc3520..e0f5d2dcaf 100644 --- a/src/lib/elementary/elm_layout.c +++ b/src/lib/elementary/elm_layout.c @@ -19,6 +19,7 @@ #define MY_CLASS_NAME_LEGACY "elm_layout" Eo *_elm_layout_pack_proxy_get(Elm_Layout *obj, Evas_Object *pack, const char *part); +static void _efl_model_properties_changed_cb(void *, const Eo_Event *); static const char SIG_THEME_CHANGED[] = "theme,changed"; const char SIG_LAYOUT_FOCUSED[] = "focused"; @@ -107,6 +108,13 @@ struct _Elm_Layout_Sub_Object_Cursor Eina_Bool engine_only : 1; }; +typedef struct _Elm_Layout_Sub_Property_Promise Elm_Layout_Sub_Property_Promise; +struct _Elm_Layout_Sub_Property_Promise +{ + Elm_Layout_Smart_Data *pd; + Eina_Stringshare *name; +}; + static void _on_sub_object_size_hint_change(void *data, Evas *e EINA_UNUSED, @@ -818,6 +826,15 @@ _elm_layout_efl_canvas_group_group_del(Eo *obj, Elm_Layout_Smart_Data *sd) free(esd); } + if(sd->model) + { + eo_event_callback_del(sd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, sd); + eo_unref(sd->model); + sd->model = NULL; + } + eina_hash_free(sd->prop_connect); + sd->prop_connect = NULL; + eina_stringshare_del(sd->klass); eina_stringshare_del(sd->group); @@ -1332,6 +1349,30 @@ _elm_layout_text_set(Eo *obj, Elm_Layout_Smart_Data *sd, const char *part, const sub_d->obj = _elm_access_edje_object_part_object_register (obj, elm_layout_edje_get(obj), part); + + if (sd->model && !sd->view_updated) + { + Eina_Hash_Tuple *tuple; + Eina_Iterator *it = eina_hash_iterator_tuple_new(sd->prop_connect); + + while (eina_iterator_next(it, (void **)&tuple)) + { + if (tuple->data == sub_d->part) + { + Eina_Value v; + eina_value_setup(&v, EINA_VALUE_TYPE_STRING); + eina_value_set(&v, text); + efl_model_property_set(sd->model, tuple->key, &v, NULL); + eina_value_flush(&v); + break; + } + } + + eina_iterator_free(it); + } + + sd->view_updated = EINA_FALSE; + return EINA_TRUE; } @@ -1909,6 +1950,150 @@ _elm_layout_eo_base_dbg_info_get(Eo *eo_obj, Elm_Layout_Smart_Data *_pd EINA_UNU } } +static void +_prop_promise_error_cb(void* data, Eina_Error err EINA_UNUSED) +{ + Elm_Layout_Sub_Property_Promise *sub_pp = data; + + eina_stringshare_del(sub_pp->name); + free(sub_pp); +} + +static void +_prop_promise_then_cb(void* data, void* v) +{ + Elm_Layout_Sub_Property_Promise *sub_pp = data; + Elm_Layout_Smart_Data *pd = sub_pp->pd; + Eina_Value *value = v; + char *text; + + const Eina_Value_Type *vtype = eina_value_type_get(value); + + pd->view_updated = EINA_TRUE; + if (vtype == EINA_VALUE_TYPE_STRING || vtype == EINA_VALUE_TYPE_STRINGSHARE) + { + eina_value_get(value, &text); + elm_layout_text_set(pd->obj, sub_pp->name, text); + } + else + { + text = eina_value_to_string(value); + elm_layout_text_set(pd->obj, sub_pp->name, text); + free(text); + } + + eina_stringshare_del(sub_pp->name); + free(sub_pp); +} + +static void +_efl_model_properties_changed_cb(void *data, const Eo_Event *event) +{ + Elm_Layout_Smart_Data *pd = data; + Efl_Model_Property_Event *evt = event->info; + Elm_Layout_Sub_Property_Promise *sub_pp; + Eina_Stringshare *name; + Eina_Array_Iterator it; + Eina_Promise *promise; + const char *prop; + unsigned int i; + + if (!evt->changed_properties) + return; + + EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it) + { + name = eina_hash_find(pd->prop_connect, prop); + if (name) + { + sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Promise); + sub_pp->pd = pd; + sub_pp->name = name; + eina_stringshare_ref(sub_pp->name); + promise = efl_model_property_get(pd->model, prop); + eina_promise_then(promise, &_prop_promise_then_cb, + &_prop_promise_error_cb, sub_pp); + } + } +} + +static Eina_Bool +_elm_layout_view_update_fn(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata) +{ + Elm_Layout_Smart_Data *pd = fdata; + Eina_Stringshare *prop = key; + Eina_Stringshare *name = data; + + if (name) + { + Elm_Layout_Sub_Property_Promise *sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Promise); + Eina_Promise *promise = efl_model_property_get(pd->model, prop); + sub_pp->pd = pd; + sub_pp->name = eina_stringshare_ref(name); + eina_promise_then(promise, &_prop_promise_then_cb, + &_prop_promise_error_cb, sub_pp); + } + return EINA_TRUE; +} + +EOLIAN static void +_elm_layout_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Elm_Layout_Smart_Data *pd, Efl_Model *model) +{ + if (pd->model) + { + eo_event_callback_del(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, pd); + eo_unref(pd->model); + pd->model = NULL; + } + + if (model) + { + pd->model = model; + eo_ref(pd->model); + eo_event_callback_add(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, pd); + } + + if (pd->prop_connect) eina_hash_foreach(pd->prop_connect, _elm_layout_view_update_fn, pd); +} + +EOLIAN static Efl_Model * +_elm_layout_efl_ui_view_model_get(Eo *obj EINA_UNUSED, Elm_Layout_Smart_Data *pd) +{ + return pd->model; +} + +EOLIAN static void +_elm_layout_efl_ui_model_connect_connect(Eo *obj EINA_UNUSED, Elm_Layout_Smart_Data *pd, const char *name, const char *property) +{ + EINA_SAFETY_ON_NULL_RETURN(name); + Eina_Stringshare *ss_name, *ss_prop; + + if (!_elm_layout_part_aliasing_eval(obj, pd, &name, EINA_TRUE)) + return; + + ss_name = eina_stringshare_add(name); + ss_prop = eina_stringshare_add(property); + if (!pd->prop_connect) + { + pd->prop_connect = eina_hash_stringshared_new(EINA_FREE_CB(eina_stringshare_del)); + } + + eina_stringshare_del(eina_hash_set(pd->prop_connect, ss_prop, ss_name)); + + if (pd->model) + { + Eina_Promise *promise; + Elm_Layout_Sub_Property_Promise *sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Promise); + + sub_pp->pd = pd; + sub_pp->name = eina_stringshare_ref(ss_name); + + promise = efl_model_property_get(pd->model, ss_prop); + eina_promise_then(promise, &_prop_promise_then_cb, + &_prop_promise_error_cb, sub_pp); + } +} + EAPI Evas_Object * elm_layout_add(Evas_Object *parent) { diff --git a/src/lib/elementary/elm_layout.eo b/src/lib/elementary/elm_layout.eo index 40c6401953..d68323f318 100644 --- a/src/lib/elementary/elm_layout.eo +++ b/src/lib/elementary/elm_layout.eo @@ -17,7 +17,7 @@ struct Elm.Layout_Part_Alias_Description real_part: string; [[Target part name for the alias set on Elm.Layout_Part_Proxies_Description::real_part. An example of usage would be "default" on that field, with "elm.content.swallow" on this one]] } -class Elm.Layout (Elm.Widget, Efl.Part, Efl.Container, Efl.File, Edje.Object) +class Elm.Layout (Elm.Widget, Efl.Part, Efl.Container, Efl.File, Edje.Object, Efl.Ui.View, Efl.Ui.Model.Connect) { legacy_prefix: elm_layout; eo_prefix: elm_obj_layout; @@ -256,6 +256,9 @@ class Elm.Layout (Elm.Widget, Efl.Part, Efl.Container, Efl.File, Edje.Object) Edje.Object.thaw; Edje.Object.signal_callback_add; Edje.Object.signal_callback_del; + Efl.Ui.View.model.set; + Efl.Ui.View.model.get; + Efl.Ui.Model.Connect.connect; } events { theme,changed; diff --git a/src/lib/elementary/elm_widget_layout.h b/src/lib/elementary/elm_widget_layout.h index ded10f3d67..eb7fe79e52 100644 --- a/src/lib/elementary/elm_widget_layout.h +++ b/src/lib/elementary/elm_widget_layout.h @@ -53,6 +53,8 @@ typedef struct _Elm_Layout_Smart_Data Eina_List *subs; /**< List of Elm_Layout_Sub_Object_Data structs, to hold the actual sub objects such as text, content and the children of box and table. */ Eina_List *edje_signals; /**< The list of edje signal callbacks. */ Eina_List *parts_cursors; /**< The list of cursor names of layout parts. This is a list of Elm_Layout_Sub_Object_Cursor struct. */ + Eina_Hash *prop_connect; /**< The list of properties connected to layout parts. */ + Efl_Model *model; /**< The model */ const char *klass; /**< 1st identifier of an edje object group which is used in theme_set. klass and group are used together. */ const char *group; /**< 2nd identifier of an edje object group which is used in theme_set. klass and group are used together. */ int frozen; /**< Layout freeze counter */ @@ -63,6 +65,7 @@ typedef struct _Elm_Layout_Smart_Data Eina_Bool can_access : 1; /**< This is true when all text(including textblock) parts can be accessible by accessibility. */ Eina_Bool destructed_is : 1; /**< This flag indicates if Elm_Layout destructor was called. This is needed to avoid unnecessary calculation of subobject deletion during layout object's deletion. */ Eina_Bool file_set : 1; /**< This flag indicates if Elm_Layout source is set from a file*/ + Eina_Bool view_updated : 1; /**< This flag indicates to Elm_Layout don't update model in text_set */ } Elm_Layout_Smart_Data; /**