comparison src/cellrenderericon.c @ 9:d907d608745f

Sync to GQview 1.5.9 release. ######## DO NOT BASE ENHANCEMENTS OR TRANSLATION UPDATES ON CODE IN THIS CVS! This CVS is never up to date with current development and is provided solely for reference purposes, please use the latest official release package when making any changes or translation updates. ########
author gqview
date Sat, 26 Feb 2005 00:13:35 +0000
parents
children 4b2d7f9af171
comparison
equal deleted inserted replaced
8:e0d0593d519e 9:d907d608745f
1 /* cellrenderericon.c, based on:
2 *
3 * gtkcellrendererpixbuf.c
4 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22 #include <stdlib.h>
23 #include "cellrenderericon.h"
24 #include "intl.h"
25
26
27 #define FIXED_ICON_SIZE_MAX 512
28
29 static void gqv_cell_renderer_icon_get_property(GObject *object,
30 guint param_id,
31 GValue *value,
32 GParamSpec *pspec);
33 static void gqv_cell_renderer_icon_set_property(GObject *object,
34 guint param_id,
35 const GValue *value,
36 GParamSpec *pspec);
37 static void gqv_cell_renderer_icon_init(GQvCellRendererIcon *celltext);
38 static void gqv_cell_renderer_icon_class_init(GQvCellRendererIconClass *class);
39 static void gqv_cell_renderer_icon_finalize(GObject *object);
40 static void gqv_cell_renderer_icon_get_size(GtkCellRenderer *cell,
41 GtkWidget *widget,
42 GdkRectangle *rectangle,
43 gint *x_offset,
44 gint *y_offset,
45 gint *width,
46 gint *height);
47 static void gqv_cell_renderer_icon_render(GtkCellRenderer *cell,
48 GdkWindow *window,
49 GtkWidget *widget,
50 GdkRectangle *background_area,
51 GdkRectangle *cell_area,
52 GdkRectangle *expose_area,
53 GtkCellRendererState flags);
54
55
56 enum {
57 PROP_ZERO,
58 PROP_PIXBUF,
59 PROP_TEXT,
60 PROP_BACKGROUND_GDK,
61 PROP_FOREGROUND_GDK,
62 PROP_FOCUSED,
63 PROP_FIXED_WIDTH,
64 PROP_FIXED_HEIGHT,
65
66 PROP_BACKGROUND_SET,
67 PROP_FOREGROUND_SET,
68 PROP_SHOW_TEXT
69 };
70
71 static gpointer parent_class;
72
73 GType
74 gqv_cell_renderer_icon_get_type (void)
75 {
76 static GType cell_icon_type = 0;
77
78 if (!cell_icon_type)
79 {
80 static const GTypeInfo cell_icon_info =
81 {
82 sizeof (GQvCellRendererIconClass),
83 NULL, /* base_init */
84 NULL, /* base_finalize */
85 (GClassInitFunc) gqv_cell_renderer_icon_class_init,
86 NULL, /* class_finalize */
87 NULL, /* class_data */
88 sizeof (GQvCellRendererIcon),
89 0, /* n_preallocs */
90 (GInstanceInitFunc) gqv_cell_renderer_icon_init,
91 };
92
93 cell_icon_type = g_type_register_static(GTK_TYPE_CELL_RENDERER,
94 "GQvCellRendererIcon",
95 &cell_icon_info, 0);
96 }
97
98 return cell_icon_type;
99 }
100
101 static void
102 gqv_cell_renderer_icon_init (GQvCellRendererIcon *cellicon)
103 {
104 GTK_CELL_RENDERER(cellicon)->xpad = 2;
105 GTK_CELL_RENDERER(cellicon)->ypad = 2;
106 }
107
108 static void
109 gqv_cell_renderer_icon_class_init (GQvCellRendererIconClass *class)
110 {
111 GObjectClass *object_class = G_OBJECT_CLASS (class);
112 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
113
114 parent_class = g_type_class_peek_parent (class);
115
116 object_class->finalize = gqv_cell_renderer_icon_finalize;
117
118 object_class->get_property = gqv_cell_renderer_icon_get_property;
119 object_class->set_property = gqv_cell_renderer_icon_set_property;
120
121 cell_class->get_size = gqv_cell_renderer_icon_get_size;
122 cell_class->render = gqv_cell_renderer_icon_render;
123
124 g_object_class_install_property(object_class,
125 PROP_PIXBUF,
126 g_param_spec_object("pixbuf",
127 _("Pixbuf Object"),
128 _("The pixbuf to render"),
129 GDK_TYPE_PIXBUF,
130 G_PARAM_READWRITE));
131
132 g_object_class_install_property(object_class,
133 PROP_TEXT,
134 g_param_spec_string("text",
135 _("Text"),
136 _("Text to render"),
137 NULL,
138 G_PARAM_READWRITE));
139
140 g_object_class_install_property(object_class,
141 PROP_BACKGROUND_GDK,
142 g_param_spec_boxed("background_gdk",
143 _("Background color"),
144 _("Background color as a GdkColor"),
145 GDK_TYPE_COLOR,
146 G_PARAM_READWRITE));
147
148 g_object_class_install_property(object_class,
149 PROP_FOREGROUND_GDK,
150 g_param_spec_boxed("foreground_gdk",
151 _("Foreground color"),
152 _("Foreground color as a GdkColor"),
153 GDK_TYPE_COLOR,
154 G_PARAM_READWRITE));
155
156 g_object_class_install_property(object_class,
157 PROP_FOCUSED,
158 g_param_spec_boolean ("has_focus",
159 _("Focus"),
160 _("Draw focus indicator"),
161 FALSE,
162 G_PARAM_READWRITE));
163
164 g_object_class_install_property(object_class,
165 PROP_FIXED_WIDTH,
166 g_param_spec_int("fixed_width",
167 _("Fixed width"),
168 _("Width of cell"),
169 -1, FIXED_ICON_SIZE_MAX,
170 -1,
171 G_PARAM_READWRITE));
172
173 g_object_class_install_property(object_class,
174 PROP_FIXED_HEIGHT,
175 g_param_spec_int("fixed_height",
176 _("Fixed height"),
177 _("Height of icon excluding text"),
178 -1, FIXED_ICON_SIZE_MAX,
179 -1,
180 G_PARAM_READWRITE));
181
182 g_object_class_install_property(object_class,
183 PROP_BACKGROUND_SET,
184 g_param_spec_boolean("background_set",
185 _("Background set"),
186 _("Whether this tag affects the background color"),
187 FALSE,
188 G_PARAM_READWRITE));
189
190 g_object_class_install_property(object_class,
191 PROP_FOREGROUND_SET,
192 g_param_spec_boolean ("foreground_set",
193 _("Foreground set"),
194 _("Whether this tag affects the foreground color"),
195 FALSE,
196 G_PARAM_READWRITE));
197
198 g_object_class_install_property(object_class,
199 PROP_SHOW_TEXT,
200 g_param_spec_boolean("show_text",
201 _("Show text"),
202 _("Whether the text is displayed"),
203 TRUE,
204 G_PARAM_READWRITE));
205 }
206
207 static void
208 gqv_cell_renderer_icon_finalize (GObject *object)
209 {
210 GQvCellRendererIcon *cellicon = GQV_CELL_RENDERER_ICON (object);
211
212 if (cellicon->pixbuf) g_object_unref (cellicon->pixbuf);
213
214 g_free(cellicon->text);
215
216 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
217 }
218
219 static void
220 gqv_cell_renderer_icon_get_property(GObject *object,
221 guint param_id,
222 GValue *value,
223 GParamSpec *pspec)
224 {
225 GQvCellRendererIcon *cellicon = GQV_CELL_RENDERER_ICON (object);
226
227 switch (param_id)
228 {
229 case PROP_PIXBUF:
230 g_value_set_object(value,
231 cellicon->pixbuf ? G_OBJECT (cellicon->pixbuf) : NULL);
232 break;
233 case PROP_TEXT:
234 g_value_set_string (value, cellicon->text);
235 break;
236 case PROP_BACKGROUND_GDK:
237 {
238 GdkColor color;
239
240 color.red = cellicon->background.red;
241 color.green = cellicon->background.green;
242 color.blue = cellicon->background.blue;
243
244 g_value_set_boxed (value, &color);
245 }
246 break;
247 case PROP_FOREGROUND_GDK:
248 {
249 GdkColor color;
250
251 color.red = cellicon->foreground.red;
252 color.green = cellicon->foreground.green;
253 color.blue = cellicon->foreground.blue;
254
255 g_value_set_boxed (value, &color);
256 }
257 break;
258 case PROP_FOCUSED:
259 g_value_set_boolean (value, cellicon->focused);
260 break;
261 case PROP_FIXED_WIDTH:
262 g_value_set_int(value, cellicon->fixed_width);
263 break;
264 case PROP_FIXED_HEIGHT:
265 g_value_set_int(value, cellicon->fixed_height);
266 break;
267 case PROP_BACKGROUND_SET:
268 g_value_set_boolean(value, cellicon->background_set);
269 break;
270 case PROP_FOREGROUND_SET:
271 g_value_set_boolean(value, cellicon->foreground_set);
272 break;
273 case PROP_SHOW_TEXT:
274 g_value_set_boolean(value, cellicon->show_text);
275 break;
276 default:
277 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
278 break;
279 }
280 }
281
282 static void
283 set_bg_color (GQvCellRendererIcon *cellicon,
284 GdkColor *color)
285 {
286 if (color)
287 {
288 if (!cellicon->background_set)
289 {
290 cellicon->background_set = TRUE;
291 g_object_notify(G_OBJECT(cellicon), "background_set");
292 }
293
294 cellicon->background.red = color->red;
295 cellicon->background.green = color->green;
296 cellicon->background.blue = color->blue;
297 }
298 else
299 {
300 if (cellicon->background_set)
301 {
302 cellicon->background_set = FALSE;
303 g_object_notify(G_OBJECT(cellicon), "background_set");
304 }
305 }
306 }
307
308 static void set_fg_color (GQvCellRendererIcon *cellicon,
309 GdkColor *color)
310 {
311 if (color)
312 {
313 if (!cellicon->foreground_set)
314 {
315 cellicon->foreground_set = TRUE;
316 g_object_notify(G_OBJECT(cellicon), "foreground_set");
317 }
318
319 cellicon->foreground.red = color->red;
320 cellicon->foreground.green = color->green;
321 cellicon->foreground.blue = color->blue;
322 }
323 else
324 {
325 if (cellicon->foreground_set)
326 {
327 cellicon->foreground_set = FALSE;
328 g_object_notify(G_OBJECT(cellicon), "foreground_set");
329 }
330 }
331 }
332
333 static void
334 gqv_cell_renderer_icon_set_property(GObject *object,
335 guint param_id,
336 const GValue *value,
337 GParamSpec *pspec)
338 {
339 GQvCellRendererIcon *cellicon = GQV_CELL_RENDERER_ICON (object);
340
341 switch (param_id)
342 {
343 case PROP_PIXBUF:
344 {
345 GdkPixbuf *pixbuf;
346
347 pixbuf = (GdkPixbuf*) g_value_get_object (value);
348 if (pixbuf) g_object_ref (pixbuf);
349 if (cellicon->pixbuf) g_object_unref (cellicon->pixbuf);
350 cellicon->pixbuf = pixbuf;
351 }
352 break;
353 case PROP_TEXT:
354 {
355 gchar *text;
356
357 text = cellicon->text;
358 cellicon->text = g_strdup(g_value_get_string(value));
359 g_free(text);
360
361 g_object_notify(object, "text");
362 }
363 break;
364 case PROP_BACKGROUND_GDK:
365 set_bg_color(cellicon, g_value_get_boxed(value));
366 break;
367 case PROP_FOREGROUND_GDK:
368 set_fg_color(cellicon, g_value_get_boxed(value));
369 break;
370 case PROP_FOCUSED:
371 cellicon->focused = g_value_get_boolean(value);
372 break;
373 case PROP_FIXED_WIDTH:
374 cellicon->fixed_width = g_value_get_int(value);
375 break;
376 case PROP_FIXED_HEIGHT:
377 cellicon->fixed_height = g_value_get_int(value);
378 break;
379 case PROP_BACKGROUND_SET:
380 cellicon->background_set = g_value_get_boolean(value);
381 break;
382 case PROP_FOREGROUND_SET:
383 cellicon->foreground_set = g_value_get_boolean(value);
384 break;
385 case PROP_SHOW_TEXT:
386 cellicon->show_text = g_value_get_boolean(value);
387 break;
388 default:
389 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
390 break;
391 }
392 }
393
394 static PangoLayout *
395 gqv_cell_renderer_icon_get_layout(GQvCellRendererIcon *cellicon, GtkWidget *widget, gboolean will_render)
396 {
397 PangoLayout *layout;
398 gint width;
399
400 width = (cellicon->fixed_width > 0) ? cellicon->fixed_width * PANGO_SCALE : -1;
401
402 layout = gtk_widget_create_pango_layout(widget, cellicon->text);
403 pango_layout_set_width(layout, width);
404 pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
405 pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
406
407 if (will_render)
408 {
409 PangoAttrList *attr_list;
410
411 attr_list = pango_attr_list_new();
412
413 if (cellicon->foreground_set)
414 {
415 PangoColor color;
416 PangoAttribute *attr;
417
418 color = cellicon->foreground;
419
420 attr = pango_attr_foreground_new(color.red, color.green, color.blue);
421
422 attr->start_index = 0;
423 attr->end_index = G_MAXINT;
424 pango_attr_list_insert(attr_list, attr);
425 }
426
427 pango_layout_set_attributes(layout, attr_list);
428 pango_attr_list_unref(attr_list);
429 }
430
431 return layout;
432 }
433
434 /**
435 * gqv_cell_renderer_icon_new:
436 *
437 * Creates a new #GQvCellRendererIcon. Adjust rendering
438 * parameters using object properties. Object properties can be set
439 * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
440 * can bind a property to a value in a #GtkTreeModel. For example, you
441 * can bind the "pixbuf" property on the cell renderer to a pixbuf value
442 * in the model, thus rendering a different image in each row of the
443 * #GtkTreeView.
444 *
445 * Return value: the new cell renderer
446 **/
447 GtkCellRenderer *
448 gqv_cell_renderer_icon_new(void)
449 {
450 return g_object_new (GQV_TYPE_CELL_RENDERER_ICON, NULL);
451 }
452
453 static void
454 gqv_cell_renderer_icon_get_size(GtkCellRenderer *cell,
455 GtkWidget *widget,
456 GdkRectangle *cell_area,
457 gint *x_offset,
458 gint *y_offset,
459 gint *width,
460 gint *height)
461 {
462 GQvCellRendererIcon *cellicon = (GQvCellRendererIcon *) cell;
463 gint calc_width;
464 gint calc_height;
465
466 if (cellicon->fixed_width > 0)
467 {
468 calc_width = cellicon->fixed_width;
469 }
470 else
471 {
472 calc_width = (cellicon->pixbuf) ? gdk_pixbuf_get_width(cellicon->pixbuf) : 0;
473 }
474
475 if (cellicon->fixed_height > 0)
476 {
477 calc_height = cellicon->fixed_height;
478 }
479 else
480 {
481 calc_height = (cellicon->pixbuf) ? gdk_pixbuf_get_height(cellicon->pixbuf) : 0;
482 }
483
484 if (cellicon->show_text && cellicon->text)
485 {
486 PangoLayout *layout;
487 PangoRectangle rect;
488
489 layout = gqv_cell_renderer_icon_get_layout(cellicon, widget, FALSE);
490 pango_layout_get_pixel_extents(layout, NULL, &rect);
491 g_object_unref(layout);
492
493 calc_width = MAX(calc_width, rect.width);
494 calc_height += rect.height;
495 }
496
497 calc_width += (gint)cell->xpad * 2;
498 calc_height += (gint)cell->ypad * 2;
499
500 if (x_offset) *x_offset = 0;
501 if (y_offset) *y_offset = 0;
502
503 if (cell_area && calc_width > 0 && calc_height > 0)
504 {
505 if (x_offset)
506 {
507 *x_offset = (cell->xalign * (cell_area->width - calc_width - 2 * cell->xpad));
508 *x_offset = MAX (*x_offset, 0) + cell->xpad;
509 }
510 if (y_offset)
511 {
512 *y_offset = (cell->yalign * (cell_area->height - calc_height - 2 * cell->ypad));
513 *y_offset = MAX (*y_offset, 0) + cell->ypad;
514 }
515 }
516
517 if (width) *width = calc_width;
518 if (height) *height = calc_height;
519 }
520
521 static void
522 gqv_cell_renderer_icon_render(GtkCellRenderer *cell,
523 GdkWindow *window,
524 GtkWidget *widget,
525 GdkRectangle *background_area,
526 GdkRectangle *cell_area,
527 GdkRectangle *expose_area,
528 GtkCellRendererState flags)
529
530 {
531 GQvCellRendererIcon *cellicon = (GQvCellRendererIcon *) cell;
532 GdkPixbuf *pixbuf;
533 const gchar *text;
534 GdkRectangle cell_rect;
535 GtkStateType state;
536
537 pixbuf = cellicon->pixbuf;
538 text = cellicon->text;
539
540 if (!pixbuf && !text) return;
541
542 gqv_cell_renderer_icon_get_size(cell, widget, cell_area,
543 &cell_rect.x, &cell_rect.y,
544 &cell_rect.width, &cell_rect.height);
545
546 cell_rect.x += cell->xpad;
547 cell_rect.y += cell->ypad;
548 cell_rect.width -= cell->xpad * 2;
549 cell_rect.height -= cell->ypad * 2;
550
551 if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
552 {
553 if (GTK_WIDGET_HAS_FOCUS(widget))
554 state = GTK_STATE_SELECTED;
555 else
556 state = GTK_STATE_ACTIVE;
557 }
558 else
559 {
560 if (GTK_WIDGET_STATE(widget) == GTK_STATE_INSENSITIVE)
561 state = GTK_STATE_INSENSITIVE;
562 else
563 state = GTK_STATE_NORMAL;
564 }
565
566 if (pixbuf)
567 {
568 GdkRectangle pix_rect;
569 GdkRectangle draw_rect;
570
571 pix_rect.width = gdk_pixbuf_get_width(pixbuf);
572 pix_rect.height = gdk_pixbuf_get_height(pixbuf);
573
574 pix_rect.x = cell_area->x + (cell_area->width - pix_rect.width) / 2;
575
576 if (cellicon->fixed_height > 0)
577 {
578 pix_rect.y = cell_area->y + cell->ypad + (cellicon->fixed_height - pix_rect.height) / 2;
579 }
580 else
581 {
582 pix_rect.y = cell_area->y + cell_rect.y;
583 }
584
585 if (gdk_rectangle_intersect(cell_area, &pix_rect, &draw_rect) &&
586 gdk_rectangle_intersect(expose_area, &draw_rect, &draw_rect))
587 {
588 gdk_draw_pixbuf(window,
589 widget->style->black_gc,
590 pixbuf,
591 /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */
592 draw_rect.x - pix_rect.x,
593 draw_rect.y - pix_rect.y,
594 draw_rect.x,
595 draw_rect.y,
596 draw_rect.width,
597 draw_rect.height,
598 GDK_RGB_DITHER_NORMAL,
599 0, 0);
600 }
601 }
602
603 if (cellicon->show_text && text)
604 {
605 PangoLayout *layout;
606 PangoRectangle text_rect;
607 GdkRectangle pix_rect;
608 GdkRectangle draw_rect;
609
610 layout = gqv_cell_renderer_icon_get_layout(cellicon, widget, TRUE);
611 pango_layout_get_pixel_extents(layout, NULL, &text_rect);
612
613 pix_rect.width = text_rect.width;
614 pix_rect.height = text_rect.height;
615 pix_rect.x = cell_area->x + cell->xpad + (cell_rect.width - text_rect.width + 1) / 2;
616 pix_rect.y = cell_area->y + cell->ypad + (cell_rect.height - text_rect.height);
617
618 if (gdk_rectangle_intersect(cell_area, &pix_rect, &draw_rect) &&
619 gdk_rectangle_intersect(expose_area, &draw_rect, &draw_rect))
620 {
621 gtk_paint_layout(widget->style, window,
622 state, TRUE,
623 cell_area, widget,
624 "cellrenderertext",
625 pix_rect.x - text_rect.x, pix_rect.y,
626 layout);
627 }
628
629 g_object_unref(layout);
630 }
631
632 if (cellicon->focused &&
633 GTK_WIDGET_HAS_FOCUS(widget))
634 {
635 gtk_paint_focus(widget->style, window,
636 state,
637 cell_area, widget,
638 "cellrendererfocus",
639 cell_area->x, cell_area->y,
640 cell_area->width, cell_area->height);
641 }
642 }
643