Contents of /trunk/src/custom_size_renderer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 185 - (show annotations)
Sat Nov 14 16:55:33 2009 UTC (14 years, 6 months ago) by harbaum
File MIME type: text/plain
File size: 13579 byte(s)
All icons redone
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_size_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_size_init (CustomCellRendererSize *cellsize);
36 static void custom_cell_renderer_size_class_init (CustomCellRendererSizeClass *klass);
37 static void custom_cell_renderer_size_get_property (GObject *object,
38 guint param_id,
39 GValue *value,
40 GParamSpec *pspec);
41 static void custom_cell_renderer_size_set_property (GObject *object,
42 guint param_id,
43 const GValue *value,
44 GParamSpec *pspec);
45 static void custom_cell_renderer_size_finalize (GObject *gobject);
46
47
48 /* These functions are the heart of our custom cell renderer: */
49
50 static void custom_cell_renderer_size_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_size_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_SIZE = 1, };
68
69 static const char *size_str[] = {
70 "Regular", "Small", "Micro", "Other", "Not chosen", "Large", "Virtual"
71 };
72
73 static gpointer parent_class;
74
75 GType custom_cell_renderer_size_get_type (void) {
76 static GType cell_size_type = 0;
77
78 if (cell_size_type == 0)
79 {
80 static const GTypeInfo cell_size_info =
81 {
82 sizeof (CustomCellRendererSizeClass),
83 NULL, /* base_init */
84 NULL, /* base_finalize */
85 (GClassInitFunc) custom_cell_renderer_size_class_init,
86 NULL, /* class_finalize */
87 NULL, /* class_data */
88 sizeof (CustomCellRendererSize),
89 0, /* n_preallocs */
90 (GInstanceInitFunc) custom_cell_renderer_size_init,
91 };
92
93 /* Derive from GtkCellRenderer */
94 cell_size_type = g_type_register_static (GTK_TYPE_CELL_RENDERER,
95 "CustomCellRendererSize",
96 &cell_size_info,
97 0);
98 }
99 return cell_size_type;
100 }
101
102
103 /***************************************************************************
104 *
105 * custom_cell_renderer_size_init: set some default properties of the
106 * parent (GtkCellRenderer).
107 *
108 ***************************************************************************/
109
110 static void
111 custom_cell_renderer_size_init (CustomCellRendererSize *cellrenderersize)
112 {
113 GTK_CELL_RENDERER(cellrenderersize)->mode = GTK_CELL_RENDERER_MODE_INERT;
114 GTK_CELL_RENDERER(cellrenderersize)->xpad = 0;
115 GTK_CELL_RENDERER(cellrenderersize)->ypad = 0;
116 }
117
118
119 /***************************************************************************
120 *
121 * custom_cell_renderer_size_class_init:
122 *
123 * set up our own get_property and set_property functions, and
124 * override the parent's functions that we need to implement.
125 * And make our new "size" property known to the type system.
126 * If you want cells that can be activated on their own (ie. not
127 * just the whole row selected) or cells that are editable, you
128 * will need to override 'activate' and 'start_editing' as well.
129 *
130 ***************************************************************************/
131
132 static void
133 custom_cell_renderer_size_class_init (CustomCellRendererSizeClass *klass) {
134 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(klass);
135 GObjectClass *object_class = G_OBJECT_CLASS(klass);
136
137 parent_class = g_type_class_peek_parent (klass);
138 object_class->finalize = custom_cell_renderer_size_finalize;
139
140 /* Hook up functions to set and get our
141 * custom cell renderer properties */
142 object_class->get_property = custom_cell_renderer_size_get_property;
143 object_class->set_property = custom_cell_renderer_size_set_property;
144
145 /* Override the two crucial functions that are the heart
146 * of a cell renderer in the parent class */
147 cell_class->get_size = custom_cell_renderer_size_get_size;
148 cell_class->render = custom_cell_renderer_size_render;
149
150 /* Install our very own properties */
151 g_object_class_install_property (object_class, PROP_SIZE,
152 g_param_spec_int ("size", "Size", "Container size", -1, CACHE_CONT_MAX, 0,
153 G_PARAM_READWRITE));
154 }
155
156
157 /***************************************************************************
158 *
159 * custom_cell_renderer_size_finalize: free any resources here
160 *
161 ***************************************************************************/
162
163 static void custom_cell_renderer_size_finalize (GObject *object) {
164 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
165 }
166
167
168 /***************************************************************************
169 *
170 * custom_cell_renderer_size_get_property: as it says
171 *
172 ***************************************************************************/
173
174 static void
175 custom_cell_renderer_size_get_property (GObject *object,
176 guint param_id,
177 GValue *value,
178 GParamSpec *psec) {
179 CustomCellRendererSize *cellsize = CUSTOM_CELL_RENDERER_SIZE(object);
180
181 switch (param_id) {
182 case PROP_SIZE:
183 g_value_set_int(value, cellsize->size);
184 break;
185
186 default:
187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, psec);
188 break;
189 }
190 }
191
192
193 /***************************************************************************
194 *
195 * custom_cell_renderer_size_set_property: as it says
196 *
197 ***************************************************************************/
198
199 static void
200 custom_cell_renderer_size_set_property (GObject *object,
201 guint param_id,
202 const GValue *value,
203 GParamSpec *pspec) {
204 CustomCellRendererSize *cellsize = CUSTOM_CELL_RENDERER_SIZE (object);
205
206 switch (param_id) {
207 case PROP_SIZE:
208 cellsize->size = g_value_get_int(value);
209 break;
210
211 default:
212 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
213 break;
214 }
215 }
216
217 /***************************************************************************
218 *
219 * custom_cell_renderer_size_new: return a new cell renderer instance
220 *
221 ***************************************************************************/
222
223 GtkCellRenderer *custom_cell_renderer_size_new (void) {
224 return g_object_new(CUSTOM_TYPE_CELL_RENDERER_SIZE, NULL);
225 }
226
227 static PangoLayout *new_layout(GtkWidget *widget, const char *str) {
228 #ifndef USE_MAEMO
229 return gtk_widget_create_pango_layout(widget, str);
230 #else
231 #ifdef USE_PANNABLE_AREA
232 char *tmp = g_strdup_printf("<span size=\"x-small\">%s</span>", str);
233 #else
234 char *tmp = g_strdup_printf("<span size=\"xx-small\">%s</span>", str);
235 #endif
236 PangoLayout *layout = gtk_widget_create_pango_layout(widget, NULL);
237 pango_layout_set_markup(layout, tmp, strlen(tmp));
238 g_free(tmp);
239 return layout;
240 #endif
241 }
242
243 static void
244 custom_cell_renderer_size_get_size (GtkCellRenderer *cell,
245 GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset,
246 gint *y_offset, gint *width, gint *height) {
247 GdkPixbuf *pixbuf = NULL;
248 CustomCellRendererSize *cellsize = CUSTOM_CELL_RENDERER_SIZE (cell);
249
250 if(cellsize->size < 0) return;
251
252 pixbuf = icon_get(ICON_CACHE_SIZE, cellsize->size);
253 if (!pixbuf) return;
254
255 pixbuf = icon_get(ICON_CACHE_SIZE, cellsize->size);
256 gint calc_width = (gint) gdk_pixbuf_get_width(pixbuf);
257 gint calc_height = (gint) gdk_pixbuf_get_height(pixbuf);
258
259 /* do the text */
260 PangoLayout *layout = new_layout(widget, _(size_str[cellsize->size]));
261
262 PangoRectangle rect;
263 pango_layout_get_pixel_extents(layout, NULL, &rect);
264 g_object_unref (layout);
265
266 calc_height += rect.height;
267 if(rect.width > calc_width) calc_width = rect.width;
268
269 // printf("req size = %d*%d\n", calc_width, calc_height);
270
271 if (x_offset) *x_offset = 0;
272 if (y_offset) *y_offset = 0;
273
274 if (cell_area) {
275 // printf("cell size = %d*%d\n", cell_area->width, cell_area->height);
276
277 if (x_offset)
278 *x_offset = (cell_area->width - calc_width)/2;
279
280 if (y_offset)
281 *y_offset = (cell_area->height - calc_height)/2;
282 }
283
284 if (width) *width = calc_width;
285 if (height) *height = calc_height;
286 }
287
288
289 /***************************************************************************
290 *
291 * custom_cell_renderer_size_render: crucial - do the rendering.
292 *
293 ***************************************************************************/
294
295 static void
296 custom_cell_renderer_size_render (GtkCellRenderer *cell,
297 GdkWindow *window,
298 GtkWidget *widget,
299 GdkRectangle *background_area,
300 GdkRectangle *cell_area,
301 GdkRectangle *expose_area,
302 guint flags)
303 {
304 CustomCellRendererSize *cellsize = CUSTOM_CELL_RENDERER_SIZE (cell);
305 GdkPixbuf *pixbuf = NULL;
306 GdkRectangle all_rect;
307 GdkRectangle draw_rect;
308
309 if(cellsize->size < 0) return;
310
311 pixbuf = icon_get(ICON_CACHE_SIZE, cellsize->size);
312 if (!pixbuf) return;
313
314 gint pix_width = gdk_pixbuf_get_width(pixbuf);
315 gint pix_height = gdk_pixbuf_get_height(pixbuf);
316
317
318 custom_cell_renderer_size_get_size (cell, widget, cell_area,
319 &all_rect.x, &all_rect.y,
320 &all_rect.width, &all_rect.height);
321
322 all_rect.x += cell_area->x;
323 all_rect.y += cell_area->y;
324
325 if (!gdk_rectangle_intersect (cell_area, &all_rect, &draw_rect) ||
326 !gdk_rectangle_intersect (expose_area, &draw_rect, &draw_rect))
327 return;
328
329 /* do the text */
330 PangoLayout *layout = new_layout(widget, _(size_str[cellsize->size]));
331 PangoRectangle rect;
332 pango_layout_get_pixel_extents(layout, NULL, &rect);
333 // printf("cell width = %d, text width = %d\n", all_rect.width, rect.width);
334
335 int yoff = (all_rect.height - (rect.height + pix_height))/2;
336
337 gtk_paint_layout(widget->style, window, GTK_STATE_NORMAL,
338 TRUE, expose_area, widget, "cellrenderersize",
339 all_rect.x + (all_rect.width - rect.width)/2,
340 all_rect.y + yoff,
341 layout);
342
343 g_object_unref (layout);
344
345 /* draw the bitmap */
346 cairo_t *cr = gdk_cairo_create(window);
347 gdk_cairo_set_source_pixbuf(cr, pixbuf,
348 all_rect.x + (all_rect.width - pix_width)/2,
349 all_rect.y + rect.height + yoff);
350 gdk_cairo_rectangle(cr, &draw_rect);
351 cairo_fill(cr);
352 cairo_destroy(cr);
353 }