Mercurial > MadButterfly
annotate src/observer.c @ 206:748896358da2
Export subject_add_event_observer() to rest of the system.
- declare it in mb_observer.h
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Wed, 10 Dec 2008 12:02:17 +0800 |
parents | 75ec0124202a |
children | 29e1b2bffe4c |
rev | line source |
---|---|
73 | 1 #include <stdio.h> |
186
530bb7728546
Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'.
Thinker K.F. Li <thinker@branda.to>
parents:
185
diff
changeset
|
2 #include "mb_redraw_man.h" |
530bb7728546
Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'.
Thinker K.F. Li <thinker@branda.to>
parents:
185
diff
changeset
|
3 #include "mb_observer.h" |
530bb7728546
Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'.
Thinker K.F. Li <thinker@branda.to>
parents:
185
diff
changeset
|
4 #include "mb_tools.h" |
73 | 5 |
126 | 6 #ifndef ASSERT |
7 #define ASSERT(x) | |
8 #endif | |
9 | |
73 | 10 subject_t *subject_new(ob_factory_t *factory, void *obj, int obj_type) { |
11 subject_t *subject; | |
12 | |
13 subject = factory->subject_alloc(factory); | |
14 if(subject == NULL) | |
15 return NULL; | |
16 | |
17 subject->obj = obj; | |
18 subject->obj_type = obj_type; | |
19 subject->flags = 0; | |
20 STAILQ_INIT(subject->observers); | |
21 | |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
22 subject->factory = factory; |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
23 |
73 | 24 return subject; |
25 } | |
26 | |
125
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
27 /*! |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
28 * \todo Keep ob_factory following subject objects. |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
29 */ |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
30 void subject_free(subject_t *subject) { |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
31 ob_factory_t *factory = subject->factory; |
73 | 32 observer_t *observer; |
33 | |
126 | 34 ASSERT(!(subject->flags & SUBF_FREE)); |
125
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
35 if(subject->flags & SUBF_BUSY) { |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
36 /* Postpond the request until busy status been stoped. |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
37 * SUBF_BUSY means in subject_notify(). |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
38 */ |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
39 subject->flags |= SUBF_FREE; |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
40 return; |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
41 } |
1c1f28c124c9
Postponding free request when a subject is in subject_notify
Thinker K.F. Li <thinker@branda.to>
parents:
77
diff
changeset
|
42 |
73 | 43 while((observer = STAILQ_HEAD(subject->observers))) { |
44 STAILQ_REMOVE(subject->observers, observer_t, next, observer); | |
45 factory->observer_free(factory, observer); | |
46 } | |
47 factory->subject_free(factory, subject); | |
48 } | |
49 | |
50 | |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
51 void subject_notify(subject_t *subject, event_t *evt) { |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
52 ob_factory_t *factory = subject->factory; |
73 | 53 observer_t *observer; |
194
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
54 subject_t *old_subject; |
73 | 55 |
77 | 56 evt->tgt = subject; |
73 | 57 while(subject) { |
127
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
58 /*! |
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
59 * \note What is happend when the subject is freed by observer? |
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
60 * Postponding the request of free until notification |
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
61 * been finished. (\ref SUBF_BUSY / \ref SUBF_FREE) |
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
62 */ |
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
63 subject->flags |= SUBF_BUSY; |
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
64 |
77 | 65 evt->cur_tgt = subject->obj; |
73 | 66 for(observer = STAILQ_HEAD(subject->observers); |
67 observer != NULL; | |
68 observer = STAILQ_NEXT(observer_t, next, observer)) { | |
198
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
69 if (observer->type == EVT_ANY || observer->type == evt->type) |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
70 observer->hdr(evt, observer->arg); |
73 | 71 } |
72 | |
127
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
73 subject->flags &= ~SUBF_BUSY; |
194
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
74 |
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
75 old_subject = subject; |
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
76 subject = factory->get_parent_subject(factory, subject); |
127
d2cc7400c971
Bug of subject_notify() when free subjects.
Thinker K.F. Li <thinker@branda.to>
parents:
126
diff
changeset
|
77 |
194
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
78 if(old_subject->flags & SUBF_FREE) |
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
79 subject_free(old_subject); |
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
80 |
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
81 if(old_subject->flags & SUBF_STOP_PROPAGATE) |
73 | 82 break; |
83 } | |
84 } | |
85 | |
206
748896358da2
Export subject_add_event_observer() to rest of the system.
Thinker K.F. Li <thinker@branda.to>
parents:
202
diff
changeset
|
86 /*! \brief Add an observer for any type of events. |
748896358da2
Export subject_add_event_observer() to rest of the system.
Thinker K.F. Li <thinker@branda.to>
parents:
202
diff
changeset
|
87 */ |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
88 observer_t *subject_add_observer(subject_t *subject, |
73 | 89 evt_handler hdr, void *arg) { |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
90 ob_factory_t *factory = subject->factory; |
73 | 91 observer_t *observer; |
92 | |
93 observer = factory->observer_alloc(factory); | |
94 if(observer == NULL) | |
95 return NULL; | |
96 observer->hdr = hdr; | |
97 observer->arg = arg; | |
198
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
98 observer->type = EVT_ANY; |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
99 |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
100 STAILQ_INS_TAIL(subject->observers, observer_t, next, observer); |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
101 |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
102 return observer; |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
103 } |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
104 |
206
748896358da2
Export subject_add_event_observer() to rest of the system.
Thinker K.F. Li <thinker@branda.to>
parents:
202
diff
changeset
|
105 /*! \brief Add an observer for specified type of events. |
748896358da2
Export subject_add_event_observer() to rest of the system.
Thinker K.F. Li <thinker@branda.to>
parents:
202
diff
changeset
|
106 */ |
198
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
107 observer_t *subject_add_event_observer(subject_t *subject, int type, |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
108 evt_handler hdr, void *arg) { |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
109 ob_factory_t *factory = subject->factory; |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
110 observer_t *observer; |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
111 |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
112 observer = factory->observer_alloc(factory); |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
113 if(observer == NULL) |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
114 return NULL; |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
115 observer->hdr = hdr; |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
116 observer->arg = arg; |
f9d507a3e1d9
Add event observer which listen to one event type only.
wycc@wycc-desktop
parents:
192
diff
changeset
|
117 observer->type = type; |
73 | 118 |
119 STAILQ_INS_TAIL(subject->observers, observer_t, next, observer); | |
120 | |
121 return observer; | |
122 } | |
123 | |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
124 void subject_remove_observer(subject_t *subject, |
73 | 125 observer_t *observer) { |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
126 ob_factory_t *factory = subject->factory; |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
127 |
73 | 128 STAILQ_REMOVE(subject->observers, observer_t, next, observer); |
129 factory->observer_free(factory, observer); | |
130 } | |
131 | |
132 #ifdef UNITTEST | |
133 | |
134 #include <CUnit/Basic.h> | |
135 #include <stdlib.h> | |
136 | |
137 static subject_t *test_subject_alloc(ob_factory_t *factory) { | |
138 subject_t *subject; | |
139 | |
140 subject = (subject_t *)malloc(sizeof(subject_t)); | |
141 return subject; | |
142 } | |
143 | |
144 static void test_subject_free(ob_factory_t *factory, subject_t *subject) { | |
145 free(subject); | |
146 } | |
147 | |
148 static observer_t *test_observer_alloc(ob_factory_t *factory) { | |
149 observer_t *observer; | |
150 | |
151 observer = (observer_t *)malloc(sizeof(observer_t)); | |
152 return observer; | |
153 } | |
154 | |
155 static void test_observer_free(ob_factory_t *factory, observer_t *observer) { | |
156 free(observer); | |
157 } | |
158 | |
159 static subject_t *test_get_parent_subject(ob_factory_t *factory, | |
160 subject_t *subject) { | |
161 return NULL; | |
162 } | |
163 | |
164 static ob_factory_t test_factory = { | |
165 test_subject_alloc, | |
166 test_subject_free, | |
167 test_observer_alloc, | |
168 test_observer_free, | |
169 test_get_parent_subject | |
170 }; | |
171 | |
172 static void handler(event_t *evt, void *arg) { | |
173 int *cnt = (int *)arg; | |
174 | |
74 | 175 CU_ASSERT(evt->type == EVT_MOUSE_OUT); |
73 | 176 (*cnt)++; |
177 } | |
178 | |
179 void test_observer(void) { | |
180 subject_t *subject; | |
74 | 181 observer_t *observer[2]; |
73 | 182 event_t evt; |
183 int cnt = 0; | |
184 | |
185 subject = subject_new(&test_factory, NULL, 0); | |
186 subject->flags |= SUBF_STOP_PROPAGATE; | |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
187 observer[0] = subject_add_observer(subject, handler, &cnt); |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
188 observer[1] = subject_add_observer(subject, handler, &cnt); |
73 | 189 |
74 | 190 evt.type = EVT_MOUSE_OUT; |
73 | 191 evt.tgt = NULL; |
192 evt.cur_tgt = NULL; | |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
193 subject_notify(subject, &evt); |
74 | 194 CU_ASSERT(cnt == 2); |
73 | 195 |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
196 subject_remove_observer(subject, observer[0]); |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
197 subject_remove_observer(subject, observer[1]); |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
198 subject_free(subject); |
73 | 199 } |
200 | |
201 CU_pSuite get_observer_suite(void) { | |
202 CU_pSuite suite; | |
203 | |
204 suite = CU_add_suite("Suite_observer", NULL, NULL); | |
205 CU_ADD_TEST(suite, test_observer); | |
206 | |
207 return suite; | |
208 } | |
209 | |
210 #endif /* UNITTEST */ |