diff options
author | Cedric BAIL <cedric.bail@free.fr> | 2019-07-11 14:53:19 -0700 |
---|---|---|
committer | Marcel Hollerbach <mail@marcel-hollerbach.de> | 2019-07-17 21:57:53 +0200 |
commit | 9e6d3b44e62c341bda6a7f226b589673fcc9cc98 (patch) | |
tree | cdebedb508bb2488b1842f7b9e1f9a6e856fba11 | |
parent | c0e7b1343c6407b040b2d137a675f91ff7574b8d (diff) |
eo: add ability to register provider on the Eo object directly.
This should reduce the need for custom implementation of efl_object_provider_bind.
It also enable the ability to register provider from user code on any Efl_Object.
Reviewed-by: Marcel Hollerbach <mail@marcel-hollerbach.de>
Differential Revision: https://phab.enlightenment.org/D9292
-rw-r--r-- | src/lib/eo/efl_object.eo | 16 | ||||
-rw-r--r-- | src/lib/eo/eo_base_class.c | 104 |
2 files changed, 93 insertions, 27 deletions
diff --git a/src/lib/eo/efl_object.eo b/src/lib/eo/efl_object.eo index 85cb664958..0b3c403a20 100644 --- a/src/lib/eo/efl_object.eo +++ b/src/lib/eo/efl_object.eo | |||
@@ -402,6 +402,22 @@ abstract Efl.Object | |||
402 | even if @.parent is not $null.]] | 402 | even if @.parent is not $null.]] |
403 | } | 403 | } |
404 | } | 404 | } |
405 | provider_register { | ||
406 | [[Will register a manager of a specific class to be answered by eo.provider_find.]] | ||
407 | params { | ||
408 | @in klass: const(Efl.Class); [[The class provided by the registered provider.]] | ||
409 | @in provider: const(Efl.Object); [[The provider for the newly registered class that has to provide that said Efl.Class.]] | ||
410 | } | ||
411 | return: bool; [[$true if successfully register, $false otherwise.]] | ||
412 | } | ||
413 | provider_unregister { | ||
414 | [[Will unregister a manager of a specific class that was previously registered and answered by eo.provider_find.]] | ||
415 | params { | ||
416 | @in klass: const(Efl.Class); [[The class provided by the provider to unregister for.]] | ||
417 | @in provider: const(Efl.Object); [[The provider for the registered class to unregister.]] | ||
418 | } | ||
419 | return: bool; [[$true if successfully unregistered, $false otherwise.]] | ||
420 | } | ||
405 | } | 421 | } |
406 | implements { | 422 | implements { |
407 | class.constructor; | 423 | class.constructor; |
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index 62a1caf9a2..d9edf15a90 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c | |||
@@ -39,6 +39,7 @@ typedef struct | |||
39 | Eo *composite_parent; | 39 | Eo *composite_parent; |
40 | Eina_Inlist *generic_data; | 40 | Eina_Inlist *generic_data; |
41 | Eo ***wrefs; | 41 | Eo ***wrefs; |
42 | Eina_Hash *providers; | ||
42 | } Efl_Object_Extension; | 43 | } Efl_Object_Extension; |
43 | 44 | ||
44 | struct _Efl_Object_Data | 45 | struct _Efl_Object_Data |
@@ -125,11 +126,46 @@ _efl_pending_futures_clear(Efl_Object_Data *pd) | |||
125 | } | 126 | } |
126 | } | 127 | } |
127 | 128 | ||
129 | static inline void | ||
130 | _efl_object_extension_free(Efl_Object_Extension *ext) | ||
131 | { | ||
132 | eina_freeq_ptr_main_add(ext, free, sizeof(*ext)); | ||
133 | } | ||
134 | |||
135 | static inline Efl_Object_Extension * | ||
136 | _efl_object_extension_need(Efl_Object_Data *pd) | ||
137 | { | ||
138 | if (!pd->ext) pd->ext = calloc(1, sizeof(Efl_Object_Extension)); | ||
139 | return pd->ext; | ||
140 | } | ||
141 | |||
142 | static inline void | ||
143 | _efl_object_extension_noneed(Efl_Object_Data *pd) | ||
144 | { | ||
145 | Efl_Object_Extension *ext = pd->ext; | ||
146 | if ((!ext) || | ||
147 | (ext->name) || | ||
148 | (ext->comment) || | ||
149 | (ext->generic_data) || | ||
150 | (ext->wrefs) || | ||
151 | (ext->composite_parent) || | ||
152 | (ext->providers)) return; | ||
153 | _efl_object_extension_free(pd->ext); | ||
154 | pd->ext = NULL; | ||
155 | } | ||
156 | |||
128 | static void | 157 | static void |
129 | _efl_object_invalidate(Eo *obj_id, Efl_Object_Data *pd) | 158 | _efl_object_invalidate(Eo *obj_id, Efl_Object_Data *pd) |
130 | { | 159 | { |
131 | _efl_pending_futures_clear(pd); | 160 | _efl_pending_futures_clear(pd); |
132 | 161 | ||
162 | if (pd->ext && pd->ext->providers) | ||
163 | { | ||
164 | eina_hash_free(pd->ext->providers); | ||
165 | pd->ext->providers = NULL; | ||
166 | _efl_object_extension_noneed(pd); | ||
167 | } | ||
168 | |||
133 | EO_OBJ_POINTER_RETURN(obj_id, obj); | 169 | EO_OBJ_POINTER_RETURN(obj_id, obj); |
134 | 170 | ||
135 | // Finally invalidate itself if it wasn't done already | 171 | // Finally invalidate itself if it wasn't done already |
@@ -185,33 +221,6 @@ _efl_invalidate(_Eo_Object *obj) | |||
185 | obj->invalidate = EINA_TRUE; | 221 | obj->invalidate = EINA_TRUE; |
186 | } | 222 | } |
187 | 223 | ||
188 | static inline void | ||
189 | _efl_object_extension_free(Efl_Object_Extension *ext) | ||
190 | { | ||
191 | eina_freeq_ptr_main_add(ext, free, sizeof(*ext)); | ||
192 | } | ||
193 | |||
194 | static inline Efl_Object_Extension * | ||
195 | _efl_object_extension_need(Efl_Object_Data *pd) | ||
196 | { | ||
197 | if (!pd->ext) pd->ext = calloc(1, sizeof(Efl_Object_Extension)); | ||
198 | return pd->ext; | ||
199 | } | ||
200 | |||
201 | static inline void | ||
202 | _efl_object_extension_noneed(Efl_Object_Data *pd) | ||
203 | { | ||
204 | Efl_Object_Extension *ext = pd->ext; | ||
205 | if ((!ext) || | ||
206 | (ext->name) || | ||
207 | (ext->comment) || | ||
208 | (ext->generic_data) || | ||
209 | (ext->wrefs) || | ||
210 | (ext->composite_parent)) return; | ||
211 | _efl_object_extension_free(pd->ext); | ||
212 | pd->ext = NULL; | ||
213 | } | ||
214 | |||
215 | static void _key_generic_cb_del(void *data, const Efl_Event *event); | 224 | static void _key_generic_cb_del(void *data, const Efl_Event *event); |
216 | 225 | ||
217 | static void | 226 | static void |
@@ -832,6 +841,7 @@ EOLIAN static Efl_Object * | |||
832 | _efl_object_provider_find(const Eo *obj, Efl_Object_Data *pd, const Efl_Object *klass) | 841 | _efl_object_provider_find(const Eo *obj, Efl_Object_Data *pd, const Efl_Object *klass) |
833 | { | 842 | { |
834 | Eina_Bool invalidate; | 843 | Eina_Bool invalidate; |
844 | Efl_Object *r = NULL; | ||
835 | 845 | ||
836 | invalidate = _efl_object_invalidated_get((Eo*) obj, NULL); | 846 | invalidate = _efl_object_invalidated_get((Eo*) obj, NULL); |
837 | if (invalidate) | 847 | if (invalidate) |
@@ -839,10 +849,50 @@ _efl_object_provider_find(const Eo *obj, Efl_Object_Data *pd, const Efl_Object * | |||
839 | ERR("Calling efl_provider_find(%p) after the object was invalidated.", obj); | 849 | ERR("Calling efl_provider_find(%p) after the object was invalidated.", obj); |
840 | return NULL; | 850 | return NULL; |
841 | } | 851 | } |
852 | |||
853 | if (efl_isa(obj, klass)) return (Eo *) obj; | ||
854 | |||
855 | if (pd->ext) r = eina_hash_find(pd->ext->providers, &klass); | ||
856 | if (r) return r; | ||
857 | |||
842 | if (pd->parent) return efl_provider_find(pd->parent, klass); | 858 | if (pd->parent) return efl_provider_find(pd->parent, klass); |
843 | return NULL; | 859 | return NULL; |
844 | } | 860 | } |
845 | 861 | ||
862 | static Eina_Bool | ||
863 | _efl_object_provider_register(Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const Efl_Class *klass, const Efl_Object *provider) | ||
864 | { | ||
865 | // The passed object does not provide that said class. | ||
866 | if (!efl_isa(provider, klass)) return EINA_FALSE; | ||
867 | |||
868 | _efl_object_extension_need(pd); | ||
869 | if (!pd->ext) return EINA_FALSE; | ||
870 | if (!pd->ext->providers) pd->ext->providers = eina_hash_pointer_new(EINA_FREE_CB(efl_unref)); | ||
871 | |||
872 | // Prevent double insertion for the same class | ||
873 | if (eina_hash_find(pd->ext->providers, &klass)) return EINA_FALSE; | ||
874 | |||
875 | // Note: I would prefer to use efl_xref here, but I can't figure a nice way to | ||
876 | // call efl_xunref on hash destruction. | ||
877 | return eina_hash_add(pd->ext->providers, &klass, efl_ref(provider)); | ||
878 | } | ||
879 | |||
880 | static Eina_Bool | ||
881 | _efl_object_provider_unregister(Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const Efl_Class *klass, const Efl_Object *provider) | ||
882 | { | ||
883 | Eina_Bool r; | ||
884 | |||
885 | if (!pd->ext) return EINA_FALSE; | ||
886 | r = eina_hash_del(pd->ext->providers, &klass, provider); | ||
887 | |||
888 | if (eina_hash_population(pd->ext->providers) != 0) return r; | ||
889 | eina_hash_free(pd->ext->providers); | ||
890 | pd->ext->providers = NULL; | ||
891 | _efl_object_extension_noneed(pd); | ||
892 | |||
893 | return r; | ||
894 | } | ||
895 | |||
846 | /* Children accessor */ | 896 | /* Children accessor */ |
847 | typedef struct _Eo_Children_Iterator Eo_Children_Iterator; | 897 | typedef struct _Eo_Children_Iterator Eo_Children_Iterator; |
848 | struct _Eo_Children_Iterator | 898 | struct _Eo_Children_Iterator |