Parent Directory | Revision Log
Various adjustments
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 | #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 | /* 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 | GdkPixbuf *pixbuf = icon_get(CUSTOM_ICON_TYPE, celltype->type>>8); |
235 | |
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 | GdkPixbuf *pixbuf = icon_get(CUSTOM_ICON_TYPE, celltype->type>>8); |
274 | 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 | /* just a note, nothing else */ |
301 | GdkPixbuf *addon = NULL; |
302 | if((celltype->type & 7) == 4) // only note is set |
303 | addon = icon_get(CUSTOM_ICON_TYPE, 13); |
304 | if((celltype->type & 7) == 5) // only note and override are set |
305 | addon = icon_get(CUSTOM_ICON_TYPE, 11); |
306 | if(celltype->type & 2) // solved is set |
307 | addon = icon_get(CUSTOM_ICON_TYPE, 12); |
308 | |
309 | /* if override (and not found) is set */ |
310 | if(addon) { |
311 | gdk_cairo_set_source_pixbuf(cr, addon, |
312 | all_rect.x + (all_rect.width - pix_width)/2, all_rect.y); |
313 | gdk_cairo_rectangle(cr, &draw_rect); |
314 | cairo_fill(cr); |
315 | } |
316 | |
317 | cairo_destroy(cr); |
318 | } |