comparison src/event.c @ 30:e06a4a667ce2

Accept mouse/pointer event and hint the shape that the pointer is over. - add find_shape_at_pos()
author Thinker K.F. Li <thinker@branda.to>
date Tue, 05 Aug 2008 12:40:45 +0800
parents
children 69c8e264890d
comparison
equal deleted inserted replaced
29:f56c96b035a8 30:e06a4a667ce2
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <cairo.h>
4 #include "mb_types.h"
5 #include "redraw_man.h"
6 #include "shapes.h"
7
8 #define OK 0
9 #define ERR -1
10
11
12 static int extend_memblk(void **buf, int o_size, int n_size) {
13 void *new_buf;
14
15 new_buf = realloc(*buf, n_size);
16 if(new_buf == NULL)
17 return ERR;
18
19 *buf = new_buf;
20
21 return OK;
22 }
23
24 /*! \brief Add a geo_t object to general geo list.
25 *
26 * General geo list can use to temporary keep a list of geo_t
27 * objects for any purpose. It supposed to be reused by
28 * different modules that need to select part of geo_t objects
29 * from a redraw manager.
30 */
31 static int add_gen_geo(redraw_man_t *rdman, geo_t *geo) {
32 int max_gen_geos;
33 int r;
34
35 if(rdman->n_gen_geos >= rdman->max_gen_geos) {
36 max_gen_geos = rdman->n_geos;
37 r = extend_memblk((void **)&rdman->gen_geos,
38 sizeof(geo_t *) * rdman->n_gen_geos,
39 sizeof(geo_t *) * max_gen_geos);
40 if(r != OK)
41 return ERR;
42 rdman->max_gen_geos = max_gen_geos;
43 }
44
45 rdman->gen_geos[rdman->n_gen_geos++] = geo;
46 return OK;
47 }
48
49 static int collect_shapes_at_point(redraw_man_t *rdman,
50 co_aix x, co_aix y) {
51 geo_t *geo;
52 int r;
53
54 r = rdman_force_clean(rdman);
55 if(r != OK)
56 return ERR;
57
58 rdman->n_gen_geos = 0;
59
60 for(geo = STAILQ_HEAD(rdman->all_geos);
61 geo != NULL;
62 geo = STAILQ_NEXT(geo_t, next, geo)) {
63 if(geo_pos_is_in(geo, x, y)) {
64 r = add_gen_geo(rdman, geo);
65 if(r != OK)
66 return ERR;
67 }
68 }
69
70 return OK;
71 }
72
73 static void draw_shape_path(shape_t *shape, cairo_t *cr) {
74 switch(shape->sh_type) {
75 case SHT_PATH:
76 sh_path_draw(shape, cr);
77 break;
78 case SHT_TEXT:
79 sh_text_draw(shape, cr);
80 break;
81 }
82 }
83
84 static geo_t *find_pos_in_geo(redraw_man_t *rdman,
85 co_aix x, co_aix y, int *in_stroke) {
86 geo_t *geo;
87 geo_t **geos;
88 shape_t *shape;
89 cairo_t *cr;
90 int i;
91
92 geos = rdman->gen_geos;
93 cr = rdman->cr;
94 for(i = rdman->n_gen_geos - 1; i >= 0; i--) {
95 geo = geos[i];
96 shape = geo->shape;
97 draw_shape_path(shape, cr);
98 if(shape->fill) {
99 if(cairo_in_fill(cr, x, y)) {
100 *in_stroke = 0;
101 cairo_new_path(cr);
102 return geo;
103 }
104 }
105 if(shape->stroke) {
106 if(cairo_in_stroke(cr, x, y)) {
107 *in_stroke = 1;
108 cairo_new_path(cr);
109 return geo;
110 }
111 }
112 }
113
114 return NULL;
115 }
116
117 shape_t *find_shape_at_pos(redraw_man_t *rdman,
118 co_aix x, co_aix y, int *in_stroke) {
119 geo_t *geo;
120 int r;
121
122 r = collect_shapes_at_point(rdman, x, y);
123 if(r != OK)
124 return NULL;
125
126 geo = find_pos_in_geo(rdman, x, y, in_stroke);
127 if(geo == NULL)
128 return NULL;
129
130 return geo->shape;
131 }