summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2019-07-10 18:03:46 -0700
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2019-07-17 21:57:51 +0200
commit2d481d859354205465db2ba3df07d2bcfcbd7979 (patch)
treec0446a76c44ba126e6f20c216d7cf5e838977b75
parenta68e18a903ffb0fa14d1b5ebeb3efc3a8db95812 (diff)
efl: add a Efl.Model_Provider that every widget will look up for in their parent tree.
This is done to simplify code as you only need to set the model on the provider and all the widget that are using it as a provider will automatically be updated. The child will find a provider during at the time the first property binding is set on the widget by checking if the parent have an Efl.Model_Provider set. It is not necessary to set a model to have a valid lookup on a Efl.Model_Provider. To disable a widget lookup, you can just force set a model on it (even NULL) and it will disable the lookup. Reviewed-by: Marcel Hollerbach <mail@marcel-hollerbach.de> Differential Revision: https://phab.enlightenment.org/D9290
-rw-r--r--src/lib/efl/Efl.h1
-rw-r--r--src/lib/efl/interfaces/efl_model_provider.c36
-rw-r--r--src/lib/efl/interfaces/efl_model_provider.eo12
-rw-r--r--src/lib/efl/interfaces/meson.build2
-rw-r--r--src/lib/elementary/efl_ui_widget.c77
-rw-r--r--src/lib/elementary/elm_widget.h1
6 files changed, 121 insertions, 8 deletions
diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h
index d2746eeedc..97c21ec3fb 100644
--- a/src/lib/efl/Efl.h
+++ b/src/lib/efl/Efl.h
@@ -147,6 +147,7 @@ typedef Efl_Gfx_Path_Command_Type Efl_Gfx_Path_Command;
147#include "interfaces/efl_ui_property_bind.eo.h" 147#include "interfaces/efl_ui_property_bind.eo.h"
148#include "interfaces/efl_ui_factory.eo.h" 148#include "interfaces/efl_ui_factory.eo.h"
149#include "interfaces/efl_ui_factory_bind.eo.h" 149#include "interfaces/efl_ui_factory_bind.eo.h"
150#include "interfaces/efl_model_provider.eo.h"
150#include "interfaces/efl_cached_item.eo.h" 151#include "interfaces/efl_cached_item.eo.h"
151 152
152/* Observable interface */ 153/* Observable interface */
diff --git a/src/lib/efl/interfaces/efl_model_provider.c b/src/lib/efl/interfaces/efl_model_provider.c
new file mode 100644
index 0000000000..d60bb4469c
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_model_provider.c
@@ -0,0 +1,36 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "Efl.h"
6
7typedef struct _Efl_Model_Provider_Data Efl_Model_Provider_Data;
8struct _Efl_Model_Provider_Data
9{
10 Efl_Model *model;
11};
12
13static void
14_efl_model_provider_efl_ui_view_model_set(Eo *obj, Efl_Model_Provider_Data *pd,
15 Efl_Model *model)
16{
17 Efl_Model_Changed_Event ev;
18
19 ev.previous = efl_ref(pd->model);
20 ev.current = efl_ref(model);
21 efl_replace(&pd->model, model);
22
23 efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
24
25 efl_unref(ev.previous);
26 efl_unref(ev.current);
27}
28
29static Efl_Model *
30_efl_model_provider_efl_ui_view_model_get(const Eo *obj EINA_UNUSED,
31 Efl_Model_Provider_Data *pd)
32{
33 return pd->model;
34}
35
36#include "efl_model_provider.eo.c"
diff --git a/src/lib/efl/interfaces/efl_model_provider.eo b/src/lib/efl/interfaces/efl_model_provider.eo
new file mode 100644
index 0000000000..6fa68f520b
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_model_provider.eo
@@ -0,0 +1,12 @@
1class @beta Efl.Model_Provider extends Efl.Object implements Efl.Ui.View
2{
3 [[EFL object that provide a model to all.
4
5 You can use this when you would otherwise have to call @Efl.Ui.View.model.set
6 on multiple widgets by registering this object using @Efl.Object.provider_register
7 on a parent that they all depends on.
8 ]]
9 implements {
10 Efl.Ui.View.model { get; set; }
11 }
12}
diff --git a/src/lib/efl/interfaces/meson.build b/src/lib/efl/interfaces/meson.build
index d09a24c255..abfe721dac 100644
--- a/src/lib/efl/interfaces/meson.build
+++ b/src/lib/efl/interfaces/meson.build
@@ -63,6 +63,7 @@ pub_eo_files = [
63 'efl_gfx_blur.eo', 63 'efl_gfx_blur.eo',
64 'efl_gfx_hint.eo', 64 'efl_gfx_hint.eo',
65 'efl_model.eo', 65 'efl_model.eo',
66 'efl_model_provider.eo',
66 'efl_interpolator.eo', 67 'efl_interpolator.eo',
67 'efl_gfx_image_orientable.eo', 68 'efl_gfx_image_orientable.eo',
68 'efl_container.eo', 69 'efl_container.eo',
@@ -167,6 +168,7 @@ efl_src += files([
167 'efl_file.c', 168 'efl_file.c',
168 'efl_ui_layout_orientable_readonly.c', 169 'efl_ui_layout_orientable_readonly.c',
169 'efl_text_markup_util.c', 170 'efl_text_markup_util.c',
171 'efl_model_provider.c',
170]) 172])
171 173
172#efl_header_src += files([ 174#efl_header_src += files([
diff --git a/src/lib/elementary/efl_ui_widget.c b/src/lib/elementary/efl_ui_widget.c
index f7749d9a66..95522038f8 100644
--- a/src/lib/elementary/efl_ui_widget.c
+++ b/src/lib/elementary/efl_ui_widget.c
@@ -5786,20 +5786,71 @@ _efl_ui_widget_model_update(Efl_Ui_Widget_Data *pd)
5786 _efl_ui_property_bind_get(pd, property); 5786 _efl_ui_property_bind_get(pd, property);
5787} 5787}
5788 5788
5789static void _efl_ui_widget_model_provider_model_change(void *data, const Efl_Event *event EINA_UNUSED);
5790static void _efl_ui_widget_model_provider_invalidate(void *data, const Efl_Event *event EINA_UNUSED);
5791
5792EFL_CALLBACKS_ARRAY_DEFINE(efl_ui_widget_model_provider_callbacks,
5793 { EFL_EVENT_INVALIDATE, _efl_ui_widget_model_provider_invalidate },
5794 { EFL_UI_VIEW_EVENT_MODEL_CHANGED, _efl_ui_widget_model_provider_model_change });
5795
5796static void
5797_efl_ui_widget_model_provider_model_change(void *data, const Efl_Event *event)
5798{
5799 Efl_Ui_Widget_Data *pd = data;
5800
5801 efl_replace(&pd->properties.model,
5802 efl_ui_view_model_get(pd->properties.provider));
5803 _efl_ui_widget_model_update(pd);
5804
5805 efl_event_callback_call(pd->obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, event->info);
5806}
5807
5808static void
5809_efl_ui_widget_model_provider_invalidate(void *data, const Efl_Event *event EINA_UNUSED)
5810{
5811 Efl_Ui_Widget_Data *pd = data;
5812
5813 efl_event_callback_array_del(pd->properties.provider,
5814 efl_ui_widget_model_provider_callbacks(),
5815 pd);
5816 efl_replace(&pd->properties.provider, NULL);
5817 efl_replace(&pd->properties.model, NULL);
5818}
5819
5789static void 5820static void
5790_efl_ui_widget_model_register(Eo *obj, Efl_Ui_Widget_Data *pd) 5821_efl_ui_widget_model_register(Eo *obj, Efl_Ui_Widget_Data *pd)
5791{ 5822{
5792 if (pd->properties.registered) return ; 5823 if (pd->properties.registered) return ;
5793 if (pd->properties.model_lookup) 5824
5825 if (!pd->properties.model)
5794 { 5826 {
5827 Efl_Model_Changed_Event ev;
5828
5829 efl_replace(&pd->properties.provider,
5830 efl_provider_find(obj, EFL_MODEL_PROVIDER_CLASS));
5831 if (!pd->properties.provider) return ;
5832 efl_event_callback_array_add(pd->properties.provider,
5833 efl_ui_widget_model_provider_callbacks(),
5834 pd);
5835
5836 efl_replace(&pd->properties.model,
5837 efl_ui_view_model_get(pd->properties.provider));
5838
5795 if (!pd->properties.model) return ; 5839 if (!pd->properties.model) return ;
5796 5840
5797 efl_event_callback_add(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, 5841 ev.current = pd->properties.model;
5798 _efl_ui_model_property_bind_changed, pd); 5842 ev.previous = NULL;
5799 efl_event_callback_add(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED, 5843 efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
5800 _efl_ui_view_property_bind_changed, pd);
5801 pd->properties.registered = EINA_TRUE;
5802 } 5844 }
5845
5846 if (!pd->properties.model) return ;
5847 if (!pd->properties.model_lookup) return ;
5848
5849 efl_event_callback_add(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
5850 _efl_ui_model_property_bind_changed, pd);
5851 efl_event_callback_add(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
5852 _efl_ui_view_property_bind_changed, pd);
5853 pd->properties.registered = EINA_TRUE;
5803} 5854}
5804 5855
5805static void 5856static void
@@ -5815,6 +5866,9 @@ _efl_ui_widget_model_unregister(Eo *obj, Efl_Ui_Widget_Data *pd)
5815 5866
5816 pd->properties.registered = EINA_FALSE; 5867 pd->properties.registered = EINA_FALSE;
5817 } 5868 }
5869 // Invalidate must be called before setting a new model and even if no model is registered
5870 if (pd->properties.provider)
5871 _efl_ui_widget_model_provider_invalidate(pd, NULL);
5818} 5872}
5819static Eina_Error 5873static Eina_Error
5820_efl_ui_widget_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Widget_Data *pd, 5874_efl_ui_widget_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Widget_Data *pd,
@@ -5822,6 +5876,11 @@ _efl_ui_widget_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Widget_Data *p
5822{ 5876{
5823 Efl_Ui_Property_Bound *prop; 5877 Efl_Ui_Property_Bound *prop;
5824 5878
5879 // Always check for a model and fetch a provider in case a binded property
5880 // is provided by a class down the hierarchy, but they still need to be notified
5881 // when a model change
5882 _efl_ui_widget_model_register(obj, pd);
5883
5825 // Check if the property is available from the reflection table of the object. 5884 // Check if the property is available from the reflection table of the object.
5826 if (!efl_property_reflection_exist(obj, key)) return EFL_PROPERTY_ERROR_INVALID_KEY; 5885 if (!efl_property_reflection_exist(obj, key)) return EFL_PROPERTY_ERROR_INVALID_KEY;
5827 5886
@@ -5830,7 +5889,6 @@ _efl_ui_widget_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Widget_Data *p
5830 pd->properties.model_lookup = eina_hash_stringshared_new(_efl_ui_property_bind_free); 5889 pd->properties.model_lookup = eina_hash_stringshared_new(_efl_ui_property_bind_free);
5831 pd->properties.view_lookup = eina_hash_stringshared_new(NULL); 5890 pd->properties.view_lookup = eina_hash_stringshared_new(NULL);
5832 } 5891 }
5833 _efl_ui_widget_model_register(obj, pd);
5834 5892
5835 prop = calloc(1, sizeof (Efl_Ui_Property_Bound)); 5893 prop = calloc(1, sizeof (Efl_Ui_Property_Bound));
5836 if (!prop) return ENOMEM; 5894 if (!prop) return ENOMEM;
@@ -5864,7 +5922,10 @@ _efl_ui_widget_efl_ui_view_model_set(Eo *obj,
5864 // Set the properties handler just in case 5922 // Set the properties handler just in case
5865 _efl_ui_widget_model_register(obj, pd); 5923 _efl_ui_widget_model_register(obj, pd);
5866 5924
5867 efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev); 5925 // In case the model set was NULL, but we did found a model provider
5926 // we shouldn't emit a second event. Otherwise we should.
5927 if (ev.current == pd->properties.model)
5928 efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
5868 5929
5869 if (pd->properties.model) _efl_ui_widget_model_update(pd); 5930 if (pd->properties.model) _efl_ui_widget_model_update(pd);
5870 5931
diff --git a/src/lib/elementary/elm_widget.h b/src/lib/elementary/elm_widget.h
index f9fe403388..dfdfdb83f7 100644
--- a/src/lib/elementary/elm_widget.h
+++ b/src/lib/elementary/elm_widget.h
@@ -386,6 +386,7 @@ typedef struct _Elm_Widget_Smart_Data
386 } legacy_focus; 386 } legacy_focus;
387 struct { 387 struct {
388 Efl_Model *model; 388 Efl_Model *model;
389 Efl_Model_Provider *provider;
389 Eina_Hash *model_lookup; 390 Eina_Hash *model_lookup;
390 Eina_Hash *view_lookup; 391 Eina_Hash *view_lookup;
391 Eina_Bool registered : 1; 392 Eina_Bool registered : 1;