Mercurial > MadButterfly
diff src/observer.c @ 73:9ab15ebc9061
Observer for mouse events
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 18 Aug 2008 01:59:26 +0800 |
parents | |
children | 3e3e074120a7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/observer.c Mon Aug 18 01:59:26 2008 +0800 @@ -0,0 +1,149 @@ +#include <stdio.h> +#include "redraw_man.h" +#include "observer.h" +#include "tools.h" + +subject_t *subject_new(ob_factory_t *factory, void *obj, int obj_type) { + subject_t *subject; + + subject = factory->subject_alloc(factory); + if(subject == NULL) + return NULL; + + subject->obj = obj; + subject->obj_type = obj_type; + subject->flags = 0; + STAILQ_INIT(subject->observers); + + return subject; +} + +void subject_free(ob_factory_t *factory, subject_t *subject) { + observer_t *observer; + + while((observer = STAILQ_HEAD(subject->observers))) { + STAILQ_REMOVE(subject->observers, observer_t, next, observer); + factory->observer_free(factory, observer); + } + factory->subject_free(factory, subject); +} + + +void subject_notify(ob_factory_t *factory, subject_t *subject, event_t *evt) { + observer_t *observer; + + while(subject) { + for(observer = STAILQ_HEAD(subject->observers); + observer != NULL; + observer = STAILQ_NEXT(observer_t, next, observer)) { + observer->hdr(evt, observer->arg); + } + + if(subject->flags & SUBF_STOP_PROPAGATE) + break; + + subject = factory->get_parent_subject(factory, subject); + } +} + +observer_t *subject_add_observer(ob_factory_t *factory, + subject_t *subject, + evt_handler hdr, void *arg) { + observer_t *observer; + + observer = factory->observer_alloc(factory); + if(observer == NULL) + return NULL; + observer->hdr = hdr; + observer->arg = arg; + + STAILQ_INS_TAIL(subject->observers, observer_t, next, observer); + + return observer; +} + +void subject_remove_observer(ob_factory_t *factory, + subject_t *subject, + observer_t *observer) { + STAILQ_REMOVE(subject->observers, observer_t, next, observer); + factory->observer_free(factory, observer); +} + +#ifdef UNITTEST + +#include <CUnit/Basic.h> +#include <stdlib.h> + +static subject_t *test_subject_alloc(ob_factory_t *factory) { + subject_t *subject; + + subject = (subject_t *)malloc(sizeof(subject_t)); + return subject; +} + +static void test_subject_free(ob_factory_t *factory, subject_t *subject) { + free(subject); +} + +static observer_t *test_observer_alloc(ob_factory_t *factory) { + observer_t *observer; + + observer = (observer_t *)malloc(sizeof(observer_t)); + return observer; +} + +static void test_observer_free(ob_factory_t *factory, observer_t *observer) { + free(observer); +} + +static subject_t *test_get_parent_subject(ob_factory_t *factory, + subject_t *subject) { + return NULL; +} + +static ob_factory_t test_factory = { + test_subject_alloc, + test_subject_free, + test_observer_alloc, + test_observer_free, + test_get_parent_subject +}; + +static void handler(event_t *evt, void *arg) { + int *cnt = (int *)arg; + + CU_ASSERT(evt->type == EVT_MOUSE_OVER); + (*cnt)++; +} + +void test_observer(void) { + subject_t *subject; + observer_t *observer; + event_t evt; + int cnt = 0; + + subject = subject_new(&test_factory, NULL, 0); + subject->flags |= SUBF_STOP_PROPAGATE; + observer = subject_add_observer(&test_factory, subject, + handler, &cnt); + + evt.type = EVT_MOUSE_OVER; + evt.tgt = NULL; + evt.cur_tgt = NULL; + subject_notify(&test_factory, subject, &evt); + CU_ASSERT(cnt == 1); + + subject_remove_observer(&test_factory, subject, observer); + subject_free(&test_factory, subject); +} + +CU_pSuite get_observer_suite(void) { + CU_pSuite suite; + + suite = CU_add_suite("Suite_observer", NULL, NULL); + CU_ADD_TEST(suite, test_observer); + + return suite; +} + +#endif /* UNITTEST */