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