Whitespaces cleanup.
[geeqie.git] / src / cellrenderericon.c
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 #define TOGGLE_WIDTH 13
30 #define TOGGLE_SPACING 18
31
32
33 static void gqv_cell_renderer_icon_get_property(GObject         *object,
34                                                 guint           param_id,
35                                                 GValue          *value,
36                                                 GParamSpec      *pspec);
37 static void gqv_cell_renderer_icon_set_property(GObject         *object,
38                                                 guint           param_id,
39                                                 const GValue    *value,
40                                                 GParamSpec      *pspec);
41 static void gqv_cell_renderer_icon_init(GQvCellRendererIcon *celltext);
42 static void gqv_cell_renderer_icon_class_init(GQvCellRendererIconClass *class);
43 static void gqv_cell_renderer_icon_finalize(GObject *object);
44 static void gqv_cell_renderer_icon_get_size(GtkCellRenderer     *cell,
45                                             GtkWidget           *widget,
46                                             GdkRectangle        *rectangle,
47                                             gint                *x_offset,
48                                             gint                *y_offset,
49                                             gint                *width,
50                                             gint                *height);
51 static void gqv_cell_renderer_icon_render(GtkCellRenderer       *cell,
52                                            GdkWindow            *window,
53                                            GtkWidget            *widget,
54                                            GdkRectangle         *background_area,
55                                            GdkRectangle         *cell_area,
56                                            GdkRectangle         *expose_area,
57                                            GtkCellRendererState flags);
58
59 static gint gqv_cell_renderer_icon_activate (GtkCellRenderer      *cell,
60                                              GdkEvent             *event,
61                                              GtkWidget            *widget,
62                                              const gchar          *path,
63                                              GdkRectangle         *background_area,
64                                              GdkRectangle         *cell_area,
65                                              GtkCellRendererState  flags);
66
67 enum {
68   TOGGLED,
69   LAST_SIGNAL
70 };
71
72 enum {
73         PROP_ZERO,
74         PROP_PIXBUF,
75         PROP_TEXT,
76         PROP_BACKGROUND_GDK,
77         PROP_FOREGROUND_GDK,
78         PROP_FOCUSED,
79         PROP_FIXED_WIDTH,
80         PROP_FIXED_HEIGHT,
81
82         PROP_BACKGROUND_SET,
83         PROP_FOREGROUND_SET,
84         PROP_SHOW_TEXT,
85         PROP_SHOW_MARKS,
86         PROP_NUM_MARKS,
87         PROP_MARKS,
88         PROP_TOGGLED
89 };
90
91 static guint toggle_cell_signals[LAST_SIGNAL] = { 0 };
92
93 static gpointer parent_class;
94
95 GType
96 gqv_cell_renderer_icon_get_type(void)
97 {
98         static GType cell_icon_type = 0;
99
100         if (!cell_icon_type)
101                 {
102                 static const GTypeInfo cell_icon_info =
103                         {
104                         sizeof(GQvCellRendererIconClass), /* class_size */
105                         NULL,           /* base_init */
106                         NULL,           /* base_finalize */
107                         (GClassInitFunc) gqv_cell_renderer_icon_class_init, /* class_init */
108                         NULL,           /* class_finalize */
109                         NULL,           /* class_data */
110                         sizeof(GQvCellRendererIcon), /* instance_size */
111                         0,              /* n_preallocs */
112                         (GInstanceInitFunc) gqv_cell_renderer_icon_init, /* instance_init */
113                         NULL,           /* value_table */
114                         };
115
116                 cell_icon_type = g_type_register_static(GTK_TYPE_CELL_RENDERER,
117                                                         "GQvCellRendererIcon",
118                                                         &cell_icon_info, 0);
119                 }
120
121         return cell_icon_type;
122 }
123
124 static void
125 gqv_cell_renderer_icon_init(GQvCellRendererIcon *cellicon)
126 {
127         GTK_CELL_RENDERER(cellicon)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
128         GTK_CELL_RENDERER(cellicon)->xpad = 2;
129         GTK_CELL_RENDERER(cellicon)->ypad = 2;
130 }
131
132 static void
133 gqv_cell_renderer_icon_class_init(GQvCellRendererIconClass *class)
134 {
135         GObjectClass *object_class = G_OBJECT_CLASS(class);
136         GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(class);
137
138         parent_class = g_type_class_peek_parent(class);
139
140         object_class->finalize = gqv_cell_renderer_icon_finalize;
141
142         object_class->get_property = gqv_cell_renderer_icon_get_property;
143         object_class->set_property = gqv_cell_renderer_icon_set_property;
144
145         cell_class->get_size = gqv_cell_renderer_icon_get_size;
146         cell_class->render = gqv_cell_renderer_icon_render;
147         cell_class->activate = gqv_cell_renderer_icon_activate;
148
149         g_object_class_install_property(object_class,
150                                         PROP_PIXBUF,
151                                         g_param_spec_object("pixbuf",
152                                                         _("Pixbuf Object"),
153                                                         _("The pixbuf to render"),
154                                                         GDK_TYPE_PIXBUF,
155                                                         G_PARAM_READWRITE));
156
157         g_object_class_install_property(object_class,
158                                         PROP_TEXT,
159                                         g_param_spec_string("text",
160                                                         _("Text"),
161                                                         _("Text to render"),
162                                                         NULL,
163                                                         G_PARAM_READWRITE));
164
165         g_object_class_install_property(object_class,
166                                         PROP_BACKGROUND_GDK,
167                                         g_param_spec_boxed("background_gdk",
168                                                         _("Background color"),
169                                                         _("Background color as a GdkColor"),
170                                                         GDK_TYPE_COLOR,
171                                                         G_PARAM_READWRITE));
172
173         g_object_class_install_property(object_class,
174                                         PROP_FOREGROUND_GDK,
175                                         g_param_spec_boxed("foreground_gdk",
176                                                         _("Foreground color"),
177                                                         _("Foreground color as a GdkColor"),
178                                                         GDK_TYPE_COLOR,
179                                                         G_PARAM_READWRITE));
180
181         g_object_class_install_property(object_class,
182                                         PROP_FOCUSED,
183                                         g_param_spec_boolean("has_focus",
184                                                         _("Focus"),
185                                                         _("Draw focus indicator"),
186                                                         FALSE,
187                                                         G_PARAM_READWRITE));
188
189         g_object_class_install_property(object_class,
190                                         PROP_FIXED_WIDTH,
191                                         g_param_spec_int("fixed_width",
192                                                         _("Fixed width"),
193                                                         _("Width of cell"),
194                                                         -1, FIXED_ICON_SIZE_MAX,
195                                                         -1,
196                                                         G_PARAM_READWRITE));
197
198         g_object_class_install_property(object_class,
199                                         PROP_FIXED_HEIGHT,
200                                         g_param_spec_int("fixed_height",
201                                                         _("Fixed height"),
202                                                         _("Height of icon excluding text"),
203                                                         -1, FIXED_ICON_SIZE_MAX,
204                                                         -1,
205                                                         G_PARAM_READWRITE));
206
207         g_object_class_install_property(object_class,
208                                         PROP_BACKGROUND_SET,
209                                         g_param_spec_boolean("background_set",
210                                                         _("Background set"),
211                                                         _("Whether this tag affects the background color"),
212                                                         FALSE,
213                                                         G_PARAM_READWRITE));
214
215         g_object_class_install_property(object_class,
216                                         PROP_FOREGROUND_SET,
217                                         g_param_spec_boolean("foreground_set",
218                                                         _("Foreground set"),
219                                                         _("Whether this tag affects the foreground color"),
220                                                         FALSE,
221                                                         G_PARAM_READWRITE));
222
223         g_object_class_install_property(object_class,
224                                         PROP_SHOW_TEXT,
225                                         g_param_spec_boolean("show_text",
226                                                         _("Show text"),
227                                                         _("Whether the text is displayed"),
228                                                         TRUE,
229                                                         G_PARAM_READWRITE));
230
231         g_object_class_install_property(object_class,
232                                         PROP_SHOW_MARKS,
233                                         g_param_spec_boolean("show_marks",
234                                                         _("Show marks"),
235                                                         _("Whether the marks are displayed"),
236                                                         TRUE,
237                                                         G_PARAM_READWRITE));
238
239         g_object_class_install_property(object_class,
240                                         PROP_NUM_MARKS,
241                                         g_param_spec_int("num_marks",
242                                                         _("Number of marks"),
243                                                         _("Number of marks"),
244                                                         0, 32,
245                                                         6,
246                                                         G_PARAM_READWRITE));
247
248         g_object_class_install_property(object_class,
249                                         PROP_MARKS,
250                                         g_param_spec_uint("marks",
251                                                         _("Marks"),
252                                                         _("Marks bit array"),
253                                                         0, 0xffffffff,
254                                                         0,
255                                                         G_PARAM_READWRITE));
256
257         g_object_class_install_property(object_class,
258                                         PROP_TOGGLED,
259                                         g_param_spec_uint("toggled_mark",
260                                                         _("Toggled mark"),
261                                                         _("Toggled mark"),
262                                                         0, 32,
263                                                         0,
264                                                         G_PARAM_READWRITE));
265         toggle_cell_signals[TOGGLED] =
266                 g_signal_new ("toggled",
267                 G_OBJECT_CLASS_TYPE (object_class),
268                 G_SIGNAL_RUN_LAST,
269                 G_STRUCT_OFFSET (GQvCellRendererIconClass, toggled),
270                 NULL, NULL,
271                 g_cclosure_marshal_VOID__STRING,
272                 G_TYPE_NONE, 1,
273                 G_TYPE_STRING);
274
275 }
276
277 static void
278 gqv_cell_renderer_icon_finalize(GObject *object)
279 {
280         GQvCellRendererIcon *cellicon = GQV_CELL_RENDERER_ICON(object);
281
282         if (cellicon->pixbuf) g_object_unref(cellicon->pixbuf);
283
284         g_free(cellicon->text);
285
286         (*(G_OBJECT_CLASS(parent_class))->finalize)(object);
287 }
288
289 static void
290 gqv_cell_renderer_icon_get_property(GObject     *object,
291                                     guint       param_id,
292                                     GValue      *value,
293                                     GParamSpec  *pspec)
294 {
295         GQvCellRendererIcon *cellicon = GQV_CELL_RENDERER_ICON(object);
296
297         switch (param_id)
298         {
299         case PROP_PIXBUF:
300                 g_value_set_object(value, cellicon->pixbuf ? G_OBJECT(cellicon->pixbuf) : NULL);
301                 break;
302         case PROP_TEXT:
303                 g_value_set_string(value, cellicon->text);
304                 break;
305         case PROP_BACKGROUND_GDK:
306                 {
307                 GdkColor color;
308
309                 color.red = cellicon->background.red;
310                 color.green = cellicon->background.green;
311                 color.blue = cellicon->background.blue;
312
313                 g_value_set_boxed(value, &color);
314                 }
315                 break;
316         case PROP_FOREGROUND_GDK:
317                 {
318                 GdkColor color;
319
320                 color.red = cellicon->foreground.red;
321                 color.green = cellicon->foreground.green;
322                 color.blue = cellicon->foreground.blue;
323
324                 g_value_set_boxed(value, &color);
325                 }
326                 break;
327         case PROP_FOCUSED:
328                 g_value_set_boolean(value, cellicon->focused);
329                 break;
330         case PROP_FIXED_WIDTH:
331                 g_value_set_int(value, cellicon->fixed_width);
332                 break;
333         case PROP_FIXED_HEIGHT:
334                 g_value_set_int(value, cellicon->fixed_height);
335                 break;
336         case PROP_BACKGROUND_SET:
337                 g_value_set_boolean(value, cellicon->background_set);
338                 break;
339         case PROP_FOREGROUND_SET:
340                 g_value_set_boolean(value, cellicon->foreground_set);
341                 break;
342         case PROP_SHOW_TEXT:
343                 g_value_set_boolean(value, cellicon->show_text);
344                 break;
345         case PROP_SHOW_MARKS:
346                 g_value_set_boolean(value, cellicon->show_marks);
347                 break;
348         case PROP_NUM_MARKS:
349                 g_value_set_int(value, cellicon->num_marks);
350                 break;
351         case PROP_MARKS:
352                 g_value_set_uint(value, cellicon->marks);
353                 break;
354         case PROP_TOGGLED:
355                 g_value_set_uint(value, cellicon->toggled_mark);
356                 break;
357         default:
358                 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
359                 break;
360         }
361 }
362
363 static void
364 set_bg_color(GQvCellRendererIcon *cellicon,
365              GdkColor             *color)
366 {
367         if (color)
368                 {
369                 if (!cellicon->background_set)
370                         {
371                         cellicon->background_set = TRUE;
372                         g_object_notify(G_OBJECT(cellicon), "background_set");
373                         }
374
375                 cellicon->background.red = color->red;
376                 cellicon->background.green = color->green;
377                 cellicon->background.blue = color->blue;
378                 }
379         else
380                 {
381                 if (cellicon->background_set)
382                         {
383                         cellicon->background_set = FALSE;
384                         g_object_notify(G_OBJECT(cellicon), "background_set");
385                         }
386                 }
387 }
388
389 static void set_fg_color(GQvCellRendererIcon *cellicon,
390                          GdkColor             *color)
391 {
392         if (color)
393                 {
394                 if (!cellicon->foreground_set)
395                         {
396                         cellicon->foreground_set = TRUE;
397                         g_object_notify(G_OBJECT(cellicon), "foreground_set");
398                         }
399
400                 cellicon->foreground.red = color->red;
401                 cellicon->foreground.green = color->green;
402                 cellicon->foreground.blue = color->blue;
403                 }
404         else
405                 {
406                 if (cellicon->foreground_set)
407                         {
408                         cellicon->foreground_set = FALSE;
409                         g_object_notify(G_OBJECT(cellicon), "foreground_set");
410                         }
411                 }
412 }
413
414 static void
415 gqv_cell_renderer_icon_set_property(GObject             *object,
416                                     guint               param_id,
417                                     const GValue        *value,
418                                     GParamSpec          *pspec)
419 {
420         GQvCellRendererIcon *cellicon = GQV_CELL_RENDERER_ICON(object);
421
422         switch (param_id)
423         {
424         case PROP_PIXBUF:
425                 {
426                 GdkPixbuf *pixbuf;
427
428                 pixbuf = (GdkPixbuf*) g_value_get_object(value);
429                 if (pixbuf) g_object_ref(pixbuf);
430                 if (cellicon->pixbuf) g_object_unref(cellicon->pixbuf);
431                 cellicon->pixbuf = pixbuf;
432                 }
433                 break;
434         case PROP_TEXT:
435                 {
436                 gchar *text;
437
438                 text = cellicon->text;
439                 cellicon->text = g_strdup(g_value_get_string(value));
440                 g_free(text);
441
442                 g_object_notify(object, "text");
443                 }
444                 break;
445         case PROP_BACKGROUND_GDK:
446                 set_bg_color(cellicon, g_value_get_boxed(value));
447                 break;
448         case PROP_FOREGROUND_GDK:
449                 set_fg_color(cellicon, g_value_get_boxed(value));
450                 break;
451         case PROP_FOCUSED:
452                 cellicon->focused = g_value_get_boolean(value);
453                 break;
454         case PROP_FIXED_WIDTH:
455                 cellicon->fixed_width = g_value_get_int(value);
456                 break;
457         case PROP_FIXED_HEIGHT:
458                 cellicon->fixed_height = g_value_get_int(value);
459                 break;
460         case PROP_BACKGROUND_SET:
461                 cellicon->background_set = g_value_get_boolean(value);
462                 break;
463         case PROP_FOREGROUND_SET:
464                 cellicon->foreground_set = g_value_get_boolean(value);
465                 break;
466         case PROP_SHOW_TEXT:
467                 cellicon->show_text = g_value_get_boolean(value);
468                 break;
469         case PROP_SHOW_MARKS:
470                 cellicon->show_marks = g_value_get_boolean(value);
471                 break;
472         case PROP_NUM_MARKS:
473                 cellicon->num_marks = g_value_get_int(value);
474                 break;
475         case PROP_MARKS:
476                 cellicon->marks = g_value_get_uint(value);
477                 break;
478         default:
479                 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
480                 break;
481         }
482 }
483
484 static PangoLayout *
485 gqv_cell_renderer_icon_get_layout(GQvCellRendererIcon *cellicon, GtkWidget *widget, gboolean will_render)
486 {
487         PangoLayout *layout;
488         gint width;
489
490         width = (cellicon->fixed_width > 0) ? cellicon->fixed_width * PANGO_SCALE : -1;
491
492         layout = gtk_widget_create_pango_layout(widget, cellicon->text);
493         pango_layout_set_width(layout, width);
494         pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
495         pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
496
497         if (will_render)
498                 {
499                 PangoAttrList *attr_list;
500
501                 attr_list = pango_attr_list_new();
502
503                 if (cellicon->foreground_set)
504                         {
505                         PangoColor color;
506                         PangoAttribute *attr;
507
508                         color = cellicon->foreground;
509
510                         attr = pango_attr_foreground_new(color.red, color.green, color.blue);
511
512                         attr->start_index = 0;
513                         attr->end_index = G_MAXINT;
514                         pango_attr_list_insert(attr_list, attr);
515                         }
516
517                 pango_layout_set_attributes(layout, attr_list);
518                 pango_attr_list_unref(attr_list);
519                 }
520
521         return layout;
522 }
523
524 /**
525  * gqv_cell_renderer_icon_new:
526  *
527  * Creates a new #GQvCellRendererIcon. Adjust rendering
528  * parameters using object properties. Object properties can be set
529  * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
530  * can bind a property to a value in a #GtkTreeModel. For example, you
531  * can bind the "pixbuf" property on the cell renderer to a pixbuf value
532  * in the model, thus rendering a different image in each row of the
533  * #GtkTreeView.
534  *
535  * Return value: the new cell renderer
536  **/
537 GtkCellRenderer *
538 gqv_cell_renderer_icon_new(void)
539 {
540         return g_object_new(GQV_TYPE_CELL_RENDERER_ICON, NULL);
541 }
542
543 static void
544 gqv_cell_renderer_icon_get_size(GtkCellRenderer *cell,
545                                 GtkWidget       *widget,
546                                 GdkRectangle    *cell_area,
547                                 gint            *x_offset,
548                                 gint            *y_offset,
549                                 gint            *width,
550                                 gint            *height)
551 {
552         GQvCellRendererIcon *cellicon = (GQvCellRendererIcon *) cell;
553         gint calc_width;
554         gint calc_height;
555
556         if (cellicon->fixed_width > 0)
557                 {
558                 calc_width = cellicon->fixed_width;
559                 }
560         else
561                 {
562                 calc_width = (cellicon->pixbuf) ? gdk_pixbuf_get_width(cellicon->pixbuf) : 0;
563                 }
564
565         if (cellicon->fixed_height > 0)
566                 {
567                 calc_height = cellicon->fixed_height;
568                 }
569         else
570                 {
571                 calc_height = (cellicon->pixbuf) ? gdk_pixbuf_get_height(cellicon->pixbuf) : 0;
572                 }
573
574         if (cellicon->show_text && cellicon->text)
575                 {
576                 PangoLayout *layout;
577                 PangoRectangle rect;
578
579                 layout = gqv_cell_renderer_icon_get_layout(cellicon, widget, FALSE);
580                 pango_layout_get_pixel_extents(layout, NULL, &rect);
581                 g_object_unref(layout);
582
583                 calc_width = MAX(calc_width, rect.width);
584                 calc_height += rect.height;
585                 }
586
587         if (cellicon->show_marks)
588                 {
589                 calc_height += TOGGLE_SPACING;
590                 calc_width = MAX(calc_width, TOGGLE_SPACING * cellicon->num_marks);
591                 }
592
593         calc_width += (gint)cell->xpad * 2;
594         calc_height += (gint)cell->ypad * 2;
595
596         if (x_offset) *x_offset = 0;
597         if (y_offset) *y_offset = 0;
598
599         if (cell_area && calc_width > 0 && calc_height > 0)
600                 {
601                 if (x_offset)
602                         {
603                         *x_offset = (cell->xalign * (cell_area->width - calc_width - 2 * cell->xpad));
604                         *x_offset = MAX(*x_offset, 0) + cell->xpad;
605                         }
606                 if (y_offset)
607                         {
608                         *y_offset = (cell->yalign * (cell_area->height - calc_height - 2 * cell->ypad));
609                         *y_offset = MAX(*y_offset, 0) + cell->ypad;
610                         }
611                 }
612
613         if (width) *width = calc_width;
614         if (height) *height = calc_height;
615 }
616
617 static void
618 gqv_cell_renderer_icon_render(GtkCellRenderer           *cell,
619                               GdkWindow                 *window,
620                               GtkWidget                 *widget,
621                               GdkRectangle              *background_area,
622                               GdkRectangle              *cell_area,
623                               GdkRectangle              *expose_area,
624                               GtkCellRendererState      flags)
625
626 {
627         GQvCellRendererIcon *cellicon = (GQvCellRendererIcon *) cell;
628         GdkPixbuf *pixbuf;
629         const gchar *text;
630         GdkRectangle cell_rect;
631         GtkStateType state;
632
633         pixbuf = cellicon->pixbuf;
634         text = cellicon->text;
635
636         if (!pixbuf && !text) return;
637
638         gqv_cell_renderer_icon_get_size(cell, widget, cell_area,
639                                         &cell_rect.x, &cell_rect.y,
640                                         &cell_rect.width, &cell_rect.height);
641
642         cell_rect.x += cell->xpad;
643         cell_rect.y += cell->ypad;
644         cell_rect.width -= cell->xpad * 2;
645         cell_rect.height -= cell->ypad * 2;
646
647         if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
648                 {
649                 if (GTK_WIDGET_HAS_FOCUS(widget))
650                         state = GTK_STATE_SELECTED;
651                 else
652                         state = GTK_STATE_ACTIVE;
653                 }
654         else
655                 {
656                 if (GTK_WIDGET_STATE(widget) == GTK_STATE_INSENSITIVE)
657                         state = GTK_STATE_INSENSITIVE;
658                 else
659                         state = GTK_STATE_NORMAL;
660                 }
661
662         if (pixbuf)
663                 {
664                 GdkRectangle pix_rect;
665                 GdkRectangle draw_rect;
666
667                 pix_rect.width = gdk_pixbuf_get_width(pixbuf);
668                 pix_rect.height = gdk_pixbuf_get_height(pixbuf);
669
670                 pix_rect.x = cell_area->x + (cell_area->width - pix_rect.width) / 2;
671
672                 if (cellicon->fixed_height > 0)
673                         {
674                         pix_rect.y = cell_area->y + cell->ypad + (cellicon->fixed_height - pix_rect.height) / 2;
675                         }
676                 else
677                         {
678                         pix_rect.y = cell_area->y + cell_rect.y;
679                         }
680
681                 if (gdk_rectangle_intersect(cell_area, &pix_rect, &draw_rect) &&
682                     gdk_rectangle_intersect(expose_area, &draw_rect, &draw_rect))
683                         {
684                         gdk_draw_pixbuf(window,
685                                         widget->style->black_gc,
686                                         pixbuf,
687                                         /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */
688                                         draw_rect.x - pix_rect.x,
689                                         draw_rect.y - pix_rect.y,
690                                         draw_rect.x,
691                                         draw_rect.y,
692                                         draw_rect.width,
693                                         draw_rect.height,
694                                         GDK_RGB_DITHER_NORMAL,
695                                         0, 0);
696                         }
697                 }
698
699         if (cellicon->show_text && text)
700                 {
701                 PangoLayout *layout;
702                 PangoRectangle text_rect;
703                 GdkRectangle pix_rect;
704                 GdkRectangle draw_rect;
705
706                 layout = gqv_cell_renderer_icon_get_layout(cellicon, widget, TRUE);
707                 pango_layout_get_pixel_extents(layout, NULL, &text_rect);
708
709                 pix_rect.width = text_rect.width;
710                 pix_rect.height = text_rect.height;
711                 pix_rect.x = cell_area->x + cell->xpad + (cell_rect.width - text_rect.width + 1) / 2;
712                 pix_rect.y = cell_area->y + cell->ypad + (cell_rect.height - text_rect.height);
713                 
714                 if (cellicon->show_marks)
715                         {
716                         pix_rect.y -= TOGGLE_SPACING;
717                         }
718
719                 if (gdk_rectangle_intersect(cell_area, &pix_rect, &draw_rect) &&
720                     gdk_rectangle_intersect(expose_area, &draw_rect, &draw_rect))
721                         {
722                         gtk_paint_layout(widget->style, window,
723                                          state, TRUE,
724                                          cell_area, widget,
725                                          "cellrenderertext",
726                                          pix_rect.x - text_rect.x, pix_rect.y,
727                                          layout);
728                         }
729
730                 g_object_unref(layout);
731                 }
732
733         if (cellicon->show_marks)
734                 {
735                 GdkRectangle pix_rect;
736                 GdkRectangle draw_rect;
737                 gint i;
738
739                 pix_rect.width = TOGGLE_SPACING * cellicon->num_marks;
740                 pix_rect.height = TOGGLE_SPACING;
741                 pix_rect.x = cell_area->x + cell->xpad + (cell_rect.width - pix_rect.width + 1) / 2 + (TOGGLE_SPACING - TOGGLE_WIDTH) / 2;
742                 pix_rect.y = cell_area->y + cell->ypad + (cell_rect.height - pix_rect.height) + (TOGGLE_SPACING - TOGGLE_WIDTH) / 2;
743                 
744                 if (gdk_rectangle_intersect(cell_area, &pix_rect, &draw_rect) &&
745                     gdk_rectangle_intersect(expose_area, &draw_rect, &draw_rect))
746                         {
747                         for (i = 0; i < cellicon->num_marks; i++)
748                                 {
749                                 gtk_paint_check (widget->style, window,
750                                          state, (cellicon->marks & (1 << i)) ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
751                                          cell_area, widget, "cellcheck",
752                                          pix_rect.x + i * TOGGLE_SPACING + (TOGGLE_WIDTH - TOGGLE_SPACING) / 2,
753                                          pix_rect.y,
754                                          TOGGLE_WIDTH, TOGGLE_WIDTH);
755                                 }
756                         }
757                 }
758
759         if (cellicon->focused && GTK_WIDGET_HAS_FOCUS(widget))
760                 {
761                 gtk_paint_focus(widget->style, window,
762                                 state,
763                                 cell_area, widget,
764                                 "cellrendererfocus",
765                                 cell_area->x, cell_area->y,
766                                 cell_area->width, cell_area->height);
767                 }
768 }
769
770 static gint
771 gqv_cell_renderer_icon_activate (GtkCellRenderer      *cell,
772                                  GdkEvent             *event,
773                                  GtkWidget            *widget,
774                                  const gchar          *path,
775                                  GdkRectangle         *background_area,
776                                  GdkRectangle         *cell_area,
777                                  GtkCellRendererState  flags)
778 {
779         GQvCellRendererIcon *cellicon = (GQvCellRendererIcon *) cell;
780         GdkEventButton      *bevent = &event->button;
781
782         if (cellicon->show_marks &&
783             event->type == GDK_BUTTON_PRESS &&
784             !(bevent->state & GDK_SHIFT_MASK ) &&
785             !(bevent->state & GDK_CONTROL_MASK ))
786                 {
787                 GdkRectangle rect;
788                 GdkRectangle cell_rect;
789                 gint i;
790                 
791                 gqv_cell_renderer_icon_get_size(cell, widget, cell_area,
792                                                 &cell_rect.x, &cell_rect.y,
793                                                 &cell_rect.width, &cell_rect.height);
794
795                 cell_rect.x += cell->xpad;
796                 cell_rect.y += cell->ypad;
797                 cell_rect.width -= cell->xpad * 2;
798                 cell_rect.height -= cell->ypad * 2;
799
800                 rect.width = TOGGLE_WIDTH;
801                 rect.height = TOGGLE_WIDTH;
802                 rect.y = cell_area->y + cell->ypad + (cell_rect.height - TOGGLE_SPACING) + (TOGGLE_SPACING - TOGGLE_WIDTH) / 2;
803                 for (i = 0; i < cellicon->num_marks; i++)
804                         {
805                         rect.x = cell_area->x + cell->xpad + (cell_rect.width - TOGGLE_SPACING * cellicon->num_marks + 1) / 2 + i * TOGGLE_SPACING;
806                         
807                         if (bevent->x >= rect.x && bevent->x < rect.x + rect.width &&
808                             bevent->y >= rect.y && bevent->y < rect.y + rect.height)
809                                 {
810                                 cellicon->toggled_mark = i;
811                                 g_signal_emit (cell, toggle_cell_signals[TOGGLED], 0, path);
812                                 break;
813                                 }
814                         }
815                 }
816         return FALSE;
817 }