Mercurial > MadButterfly
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 } |