summaryrefslogtreecommitdiff
path: root/src/lib/efl
diff options
context:
space:
mode:
authorJee-Yong Um <conr2d@gmail.com>2016-11-01 10:59:09 -0700
committerCedric BAIL <cedric@osg.samsung.com>2016-11-01 11:48:44 -0700
commit0fd144550877ff0a6f413c025685b7e7d63e6535 (patch)
tree600eabc63544ab9e287fcf36f1ef1f3d69ec93a2 /src/lib/efl
parentab9f0ae3ca3f97f550f33947da6e49ac256076ca (diff)
edje.object: implement Efl.Observer interface
Summary: To remove duplicated lines to handle edje class (color, text, size), observer interface is implemented to Edje.Object. Reviewers: jpeg, cedric Reviewed By: cedric Subscribers: bu5hm4n, cedric Differential Revision: https://phab.enlightenment.org/D4359 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
Diffstat (limited to 'src/lib/efl')
-rw-r--r--src/lib/efl/Efl.h3
-rw-r--r--src/lib/efl/interfaces/efl_observable.eo63
-rw-r--r--src/lib/efl/interfaces/efl_observer.c259
-rw-r--r--src/lib/efl/interfaces/efl_observer.eo15
-rw-r--r--src/lib/efl/interfaces/efl_types.eot6
5 files changed, 346 insertions, 0 deletions
diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h
index 142950aed6..afcb314863 100644
--- a/src/lib/efl/Efl.h
+++ b/src/lib/efl/Efl.h
@@ -53,6 +53,9 @@ typedef struct tm Efl_Time;
53 53
54#ifdef EFL_BETA_API_SUPPORT 54#ifdef EFL_BETA_API_SUPPORT
55 55
56#include "interfaces/efl_observer.eo.h"
57#include "interfaces/efl_observable.eo.h"
58
56#include "interfaces/efl_types.eot.h" 59#include "interfaces/efl_types.eot.h"
57 60
58#include <Efl_Model_Common.h> 61#include <Efl_Model_Common.h>
diff --git a/src/lib/efl/interfaces/efl_observable.eo b/src/lib/efl/interfaces/efl_observable.eo
new file mode 100644
index 0000000000..7accb4c9f4
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_observable.eo
@@ -0,0 +1,63 @@
1class Efl.Observable (Efl.Object) {
2 methods {
3 observer_add {
4 [[Add an observer to a group of observers.
5
6 Note: Observers that observe this observable are grouped by the $key
7 and an observer can belong to multiple groups at the same time.
8
9 @since 1.19]]
10 params {
11 @in key: string; [[A key to classify observer groups]]
12 @in obs: Efl.Observer; [[An observer object]]
13 }
14 }
15 observer_del {
16 [[Delete an observer from a group of observers.
17
18 See also @.observer_add().
19
20 @since 1.19]]
21 params {
22 @in key: string; [[A key to classify observer groups]]
23 @in obs: Efl.Observer; [[An observer object]]
24 }
25 }
26 observer_clean {
27 [[Clear an observer from all groups of observers.
28
29 @since 1.19]]
30 params {
31 @in obs: Efl.Observer; [[An observer object]]
32 }
33 }
34 observers_iterator_new {
35 [[Return a new iterator associated with a group of observers.
36
37 @since 1.19]]
38 return: free(own(iterator<Efl.Observer>), eina_iterator_free);
39 params {
40 @in key: string; [[A key to classify observer groups]]
41 }
42 }
43 observers_update {
44 [[Update all observers in a group by calling their update() method.
45
46 @since 1.19]]
47 params {
48 @in key: string; [[A key to classify observer groups]]
49 @in data: void_ptr; [[Required data to update observer]]
50 }
51 }
52 iterator_tuple_new {
53 [[Return a new iterator associated to this observable.
54
55 @since 1.19]]
56 return: free(own(iterator<Efl.Observable.Tuple>), eina_iterator_free);
57 }
58 }
59 implements {
60 Efl.Object.constructor;
61 Efl.Object.destructor;
62 }
63}
diff --git a/src/lib/efl/interfaces/efl_observer.c b/src/lib/efl/interfaces/efl_observer.c
new file mode 100644
index 0000000000..eb2ca92f9f
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_observer.c
@@ -0,0 +1,259 @@
1#include "config.h"
2#include "Efl.h"
3
4typedef struct
5{
6 Eina_Hash *observers;
7} Efl_Observable_Data;
8
9typedef struct
10{
11 EINA_REFCOUNT;
12
13 Efl_Observer *o;
14} Efl_Observer_Refcount;
15
16EOLIAN static Eo *
17_efl_observable_efl_object_constructor(Efl_Object *obj, Efl_Observable_Data *pd)
18{
19 pd->observers = eina_hash_string_superfast_new((Eina_Free_Cb)eina_hash_free);
20
21 obj = efl_constructor(efl_super(obj, EFL_OBSERVABLE_CLASS));
22
23 return obj;
24}
25
26EOLIAN static void
27_efl_observable_efl_object_destructor(Eo *obj, Efl_Observable_Data *pd)
28{
29 eina_hash_free(pd->observers);
30
31 efl_destructor(efl_super(obj, EFL_OBSERVABLE_CLASS));
32}
33
34EOLIAN static void
35_efl_observable_observer_add(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, const char *key, Efl_Observer *obs)
36{
37 Eina_Hash *observers;
38 Efl_Observer_Refcount *or;
39
40 if (!key) return;
41
42 observers = eina_hash_find(pd->observers, key);
43 if (!observers)
44 {
45 observers = eina_hash_pointer_new(free);
46 eina_hash_add(pd->observers, key, observers);
47 }
48
49 or = eina_hash_find(observers, &obs);
50 if (!or)
51 {
52 or = calloc(1, sizeof(Efl_Observer_Refcount));
53 or->o = obs;
54 EINA_REFCOUNT_INIT(or);
55
56 eina_hash_direct_add(observers, &or->o, or);
57 }
58 else
59 {
60 EINA_REFCOUNT_REF(or);
61 }
62}
63
64EOLIAN static void
65_efl_observable_observer_del(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, const char *key, Efl_Observer *obs)
66{
67 Eina_Hash *observers;
68 Efl_Observer_Refcount *or;
69
70 if (!key) return;
71
72 observers = eina_hash_find(pd->observers, key);
73 if (!observers) return;
74
75 or = eina_hash_find(observers, &obs);
76 if (!or) return;
77
78 EINA_REFCOUNT_UNREF(or)
79 {
80 eina_hash_del(observers, &or->o, or);
81
82 if (eina_hash_population(observers) == 0)
83 {
84 eina_hash_del(pd->observers, key, observers);
85 }
86 }
87}
88
89EOLIAN static void
90_efl_observable_observer_clean(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, Efl_Observer *obs)
91{
92 Eina_Iterator *it;
93 Eina_Hash *observers;
94
95 it = eina_hash_iterator_data_new(pd->observers);
96 EINA_ITERATOR_FOREACH(it, observers)
97 {
98 Efl_Observer_Refcount *or;
99
100 or = eina_hash_find(observers, &obs);
101 if (!or) continue;
102
103 EINA_REFCOUNT_UNREF(or)
104 {
105 eina_hash_del(observers, &obs, or);
106 }
107 }
108 eina_iterator_free(it);
109}
110
111typedef struct
112{
113 Eina_Iterator iterator;
114 Eina_Iterator *classes;
115} Efl_Observer_Iterator;
116
117static Eina_Bool
118_efl_observable_observers_iterator_next(Eina_Iterator *it, void **data)
119{
120 Efl_Observer_Iterator *et = (void *)it;
121 Efl_Observer_Refcount *or = NULL;
122
123 if (!eina_iterator_next(et->classes, (void **)&or)) return EINA_FALSE;
124 if (!or) return EINA_FALSE;
125
126 *data = or->o;
127
128 return EINA_TRUE;
129}
130
131static void *
132_efl_observable_observers_iterator_container(Eina_Iterator *it EINA_UNUSED)
133{
134 return NULL;
135}
136
137static void
138_efl_observable_observers_iterator_free(Eina_Iterator *it)
139{
140 Efl_Observer_Iterator *et = (void *)it;
141
142 eina_iterator_free(et->classes);
143 EINA_MAGIC_SET(&et->iterator, 0);
144 free(et);
145}
146
147EOLIAN static Eina_Iterator *
148_efl_observable_observers_iterator_new(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, const char *key)
149{
150 Eina_Hash *observers;
151 Efl_Observer_Iterator *it;
152
153 observers = eina_hash_find(pd->observers, key);
154 if (!observers) return NULL;
155
156 it = calloc(1, sizeof(Efl_Observer_Iterator));
157 if (!it) return NULL;
158
159 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
160 it->classes = eina_hash_iterator_data_new(observers);
161
162 it->iterator.version = EINA_ITERATOR_VERSION;
163 it->iterator.next = _efl_observable_observers_iterator_next;
164 it->iterator.get_container = _efl_observable_observers_iterator_container;
165 it->iterator.free = _efl_observable_observers_iterator_free;
166
167 return &it->iterator;
168}
169
170EOLIAN static void
171_efl_observable_observers_update(Eo *obj, Efl_Observable_Data *pd EINA_UNUSED, const char *key, void *data)
172{
173 Eina_Iterator *it;
174 Efl_Observer *o;
175
176 it = efl_observable_observers_iterator_new(obj, key);
177 if (!it) return;
178
179 EINA_ITERATOR_FOREACH(it, o)
180 {
181 efl_observer_update(o, obj, key, data);
182 }
183}
184
185typedef struct
186{
187 Eina_Iterator iterator;
188 Eina_Iterator *classes;
189 Efl_Observable *obs;
190 Eina_List *tuples;
191} Efl_Observable_Iterator;
192
193static Eina_Bool
194_efl_observable_iterator_tuple_next(Eina_Iterator *it, void **data)
195{
196 Efl_Observable_Iterator *et = (void *)it;
197 Efl_Observable_Tuple *tuple;
198 const char *key;
199
200 if (!eina_iterator_next(et->classes, (void **)&key)) return EINA_FALSE;
201 if (!key) return EINA_FALSE;
202
203 tuple = calloc(1, sizeof(Efl_Observable_Tuple));
204 if (!tuple) return EINA_FALSE;
205
206 tuple->key = key;
207 tuple->data = efl_observable_observers_iterator_new(et->obs, key);
208
209 et->tuples = eina_list_append(et->tuples, tuple);
210 *data = tuple;
211
212 return EINA_TRUE;
213}
214
215static void *
216_efl_observable_iterator_tuple_container(Eina_Iterator *it EINA_UNUSED)
217{
218 return NULL;
219}
220
221static void
222_efl_observable_iterator_tuple_free(Eina_Iterator *it)
223{
224 Efl_Observable_Iterator *et = (void *)it;
225 Efl_Observable_Tuple *tuple;
226
227 eina_iterator_free(et->classes);
228 EINA_LIST_FREE(et->tuples, tuple)
229 {
230 if (tuple->data)
231 eina_iterator_free(tuple->data);
232 free(tuple);
233 }
234 EINA_MAGIC_SET(&et->iterator, 0);
235 free(et);
236}
237
238EOLIAN static Eina_Iterator *
239_efl_observable_iterator_tuple_new(Eo *obj, Efl_Observable_Data *pd)
240{
241 Efl_Observable_Iterator *it;
242
243 it = calloc(1, sizeof(Efl_Observable_Iterator));
244 if (!it) return NULL;
245
246 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
247 it->classes = eina_hash_iterator_key_new(pd->observers);
248 it->obs = obj;
249
250 it->iterator.version = EINA_ITERATOR_VERSION;
251 it->iterator.next = _efl_observable_iterator_tuple_next;
252 it->iterator.get_container = _efl_observable_iterator_tuple_container;
253 it->iterator.free = _efl_observable_iterator_tuple_free;
254
255 return &it->iterator;
256}
257
258#include "efl_observable.eo.c"
259#include "efl_observer.eo.c"
diff --git a/src/lib/efl/interfaces/efl_observer.eo b/src/lib/efl/interfaces/efl_observer.eo
new file mode 100644
index 0000000000..a0d4ffe665
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_observer.eo
@@ -0,0 +1,15 @@
1interface Efl.Observer {
2 methods {
3 update @virtual_pure {
4 [[Update observer according to the changes of observable object.
5
6 @since 1.19]]
7 params {
8 /* FIXME: obs should be Efl.Observable, but cyclic dependency error occurs. */
9 @in obs: Efl.Object; [[An observable object]]
10 @in key: string; [[A key to classify observer groups]]
11 @in data: void_ptr; [[Required data to update the observer, usually passed by observable object]]
12 }
13 }
14 }
15}
diff --git a/src/lib/efl/interfaces/efl_types.eot b/src/lib/efl/interfaces/efl_types.eot
index 0625dc3c65..988f7abb68 100644
--- a/src/lib/efl/interfaces/efl_types.eot
+++ b/src/lib/efl/interfaces/efl_types.eot
@@ -38,3 +38,9 @@ struct Efl.Version
38 vanilla (upstream) EFL. Contains $EFL_VERSION_FLAVOR.]] 38 vanilla (upstream) EFL. Contains $EFL_VERSION_FLAVOR.]]
39 build_id: string; [[Contains $EFL_BUILD_ID.]] 39 build_id: string; [[Contains $EFL_BUILD_ID.]]
40} 40}
41
42struct Efl.Observable.Tuple
43{
44 key: string;
45 data: free(own(iterator<Efl.Observer>), eina_iterator_free);
46}