Mercurial > MadButterfly
comparison src/redraw_man.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 | 1ca417f741f1 |
children | 23bc382d9683 |
comparison
equal
deleted
inserted
replaced
72:171a8cb7e4b5 | 73:9ab15ebc9061 |
---|---|
4 #include <cairo.h> | 4 #include <cairo.h> |
5 #include "mb_types.h" | 5 #include "mb_types.h" |
6 #include "shapes.h" | 6 #include "shapes.h" |
7 #include "tools.h" | 7 #include "tools.h" |
8 #include "redraw_man.h" | 8 #include "redraw_man.h" |
9 #include "observer.h" | |
10 | |
9 | 11 |
10 /* NOTE: bounding box should also consider width of stroke. | 12 /* NOTE: bounding box should also consider width of stroke. |
11 */ | 13 */ |
12 | 14 |
13 #define OK 0 | 15 #define OK 0 |
14 #define ERR -1 | 16 #define ERR -1 |
15 | 17 |
16 #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL) | |
17 #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0) | 18 #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0) |
18 | 19 |
19 #ifdef UNITTEST | 20 #ifdef UNITTEST |
20 typedef struct _sh_dummy sh_dummy_t; | 21 typedef struct _sh_dummy sh_dummy_t; |
21 | 22 |
22 extern void sh_dummy_transform(shape_t *shape); | 23 extern void sh_dummy_transform(shape_t *shape); |
23 extern void sh_dummy_fill(shape_t *, cairo_t *); | 24 extern void sh_dummy_fill(shape_t *, cairo_t *); |
24 #endif /* UNITTEST */ | 25 #endif /* UNITTEST */ |
26 | |
27 static subject_t *ob_subject_alloc(ob_factory_t *factory); | |
28 static void ob_subject_free(ob_factory_t *factory, subject_t *subject); | |
29 static observer_t *ob_observer_alloc(ob_factory_t *factory); | |
30 static void ob_observer_free(ob_factory_t *factory, observer_t *observer); | |
31 static subject_t *ob_get_parent_subject(ob_factory_t *factory, | |
32 subject_t *cur_subject); | |
33 | |
25 | 34 |
26 /*! \brief Sort a list of element by a unsigned integer. | 35 /*! \brief Sort a list of element by a unsigned integer. |
27 * | 36 * |
28 * The result is in ascend order. The unsigned integers is | 37 * The result is in ascend order. The unsigned integers is |
29 * at offset specified by 'off' from start address of elemnts. | 38 * at offset specified by 'off' from start address of elemnts. |
121 elmpool_free(rdman->geo_pool); | 130 elmpool_free(rdman->geo_pool); |
122 elmpool_free(rdman->coord_pool); | 131 elmpool_free(rdman->coord_pool); |
123 return ERR; | 132 return ERR; |
124 } | 133 } |
125 | 134 |
135 rdman->observer_pool = elmpool_new(sizeof(observer_t), 16); | |
136 if(rdman->observer_pool == NULL) { | |
137 elmpool_free(rdman->geo_pool); | |
138 elmpool_free(rdman->coord_pool); | |
139 elmpool_free(rdman->shnode_pool); | |
140 return ERR; | |
141 } | |
142 | |
143 rdman->subject_pool = elmpool_new(sizeof(subject_t), 16); | |
144 if(rdman->subject_pool == NULL) { | |
145 elmpool_free(rdman->geo_pool); | |
146 elmpool_free(rdman->coord_pool); | |
147 elmpool_free(rdman->shnode_pool); | |
148 elmpool_free(rdman->observer_pool); | |
149 return ERR; | |
150 } | |
151 | |
152 rdman->ob_factory.subject_alloc = ob_subject_alloc; | |
153 rdman->ob_factory.subject_free = ob_subject_free; | |
154 rdman->ob_factory.observer_alloc = ob_observer_alloc; | |
155 rdman->ob_factory.observer_free = ob_observer_free; | |
156 rdman->ob_factory.get_parent_subject = ob_get_parent_subject; | |
157 | |
126 rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool); | 158 rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool); |
127 if(rdman->root_coord == NULL) | 159 if(rdman->root_coord == NULL) |
128 redraw_man_destroy(rdman); | 160 redraw_man_destroy(rdman); |
129 rdman->n_coords = 1; | 161 rdman->n_coords = 1; |
130 coord_init(rdman->root_coord, NULL); | 162 coord_init(rdman->root_coord, NULL); |
163 rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, | |
164 rdman->root_coord, | |
165 OBJT_COORD); | |
131 | 166 |
132 rdman->cr = cr; | 167 rdman->cr = cr; |
133 rdman->backend = backend; | 168 rdman->backend = backend; |
134 | 169 |
135 return OK; | 170 return OK; |
137 | 172 |
138 void redraw_man_destroy(redraw_man_t *rdman) { | 173 void redraw_man_destroy(redraw_man_t *rdman) { |
139 elmpool_free(rdman->coord_pool); | 174 elmpool_free(rdman->coord_pool); |
140 elmpool_free(rdman->geo_pool); | 175 elmpool_free(rdman->geo_pool); |
141 elmpool_free(rdman->shnode_pool); | 176 elmpool_free(rdman->shnode_pool); |
177 elmpool_free(rdman->observer_pool); | |
178 elmpool_free(rdman->subject_pool); | |
142 if(rdman->dirty_coords) | 179 if(rdman->dirty_coords) |
143 free(rdman->dirty_coords); | 180 free(rdman->dirty_coords); |
144 if(rdman->dirty_geos) | 181 if(rdman->dirty_geos) |
145 free(rdman->dirty_geos); | 182 free(rdman->dirty_geos); |
146 if(rdman->gen_geos) | 183 if(rdman->gen_geos) |
224 geo = elmpool_elm_alloc(rdman->geo_pool); | 261 geo = elmpool_elm_alloc(rdman->geo_pool); |
225 if(geo == NULL) | 262 if(geo == NULL) |
226 return ERR; | 263 return ERR; |
227 | 264 |
228 geo_init(geo); | 265 geo_init(geo); |
266 geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO); | |
229 | 267 |
230 sh_attach_geo(shape, geo); | 268 sh_attach_geo(shape, geo); |
231 STAILQ_INS_TAIL(rdman->all_geos, geo_t, next, geo); | 269 STAILQ_INS_TAIL(rdman->all_geos, geo_t, next, geo); |
232 rdman->n_geos++; | 270 rdman->n_geos++; |
233 | 271 |
259 * | 297 * |
260 * \todo redraw shape objects that overlaid with removed one. | 298 * \todo redraw shape objects that overlaid with removed one. |
261 */ | 299 */ |
262 int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape) { | 300 int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape) { |
263 STAILQ_REMOVE(rdman->all_geos, geo_t, next, shape->geo); | 301 STAILQ_REMOVE(rdman->all_geos, geo_t, next, shape->geo); |
302 subject_free(&rdman->ob_factory, shape->geo->mouse_event); | |
264 elmpool_elm_free(rdman->geo_pool, shape->geo); | 303 elmpool_elm_free(rdman->geo_pool, shape->geo); |
265 sh_detach_geo(shape); | 304 sh_detach_geo(shape); |
266 rdman->n_geos--; | 305 rdman->n_geos--; |
267 sh_detach_coord(shape); | 306 sh_detach_coord(shape); |
268 return OK; | 307 return OK; |
275 coord = elmpool_elm_alloc(rdman->coord_pool); | 314 coord = elmpool_elm_alloc(rdman->coord_pool); |
276 if(coord == NULL) | 315 if(coord == NULL) |
277 return NULL; | 316 return NULL; |
278 | 317 |
279 coord_init(coord, parent); | 318 coord_init(coord, parent); |
319 coord->mouse_event = subject_new(&rdman->ob_factory, | |
320 coord, | |
321 OBJT_COORD); | |
280 rdman->n_coords++; | 322 rdman->n_coords++; |
281 | 323 |
282 coord->order = ++rdman->next_coord_order; | 324 coord->order = ++rdman->next_coord_order; |
283 if(coord->order == 0) { | 325 if(coord->order == 0) { |
284 rdman->next_coord_order = 0; | 326 rdman->next_coord_order = 0; |
311 | 353 |
312 if(STAILQ_HEAD(coord->children) != NULL) | 354 if(STAILQ_HEAD(coord->children) != NULL) |
313 return ERR; | 355 return ERR; |
314 | 356 |
315 STAILQ_REMOVE(parent->children, coord_t, sibling, coord); | 357 STAILQ_REMOVE(parent->children, coord_t, sibling, coord); |
358 subject_free(&rdman->ob_factory, coord->mouse_event); | |
316 elmpool_elm_free(rdman->coord_pool, coord); | 359 elmpool_elm_free(rdman->coord_pool, coord); |
317 rdman->n_coords--; | 360 rdman->n_coords--; |
318 | 361 |
319 return OK; | 362 return OK; |
320 } | 363 } |
855 * functions: | 898 * functions: |
856 * - redraw all | 899 * - redraw all |
857 * - redraw changed | 900 * - redraw changed |
858 */ | 901 */ |
859 | 902 |
903 /* Implment factory and strategy functions for observers and subjects. | |
904 */ | |
905 static subject_t *ob_subject_alloc(ob_factory_t *factory) { | |
906 redraw_man_t *rdman; | |
907 subject_t *subject; | |
908 | |
909 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); | |
910 subject = elmpool_elm_alloc(rdman->subject_pool); | |
911 | |
912 return subject; | |
913 } | |
914 | |
915 static void ob_subject_free(ob_factory_t *factory, subject_t *subject) { | |
916 redraw_man_t *rdman; | |
917 | |
918 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); | |
919 elmpool_elm_free(rdman->subject_pool, subject); | |
920 } | |
921 | |
922 static observer_t *ob_observer_alloc(ob_factory_t *factory) { | |
923 redraw_man_t *rdman; | |
924 observer_t *observer; | |
925 | |
926 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); | |
927 observer = elmpool_elm_alloc(rdman->observer_pool); | |
928 | |
929 return observer; | |
930 } | |
931 | |
932 static void ob_observer_free(ob_factory_t *factory, observer_t *observer) { | |
933 redraw_man_t *rdman; | |
934 | |
935 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); | |
936 elmpool_elm_free(rdman->observer_pool, observer); | |
937 } | |
938 | |
939 static subject_t *ob_get_parent_subject(ob_factory_t *factory, | |
940 subject_t *cur_subject) { | |
941 redraw_man_t *rdman; | |
942 coord_t *coord; | |
943 geo_t *geo; | |
944 subject_t *parent; | |
945 | |
946 rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); | |
947 switch(cur_subject->obj_type) { | |
948 case OBJT_GEO: | |
949 geo = (geo_t *)cur_subject->obj; | |
950 coord = geo->shape->coord; | |
951 parent = coord->mouse_event; | |
952 break; | |
953 case OBJT_COORD: | |
954 coord = (coord_t *)cur_subject->obj; | |
955 coord = coord->parent; | |
956 parent = coord->mouse_event; | |
957 break; | |
958 default: | |
959 parent = NULL; | |
960 break; | |
961 } | |
962 | |
963 return parent; | |
964 } | |
965 | |
860 #ifdef UNITTEST | 966 #ifdef UNITTEST |
967 /* Test cases */ | |
861 | 968 |
862 #include <CUnit/Basic.h> | 969 #include <CUnit/Basic.h> |
863 #include "paint.h" | 970 #include "paint.h" |
864 | 971 |
865 struct _sh_dummy { | 972 struct _sh_dummy { |