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 {