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