Parent Directory | Revision Log
Map/cache icon handling
1 | harbaum | 1 | /* |
2 | * Copyright (C) 2008 Till Harbaum <till@harbaum.org>. | ||
3 | * | ||
4 | * This file is part of GPXView. | ||
5 | * | ||
6 | * GPXView is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation, either version 3 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GPXView is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with GPXView. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include "gpxview.h" | ||
21 | #include "custom_type_renderer.h" | ||
22 | |||
23 | harbaum | 189 | #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5) |
24 | #define CUSTOM_ICON_TYPE ICON_CACHE_TYPE_1_5X | ||
25 | #else | ||
26 | #define CUSTOM_ICON_TYPE ICON_CACHE_TYPE | ||
27 | #endif | ||
28 | |||
29 | harbaum | 1 | /* http://scentric.net/tutorial/sec-custom-cell-renderers.html */ |
30 | /* https://stage.maemo.org/svn/maemo/projects/haf/trunk/gtk+/gtk/gtkcellrendererpixbuf.c */ | ||
31 | /* https://stage.maemo.org/svn/maemo/projects/haf/trunk/gtk+/gtk/gtkcellrenderertext.c */ | ||
32 | |||
33 | /* This is based mainly on GtkCellRendererProgress | ||
34 | * in GAIM, written and (c) 2002 by Sean Egan | ||
35 | * (Licensed under the GPL), which in turn is | ||
36 | * based on Gtk's GtkCellRenderer[Text|Toggle|Pixbuf] | ||
37 | * implementation by Jonathan Blandford */ | ||
38 | |||
39 | /* Some boring function declarations: GObject type system stuff */ | ||
40 | |||
41 | static void custom_cell_renderer_type_init (CustomCellRendererType *celltype); | ||
42 | static void custom_cell_renderer_type_class_init (CustomCellRendererTypeClass *klass); | ||
43 | static void custom_cell_renderer_type_get_property (GObject *object, | ||
44 | guint param_id, | ||
45 | GValue *value, | ||
46 | GParamSpec *pspec); | ||
47 | static void custom_cell_renderer_type_set_property (GObject *object, | ||
48 | guint param_id, | ||
49 | const GValue *value, | ||
50 | GParamSpec *pspec); | ||
51 | static void custom_cell_renderer_type_finalize (GObject *gobject); | ||
52 | |||
53 | |||
54 | /* These functions are the heart of our custom cell renderer: */ | ||
55 | |||
56 | static void custom_cell_renderer_type_get_size (GtkCellRenderer *cell, | ||
57 | GtkWidget *widget, | ||
58 | GdkRectangle *cell_area, | ||
59 | gint *x_offset, | ||
60 | gint *y_offset, | ||
61 | gint *width, | ||
62 | gint *height); | ||
63 | |||
64 | static void custom_cell_renderer_type_render (GtkCellRenderer *cell, | ||
65 | GdkWindow *window, | ||
66 | GtkWidget *widget, | ||
67 | GdkRectangle *background_area, | ||
68 | GdkRectangle *cell_area, | ||
69 | GdkRectangle *expose_area, | ||
70 | guint flags); | ||
71 | |||
72 | |||
73 | enum { PROP_TYPE = 1, }; | ||
74 | |||
75 | static gpointer parent_class; | ||
76 | |||
77 | GType custom_cell_renderer_type_get_type (void) { | ||
78 | static GType cell_type_type = 0; | ||
79 | |||
80 | if (cell_type_type == 0) | ||
81 | { | ||
82 | static const GTypeInfo cell_type_info = | ||
83 | { | ||
84 | sizeof (CustomCellRendererTypeClass), | ||
85 | NULL, /* base_init */ | ||
86 | NULL, /* base_finalize */ | ||
87 | (GClassInitFunc) custom_cell_renderer_type_class_init, | ||
88 | NULL, /* class_finalize */ | ||
89 | NULL, /* class_data */ | ||
90 | sizeof (CustomCellRendererType), | ||
91 | 0, /* n_preallocs */ | ||
92 | (GInstanceInitFunc) custom_cell_renderer_type_init, | ||
93 | }; | ||
94 | |||
95 | /* Derive from GtkCellRenderer */ | ||
96 | cell_type_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, | ||
97 | "CustomCellRendererType", | ||
98 | &cell_type_info, | ||
99 | 0); | ||
100 | } | ||
101 | return cell_type_type; | ||
102 | } | ||
103 | |||
104 | |||
105 | /*************************************************************************** | ||
106 | * | ||
107 | * custom_cell_renderer_type_init: set some default properties of the | ||
108 | * parent (GtkCellRenderer). | ||
109 | * | ||
110 | ***************************************************************************/ | ||
111 | |||
112 | static void | ||
113 | custom_cell_renderer_type_init (CustomCellRendererType *cellrenderertype) | ||
114 | { | ||
115 | GTK_CELL_RENDERER(cellrenderertype)->mode = GTK_CELL_RENDERER_MODE_INERT; | ||
116 | GTK_CELL_RENDERER(cellrenderertype)->xpad = 0; | ||
117 | GTK_CELL_RENDERER(cellrenderertype)->ypad = 0; | ||
118 | } | ||
119 | |||
120 | |||
121 | /*************************************************************************** | ||
122 | * | ||
123 | * custom_cell_renderer_type_class_init: | ||
124 | * | ||
125 | * set up our own get_property and set_property functions, and | ||
126 | * override the parent's functions that we need to implement. | ||
127 | * And make our new "size" property known to the type system. | ||
128 | * If you want cells that can be activated on their own (ie. not | ||
129 | * just the whole row selected) or cells that are editable, you | ||
130 | * will need to override 'activate' and 'start_editing' as well. | ||
131 | * | ||
132 | ***************************************************************************/ | ||
133 | |||
134 | static void | ||
135 | custom_cell_renderer_type_class_init (CustomCellRendererTypeClass *klass) { | ||
136 | GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(klass); | ||
137 | GObjectClass *object_class = G_OBJECT_CLASS(klass); | ||
138 | |||
139 | parent_class = g_type_class_peek_parent (klass); | ||
140 | object_class->finalize = custom_cell_renderer_type_finalize; | ||
141 | |||
142 | /* Hook up functions to set and get our | ||
143 | * custom cell renderer properties */ | ||
144 | object_class->get_property = custom_cell_renderer_type_get_property; | ||
145 | object_class->set_property = custom_cell_renderer_type_set_property; | ||
146 | |||
147 | /* Override the two crucial functions that are the heart | ||
148 | * of a cell renderer in the parent class */ | ||
149 | cell_class->get_size = custom_cell_renderer_type_get_size; | ||
150 | cell_class->render = custom_cell_renderer_type_render; | ||
151 | |||
152 | /* Install our very own properties */ | ||
153 | g_object_class_install_property (object_class, PROP_TYPE, | ||
154 | g_param_spec_int ("type", "Type", "Container type", -256, | ||
155 | (CACHE_TYPE_MAX<<8)+255, 0, G_PARAM_READWRITE)); | ||
156 | } | ||
157 | |||
158 | |||
159 | /*************************************************************************** | ||
160 | * | ||
161 | * custom_cell_renderer_type_finalize: free any resources here | ||
162 | * | ||
163 | ***************************************************************************/ | ||
164 | |||
165 | static void custom_cell_renderer_type_finalize (GObject *object) { | ||
166 | (* G_OBJECT_CLASS (parent_class)->finalize) (object); | ||
167 | } | ||
168 | |||
169 | |||
170 | /*************************************************************************** | ||
171 | * | ||
172 | * custom_cell_renderer_type_get_property: as it says | ||
173 | * | ||
174 | ***************************************************************************/ | ||
175 | |||
176 | static void | ||
177 | custom_cell_renderer_type_get_property (GObject *object, | ||
178 | guint param_id, | ||
179 | GValue *value, | ||
180 | GParamSpec *psec) { | ||
181 | CustomCellRendererType *celltype = CUSTOM_CELL_RENDERER_TYPE(object); | ||
182 | |||
183 | switch (param_id) { | ||
184 | case PROP_TYPE: | ||
185 | g_value_set_int(value, celltype->type); | ||
186 | break; | ||
187 | |||
188 | default: | ||
189 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, psec); | ||
190 | break; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | |||
195 | /*************************************************************************** | ||
196 | * | ||
197 | * custom_cell_renderer_type_set_property: as it says | ||
198 | * | ||
199 | ***************************************************************************/ | ||
200 | |||
201 | static void | ||
202 | custom_cell_renderer_type_set_property (GObject *object, | ||
203 | guint param_id, | ||
204 | const GValue *value, | ||
205 | GParamSpec *pspec) { | ||
206 | CustomCellRendererType *celltype = CUSTOM_CELL_RENDERER_TYPE (object); | ||
207 | |||
208 | switch (param_id) { | ||
209 | case PROP_TYPE: | ||
210 | celltype->type = g_value_get_int(value); | ||
211 | break; | ||
212 | |||
213 | default: | ||
214 | G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); | ||
215 | break; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /*************************************************************************** | ||
220 | * | ||
221 | * custom_cell_renderer_type_new: return a new cell renderer instance | ||
222 | * | ||
223 | ***************************************************************************/ | ||
224 | |||
225 | GtkCellRenderer *custom_cell_renderer_type_new (void) { | ||
226 | return g_object_new(CUSTOM_TYPE_CELL_RENDERER_TYPE, NULL); | ||
227 | } | ||
228 | |||
229 | static void | ||
230 | custom_cell_renderer_type_get_size (GtkCellRenderer *cell, | ||
231 | GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, | ||
232 | gint *y_offset, gint *width, gint *height) { | ||
233 | CustomCellRendererType *celltype = CUSTOM_CELL_RENDERER_TYPE (cell); | ||
234 | harbaum | 189 | GdkPixbuf *pixbuf = icon_get(CUSTOM_ICON_TYPE, celltype->type>>8); |
235 | harbaum | 1 | |
236 | if(!pixbuf) return; | ||
237 | |||
238 | gint calc_width = (gint) gdk_pixbuf_get_width(pixbuf); | ||
239 | gint calc_height = (gint) gdk_pixbuf_get_height(pixbuf); | ||
240 | |||
241 | if (x_offset) *x_offset = 0; | ||
242 | if (y_offset) *y_offset = 0; | ||
243 | |||
244 | if (cell_area) { | ||
245 | if (x_offset) | ||
246 | *x_offset = (cell_area->width - calc_width)/2; | ||
247 | |||
248 | if (y_offset) | ||
249 | *y_offset = (cell_area->height - calc_height)/2; | ||
250 | } | ||
251 | |||
252 | if (width) *width = calc_width; | ||
253 | if (height) *height = calc_height; | ||
254 | } | ||
255 | |||
256 | |||
257 | /*************************************************************************** | ||
258 | * | ||
259 | * custom_cell_renderer_type_render: crucial - do the rendering. | ||
260 | * | ||
261 | ***************************************************************************/ | ||
262 | |||
263 | static void | ||
264 | custom_cell_renderer_type_render (GtkCellRenderer *cell, | ||
265 | GdkWindow *window, | ||
266 | GtkWidget *widget, | ||
267 | GdkRectangle *background_area, | ||
268 | GdkRectangle *cell_area, | ||
269 | GdkRectangle *expose_area, | ||
270 | guint flags) | ||
271 | { | ||
272 | CustomCellRendererType *celltype = CUSTOM_CELL_RENDERER_TYPE (cell); | ||
273 | harbaum | 189 | GdkPixbuf *pixbuf = icon_get(CUSTOM_ICON_TYPE, celltype->type>>8); |
274 | harbaum | 1 | GdkRectangle all_rect; |
275 | GdkRectangle draw_rect; | ||
276 | |||
277 | if(!pixbuf) return; | ||
278 | |||
279 | gint pix_width = gdk_pixbuf_get_width(pixbuf); | ||
280 | |||
281 | custom_cell_renderer_type_get_size (cell, widget, cell_area, | ||
282 | &all_rect.x, &all_rect.y, | ||
283 | &all_rect.width, &all_rect.height); | ||
284 | |||
285 | all_rect.x += cell_area->x; | ||
286 | all_rect.y += cell_area->y; | ||
287 | |||
288 | if (!gdk_rectangle_intersect (cell_area, &all_rect, &draw_rect) || | ||
289 | !gdk_rectangle_intersect (expose_area, &draw_rect, &draw_rect)) | ||
290 | return; | ||
291 | |||
292 | /* draw the bitmap */ | ||
293 | cairo_t *cr = gdk_cairo_create(window); | ||
294 | |||
295 | gdk_cairo_set_source_pixbuf(cr, pixbuf, | ||
296 | all_rect.x + (all_rect.width - pix_width)/2, all_rect.y); | ||
297 | gdk_cairo_rectangle(cr, &draw_rect); | ||
298 | cairo_fill(cr); | ||
299 | |||
300 | harbaum | 205 | /* add "special" addon. the order of these test results in */ |
301 | /* a priority */ | ||
302 | harbaum | 1 | GdkPixbuf *addon = NULL; |
303 | harbaum | 205 | if(celltype->type & 8) // mine is set |
304 | addon = icon_get(CUSTOM_ICON_TYPE, 14); | ||
305 | else if(celltype->type & 2) // solved is set | ||
306 | addon = icon_get(CUSTOM_ICON_TYPE, 12); | ||
307 | else if(celltype->type & 1) // override is set | ||
308 | addon = icon_get(CUSTOM_ICON_TYPE, 11); | ||
309 | else if(celltype->type & 4) // note is set | ||
310 | harbaum | 189 | addon = icon_get(CUSTOM_ICON_TYPE, 13); |
311 | harbaum | 1 | |
312 | /* if override (and not found) is set */ | ||
313 | if(addon) { | ||
314 | gdk_cairo_set_source_pixbuf(cr, addon, | ||
315 | harbaum | 120 | all_rect.x + (all_rect.width - pix_width)/2, all_rect.y); |
316 | harbaum | 1 | gdk_cairo_rectangle(cr, &draw_rect); |
317 | cairo_fill(cr); | ||
318 | } | ||
319 | |||
320 | cairo_destroy(cr); | ||
321 | } |