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