Contents of /trunk/src/custom_size_renderer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 185 - (hide 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 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_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 harbaum 185 PangoLayout *layout = new_layout(widget, _(size_str[cellsize->size]));
261 harbaum 1
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 harbaum 185 PangoLayout *layout = new_layout(widget, _(size_str[cellsize->size]));
331 harbaum 1 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     }