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