summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2019-02-11 18:28:22 -0800
committerCedric BAIL <cedric.bail@free.fr>2019-03-08 14:31:00 -0800
commitd1d30f442bb376817535838a8747764941a2329c (patch)
tree0f04ba697e14319a39a9f64bccd1d854f6bfa66c
parentcbd8c45afeb458560e70ed5c3bc415ac79c66db4 (diff)
downloadefl-d1d30f442bb376817535838a8747764941a2329c.tar.gz
elementary: implemente property_bind support on all widget using property reflection.
This means that all property that are registered in the reflection table of any Eo class will be available for binding with a model. This will increase the amount of useful binding quickly. Reviewed-by: Vitor Sousa da Silva <vitorsousa@expertisesolutions.com.br> Differential Revision: https://phab.enlightenment.org/D7941
-rw-r--r--src/lib/elementary/efl_ui_widget.c184
-rw-r--r--src/lib/elementary/efl_ui_widget.eo6
-rw-r--r--src/lib/elementary/elm_widget.h5
3 files changed, 194 insertions, 1 deletions
diff --git a/src/lib/elementary/efl_ui_widget.c b/src/lib/elementary/efl_ui_widget.c
index e39bea0065..2c49d0fecf 100644
--- a/src/lib/elementary/efl_ui_widget.c
+++ b/src/lib/elementary/efl_ui_widget.c
@@ -5940,6 +5940,190 @@ _efl_ui_widget_part_bg_efl_gfx_image_scale_type_get(const Eo *obj, void *pd EINA
return efl_gfx_image_scale_type_get(bg_obj);
}
+typedef struct _Efl_Ui_Property_Bound Efl_Ui_Property_Bound;
+struct _Efl_Ui_Property_Bound
+{
+ Eina_Stringshare *key; // Local object property
+ Eina_Stringshare *property; // Model property
+ Eina_Future *f;
+};
+
+static void
+_efl_ui_property_bind_free(void *data)
+{
+ Efl_Ui_Property_Bound *prop = data;
+
+ eina_stringshare_del(prop->key);
+ eina_stringshare_del(prop->property);
+ free(prop);
+}
+
+static void
+_efl_ui_property_bind_clean(Eo *obj EINA_UNUSED,
+ void *data,
+ const Eina_Future *f EINA_UNUSED)
+{
+ Efl_Ui_Property_Bound *prop = data;
+
+ prop->f = NULL;
+}
+
+static void
+_efl_ui_property_bind_get(Efl_Ui_Widget_Data *pd, Efl_Ui_Property_Bound *prop)
+{
+ Eina_Value *value = efl_model_property_get(pd->properties.model, prop->property);
+ Eina_Future *f;
+ Eina_Error err;
+
+ err = efl_property_reflection_set(pd->obj, prop->key, eina_value_reference_copy(value));
+ eina_value_free(value);
+
+ if (!err) return ;
+
+ // Report back the error to the model
+ if (prop->f) eina_future_cancel(prop->f);
+ f = efl_model_property_set(pd->properties.model, prop->property,
+ eina_value_error_new(err));
+ prop->f = efl_future_then(pd->obj, f, .free = _efl_ui_property_bind_clean, .data = prop);
+}
+
+static void
+_efl_ui_property_bind_set(Efl_Ui_Widget_Data *pd, Efl_Ui_Property_Bound *prop)
+{
+ Eina_Value value = efl_property_reflection_get(pd->obj, prop->key);
+ Eina_Future *f;
+
+ if (prop->f) eina_future_cancel(prop->f);
+ f = efl_model_property_set(pd->properties.model, prop->property, eina_value_dup(&value));
+ prop->f = efl_future_then(pd->obj, f, .free = _efl_ui_property_bind_clean, .data = prop);
+ eina_value_flush(&value);
+}
+
+static void
+_efl_ui_model_property_bind_changed(void *data, const Efl_Event *event)
+{
+ Efl_Model_Property_Event *evt = event->info;
+ Efl_Ui_Widget_Data *pd = data;
+ Eina_Array_Iterator it;
+ const char *prop;
+ unsigned int i;
+
+ EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
+ {
+ Eina_Stringshare *sp = eina_stringshare_add(prop);
+ Efl_Ui_Property_Bound *lookup;
+
+ lookup = eina_hash_find(pd->properties.model_lookup, sp);
+ if (lookup) _efl_ui_property_bind_get(pd, lookup);
+ eina_stringshare_del(sp);
+ }
+}
+
+static void
+_efl_ui_view_property_bind_changed(void *data, const Efl_Event *event)
+{
+ Efl_Ui_Property_Event *evt = event->info;
+ Efl_Ui_Widget_Data *pd = data;
+ Eina_Array_Iterator it;
+ Eina_Stringshare *prop;
+ unsigned int i;
+
+ EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
+ {
+ Efl_Ui_Property_Bound *lookup;
+
+ lookup = eina_hash_find(pd->properties.view_lookup, prop);
+ if (lookup) _efl_ui_property_bind_set(pd, lookup);
+ }
+}
+
+static Eina_Error
+_efl_ui_widget_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Widget_Data *pd,
+ const char *key, const char *property)
+{
+ Efl_Ui_Property_Bound *prop;
+
+ // Check if the property is available from the reflection table of the object.
+ if (!efl_property_reflection_exist(obj, key)) return EFL_PROPERTY_ERROR_INVALID_KEY;
+
+ if (!pd->properties.model_lookup)
+ {
+ pd->properties.model_lookup = eina_hash_stringshared_new(_efl_ui_property_bind_free);
+ pd->properties.view_lookup = eina_hash_stringshared_new(NULL);
+ if (pd->properties.model)
+ {
+ efl_event_callback_add(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
+ _efl_ui_model_property_bind_changed, pd);
+ efl_event_callback_add(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
+ _efl_ui_view_property_bind_changed, pd);
+ }
+ }
+
+ prop = calloc(1, sizeof (Efl_Ui_Property_Bound));
+ if (!prop) return ENOMEM;
+ prop->key = eina_stringshare_add(key);
+ prop->property = eina_stringshare_add(property);
+
+ eina_hash_direct_add(pd->properties.model_lookup, prop->property, prop);
+ eina_hash_direct_add(pd->properties.view_lookup, prop->key, prop);
+
+ _efl_ui_property_bind_get(pd, prop);
+
+
+ return 0;
+}
+
+static void
+_efl_ui_widget_efl_ui_view_model_set(Eo *obj,
+ Efl_Ui_Widget_Data *pd,
+ Efl_Model *model)
+{
+ if (pd->properties.model)
+ {
+ // Remove any existing handler that might exist for any reason
+ efl_event_callback_del(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
+ _efl_ui_model_property_bind_changed, pd);
+ efl_event_callback_del(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
+ _efl_ui_view_property_bind_changed, pd);
+ }
+
+ efl_replace(&pd->properties.model, model);
+
+ if (pd->properties.model && pd->properties.model_lookup)
+ {
+ // Set the properties handler just in case
+ efl_event_callback_add(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
+ _efl_ui_model_property_bind_changed, pd);
+ efl_event_callback_add(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
+ _efl_ui_view_property_bind_changed, pd);
+ }
+}
+
+static Efl_Model *
+_efl_ui_widget_efl_ui_view_model_get(const Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *pd)
+{
+ return pd->properties.model;
+}
+
+static void
+_efl_ui_widget_efl_object_invalidate(Eo *obj, Efl_Ui_Widget_Data *pd)
+{
+ efl_invalidate(efl_super(obj, EFL_UI_WIDGET_CLASS));
+
+ if (pd->properties.model)
+ {
+ efl_event_callback_del(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
+ _efl_ui_model_property_bind_changed, pd);
+ efl_event_callback_del(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
+ _efl_ui_view_property_bind_changed, pd);
+ efl_replace(&pd->properties.model, NULL);
+ }
+ if (pd->properties.view_lookup) eina_hash_free(pd->properties.view_lookup);
+ pd->properties.view_lookup = NULL;
+ if (pd->properties.model_lookup) eina_hash_free(pd->properties.model_lookup);
+ pd->properties.model_lookup = NULL;
+}
+
#include "efl_ui_widget_part_bg.eo.c"
/* Efl.Part Bg end */
diff --git a/src/lib/elementary/efl_ui_widget.eo b/src/lib/elementary/efl_ui_widget.eo
index edbdaa5331..21bbb3ebd4 100644
--- a/src/lib/elementary/efl_ui_widget.eo
+++ b/src/lib/elementary/efl_ui_widget.eo
@@ -16,7 +16,8 @@ struct Efl.Ui.Widget_Focus_State {
abstract @beta Efl.Ui.Widget extends Efl.Canvas.Group implements Efl.Access.Object,
Efl.Access.Component, Efl.Part, Efl.Ui.Focus.Object,
Efl.Ui.L10n,
- Efl.Ui.Selection, Efl.Ui.Dnd
+ Efl.Ui.Selection, Efl.Ui.Dnd,
+ Efl.Ui.Property_Bind, Efl.Ui.View
{
[[Efl UI widget abstract class]]
//eo_prefix: efl_ui_widget;
@@ -388,6 +389,7 @@ abstract @beta Efl.Ui.Widget extends Efl.Canvas.Group implements Efl.Access.Obje
class.constructor;
Efl.Object.constructor;
Efl.Object.finalize;
+ Efl.Object.invalidate;
Efl.Object.destructor;
Efl.Object.provider_find;
Efl.Object.debug_name_override;
@@ -415,6 +417,8 @@ abstract @beta Efl.Ui.Widget extends Efl.Canvas.Group implements Efl.Access.Obje
Efl.Ui.Focus.Object.on_focus_update;
Efl.Ui.L10n.translation_update; [[This implements the calls to $gettext() and $text_set().]]
Efl.Part.part_get; [[Returns @Efl.Ui.Widget_Part.]]
+ Efl.Ui.View.model { get; set; }
+ Efl.Ui.Property_Bind.property_bind;
}
constructors {
.style @optional;
diff --git a/src/lib/elementary/elm_widget.h b/src/lib/elementary/elm_widget.h
index 0b8a5df5cb..f6eb21cec7 100644
--- a/src/lib/elementary/elm_widget.h
+++ b/src/lib/elementary/elm_widget.h
@@ -383,6 +383,11 @@ typedef struct _Elm_Widget_Smart_Data
Evas_Object *prev, *next, *up, *down, *right, *left;
Elm_Object_Item *item_prev, *item_next, *item_up, *item_down, *item_right, *item_left;
} legacy_focus;
+ struct {
+ Efl_Model *model;
+ Eina_Hash *model_lookup;
+ Eina_Hash *view_lookup;
+ } properties;
Eina_Bool scroll_x_locked : 1;
Eina_Bool scroll_y_locked : 1;