00001 #include <stdio.h>
00002 #include "mb_redraw_man.h"
00003 #include "mb_observer.h"
00004 #include "mb_tools.h"
00005
00006 #ifndef ASSERT
00007 #define ASSERT(x)
00008 #endif
00009
00010 subject_t *subject_new(ob_factory_t *factory, void *obj, int obj_type) {
00011 subject_t *subject;
00012
00013 subject = factory->subject_alloc(factory);
00014 if(subject == NULL)
00015 return NULL;
00016
00017 subject->obj = obj;
00018 subject->obj_type = obj_type;
00019 subject->flags = 0;
00020 STAILQ_INIT(subject->observers);
00021
00022 return subject;
00023 }
00024
00025
00026
00027
00028 void subject_free(ob_factory_t *factory, subject_t *subject) {
00029 observer_t *observer;
00030
00031 ASSERT(!(subject->flags & SUBF_FREE));
00032 if(subject->flags & SUBF_BUSY) {
00033
00034
00035
00036 subject->flags |= SUBF_FREE;
00037 return;
00038 }
00039
00040 while((observer = STAILQ_HEAD(subject->observers))) {
00041 STAILQ_REMOVE(subject->observers, observer_t, next, observer);
00042 factory->observer_free(factory, observer);
00043 }
00044 factory->subject_free(factory, subject);
00045 }
00046
00047
00048 void subject_notify(ob_factory_t *factory, subject_t *subject, event_t *evt) {
00049 observer_t *observer;
00050
00051 evt->tgt = subject;
00052 while(subject) {
00053
00054
00055
00056
00057
00058 subject->flags |= SUBF_BUSY;
00059
00060 evt->cur_tgt = subject->obj;
00061 for(observer = STAILQ_HEAD(subject->observers);
00062 observer != NULL;
00063 observer = STAILQ_NEXT(observer_t, next, observer)) {
00064 observer->hdr(evt, observer->arg);
00065 }
00066
00067 subject->flags &= ~SUBF_BUSY;
00068 if(subject->flags & SUBF_FREE)
00069 subject_free(factory, subject);
00070
00071 if(subject->flags & SUBF_STOP_PROPAGATE)
00072 break;
00073
00074 subject = factory->get_parent_subject(factory, subject);
00075 }
00076
00077 }
00078
00079 observer_t *subject_add_observer(ob_factory_t *factory,
00080 subject_t *subject,
00081 evt_handler hdr, void *arg) {
00082 observer_t *observer;
00083
00084 observer = factory->observer_alloc(factory);
00085 if(observer == NULL)
00086 return NULL;
00087 observer->hdr = hdr;
00088 observer->arg = arg;
00089
00090 STAILQ_INS_TAIL(subject->observers, observer_t, next, observer);
00091
00092 return observer;
00093 }
00094
00095 void subject_remove_observer(ob_factory_t *factory,
00096 subject_t *subject,
00097 observer_t *observer) {
00098 STAILQ_REMOVE(subject->observers, observer_t, next, observer);
00099 factory->observer_free(factory, observer);
00100 }
00101
00102 #ifdef UNITTEST
00103
00104 #include <CUnit/Basic.h>
00105 #include <stdlib.h>
00106
00107 static subject_t *test_subject_alloc(ob_factory_t *factory) {
00108 subject_t *subject;
00109
00110 subject = (subject_t *)malloc(sizeof(subject_t));
00111 return subject;
00112 }
00113
00114 static void test_subject_free(ob_factory_t *factory, subject_t *subject) {
00115 free(subject);
00116 }
00117
00118 static observer_t *test_observer_alloc(ob_factory_t *factory) {
00119 observer_t *observer;
00120
00121 observer = (observer_t *)malloc(sizeof(observer_t));
00122 return observer;
00123 }
00124
00125 static void test_observer_free(ob_factory_t *factory, observer_t *observer) {
00126 free(observer);
00127 }
00128
00129 static subject_t *test_get_parent_subject(ob_factory_t *factory,
00130 subject_t *subject) {
00131 return NULL;
00132 }
00133
00134 static ob_factory_t test_factory = {
00135 test_subject_alloc,
00136 test_subject_free,
00137 test_observer_alloc,
00138 test_observer_free,
00139 test_get_parent_subject
00140 };
00141
00142 static void handler(event_t *evt, void *arg) {
00143 int *cnt = (int *)arg;
00144
00145 CU_ASSERT(evt->type == EVT_MOUSE_OUT);
00146 (*cnt)++;
00147 }
00148
00149 void test_observer(void) {
00150 subject_t *subject;
00151 observer_t *observer[2];
00152 event_t evt;
00153 int cnt = 0;
00154
00155 subject = subject_new(&test_factory, NULL, 0);
00156 subject->flags |= SUBF_STOP_PROPAGATE;
00157 observer[0] = subject_add_observer(&test_factory, subject,
00158 handler, &cnt);
00159 observer[1] = subject_add_observer(&test_factory, subject,
00160 handler, &cnt);
00161
00162 evt.type = EVT_MOUSE_OUT;
00163 evt.tgt = NULL;
00164 evt.cur_tgt = NULL;
00165 subject_notify(&test_factory, subject, &evt);
00166 CU_ASSERT(cnt == 2);
00167
00168 subject_remove_observer(&test_factory, subject, observer[0]);
00169 subject_remove_observer(&test_factory, subject, observer[1]);
00170 subject_free(&test_factory, subject);
00171 }
00172
00173 CU_pSuite get_observer_suite(void) {
00174 CU_pSuite suite;
00175
00176 suite = CU_add_suite("Suite_observer", NULL, NULL);
00177 CU_ADD_TEST(suite, test_observer);
00178
00179 return suite;
00180 }
00181
00182 #endif