1 /* gtkcellrendererpixbuf.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 #include <stdlib.h>
20 #include <cairo-gobject.h>
21 #include "gtkcellrendererpixbuf.h"
22 #include "deprecated/gtkiconfactory.h"
23 #include "gtkiconhelperprivate.h"
24 #include "gtkicontheme.h"
25 #include "gtkintl.h"
26 #include "gtkprivate.h"
27 #include "gtkstylecontextprivate.h"
28 #include "a11y/gtkimagecellaccessible.h"
29 
30 
31 /**
32  * SECTION:gtkcellrendererpixbuf
33  * @Short_description: Renders a pixbuf in a cell
34  * @Title: GtkCellRendererPixbuf
35  *
36  * A #GtkCellRendererPixbuf can be used to render an image in a cell. It allows
37  * to render either a given #GdkPixbuf (set via the
38  * #GtkCellRendererPixbuf:pixbuf property) or a named icon (set via the
39  * #GtkCellRendererPixbuf:icon-name property).
40  *
41  * To support the tree view, #GtkCellRendererPixbuf also supports rendering two
42  * alternative pixbufs, when the #GtkCellRenderer:is-expander property is %TRUE.
43  * If the #GtkCellRenderer:is-expanded property is %TRUE and the
44  * #GtkCellRendererPixbuf:pixbuf-expander-open property is set to a pixbuf, it
45  * renders that pixbuf, if the #GtkCellRenderer:is-expanded property is %FALSE
46  * and the #GtkCellRendererPixbuf:pixbuf-expander-closed property is set to a
47  * pixbuf, it renders that one.
48  */
49 
50 
51 static void gtk_cell_renderer_pixbuf_get_property  (GObject                    *object,
52 						    guint                       param_id,
53 						    GValue                     *value,
54 						    GParamSpec                 *pspec);
55 static void gtk_cell_renderer_pixbuf_set_property  (GObject                    *object,
56 						    guint                       param_id,
57 						    const GValue               *value,
58 						    GParamSpec                 *pspec);
59 static void gtk_cell_renderer_pixbuf_get_size   (GtkCellRenderer            *cell,
60 						 GtkWidget                  *widget,
61 						 const GdkRectangle         *rectangle,
62 						 gint                       *x_offset,
63 						 gint                       *y_offset,
64 						 gint                       *width,
65 						 gint                       *height);
66 static void gtk_cell_renderer_pixbuf_render     (GtkCellRenderer            *cell,
67 						 cairo_t                    *cr,
68 						 GtkWidget                  *widget,
69 						 const GdkRectangle         *background_area,
70 						 const GdkRectangle         *cell_area,
71 						 GtkCellRendererState        flags);
72 
73 
74 enum {
75   PROP_0,
76   PROP_PIXBUF,
77   PROP_PIXBUF_EXPANDER_OPEN,
78   PROP_PIXBUF_EXPANDER_CLOSED,
79   PROP_SURFACE,
80   PROP_STOCK_ID,
81   PROP_STOCK_SIZE,
82   PROP_STOCK_DETAIL,
83   PROP_FOLLOW_STATE,
84   PROP_ICON_NAME,
85   PROP_GICON
86 };
87 
88 
89 struct _GtkCellRendererPixbufPrivate
90 {
91   GtkImageDefinition *image_def;
92   GtkIconSize         icon_size;
93 
94   GdkPixbuf *pixbuf_expander_open;
95   GdkPixbuf *pixbuf_expander_closed;
96 
97   gboolean follow_state;
98 
99   gchar *stock_detail;
100 };
101 
G_DEFINE_TYPE_WITH_PRIVATE(GtkCellRendererPixbuf,gtk_cell_renderer_pixbuf,GTK_TYPE_CELL_RENDERER)102 G_DEFINE_TYPE_WITH_PRIVATE (GtkCellRendererPixbuf, gtk_cell_renderer_pixbuf, GTK_TYPE_CELL_RENDERER)
103 
104 static void
105 gtk_cell_renderer_pixbuf_init (GtkCellRendererPixbuf *cellpixbuf)
106 {
107   GtkCellRendererPixbufPrivate *priv;
108 
109   cellpixbuf->priv = gtk_cell_renderer_pixbuf_get_instance_private (cellpixbuf);
110   priv = cellpixbuf->priv;
111 
112   priv->image_def = gtk_image_definition_new_empty ();
113   priv->icon_size = GTK_ICON_SIZE_MENU;
114   priv->follow_state = TRUE;
115 }
116 
117 static void
gtk_cell_renderer_pixbuf_finalize(GObject * object)118 gtk_cell_renderer_pixbuf_finalize (GObject *object)
119 {
120   GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
121   GtkCellRendererPixbufPrivate *priv = cellpixbuf->priv;
122 
123   gtk_image_definition_unref (priv->image_def);
124 
125   if (priv->pixbuf_expander_open)
126     g_object_unref (priv->pixbuf_expander_open);
127   if (priv->pixbuf_expander_closed)
128     g_object_unref (priv->pixbuf_expander_closed);
129 
130   g_free (priv->stock_detail);
131 
132   G_OBJECT_CLASS (gtk_cell_renderer_pixbuf_parent_class)->finalize (object);
133 }
134 
135 static void
gtk_cell_renderer_pixbuf_class_init(GtkCellRendererPixbufClass * class)136 gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class)
137 {
138   GObjectClass *object_class = G_OBJECT_CLASS (class);
139   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
140 
141   object_class->finalize = gtk_cell_renderer_pixbuf_finalize;
142 
143   object_class->get_property = gtk_cell_renderer_pixbuf_get_property;
144   object_class->set_property = gtk_cell_renderer_pixbuf_set_property;
145 
146   cell_class->get_size = gtk_cell_renderer_pixbuf_get_size;
147   cell_class->render = gtk_cell_renderer_pixbuf_render;
148 
149   g_object_class_install_property (object_class,
150 				   PROP_PIXBUF,
151 				   g_param_spec_object ("pixbuf",
152 							P_("Pixbuf Object"),
153 							P_("The pixbuf to render"),
154 							GDK_TYPE_PIXBUF,
155 							GTK_PARAM_READWRITE));
156 
157   g_object_class_install_property (object_class,
158 				   PROP_PIXBUF_EXPANDER_OPEN,
159 				   g_param_spec_object ("pixbuf-expander-open",
160 							P_("Pixbuf Expander Open"),
161 							P_("Pixbuf for open expander"),
162 							GDK_TYPE_PIXBUF,
163 							GTK_PARAM_READWRITE));
164 
165   g_object_class_install_property (object_class,
166 				   PROP_PIXBUF_EXPANDER_CLOSED,
167 				   g_param_spec_object ("pixbuf-expander-closed",
168 							P_("Pixbuf Expander Closed"),
169 							P_("Pixbuf for closed expander"),
170 							GDK_TYPE_PIXBUF,
171 							GTK_PARAM_READWRITE));
172   /**
173    * GtkCellRendererPixbuf:surface:
174    *
175    * Since: 3.10
176    */
177   g_object_class_install_property (object_class,
178 				   PROP_SURFACE,
179 				   g_param_spec_boxed ("surface",
180 						       P_("surface"),
181 						       P_("The surface to render"),
182 						       CAIRO_GOBJECT_TYPE_SURFACE,
183 						       GTK_PARAM_READWRITE));
184 
185   /**
186    * GtkCellRendererPixbuf:stock-id:
187    *
188    * Since: 2.2
189    *
190    * Deprecated: 3.10: Use #GtkCellRendererPixbuf:icon-name instead.
191    */
192   g_object_class_install_property (object_class,
193 				   PROP_STOCK_ID,
194 				   g_param_spec_string ("stock-id",
195 							P_("Stock ID"),
196 							P_("The stock ID of the stock icon to render"),
197 							NULL,
198 							GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
199 
200   /**
201    * GtkCellRendererPixbuf:stock-size:
202    *
203    * The #GtkIconSize value that specifies the size of the rendered icon.
204    *
205    * Since: 2.2
206    */
207   g_object_class_install_property (object_class,
208 				   PROP_STOCK_SIZE,
209 				   g_param_spec_uint ("stock-size",
210 						      P_("Size"),
211 						      P_("The GtkIconSize value that specifies the size of the rendered icon"),
212 						      0,
213 						      G_MAXUINT,
214 						      GTK_ICON_SIZE_MENU,
215 						      GTK_PARAM_READWRITE));
216 
217   /*
218    * GtkCellRendererPixbuf:stock-detail:
219    *
220    * Since: 2.2
221    *
222    * Deprecated: 3.22: This property does nothing. Use CSS to theme widgets.
223    */
224   g_object_class_install_property (object_class,
225 				   PROP_STOCK_DETAIL,
226 				   g_param_spec_string ("stock-detail",
227 							P_("Detail"),
228 							P_("Render detail to pass to the theme engine"),
229 							NULL,
230 							GTK_PARAM_READWRITE));
231 
232 
233   /**
234    * GtkCellRendererPixbuf:icon-name:
235    *
236    * The name of the themed icon to display.
237    * This property only has an effect if not overridden by "stock_id"
238    * or "pixbuf" properties.
239    *
240    * Since: 2.8
241    */
242   g_object_class_install_property (object_class,
243 				   PROP_ICON_NAME,
244 				   g_param_spec_string ("icon-name",
245 							P_("Icon Name"),
246 							P_("The name of the icon from the icon theme"),
247 							NULL,
248 							GTK_PARAM_READWRITE));
249 
250   /**
251    * GtkCellRendererPixbuf:follow-state:
252    *
253    * Specifies whether the rendered pixbuf should be colorized
254    * according to the #GtkCellRendererState.
255    *
256    * Since: 2.8
257    *
258    * Deprecated: 3.16: Cell renderers always follow state.
259    */
260   g_object_class_install_property (object_class,
261 				   PROP_FOLLOW_STATE,
262 				   g_param_spec_boolean ("follow-state",
263  							 P_("Follow State"),
264  							 P_("Whether the rendered pixbuf should be "
265 							    "colorized according to the state"),
266  							 TRUE,
267  							 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
268 
269   /**
270    * GtkCellRendererPixbuf:gicon:
271    *
272    * The GIcon representing the icon to display.
273    * If the icon theme is changed, the image will be updated
274    * automatically.
275    *
276    * Since: 2.14
277    */
278   g_object_class_install_property (object_class,
279                                    PROP_GICON,
280                                    g_param_spec_object ("gicon",
281                                                         P_("Icon"),
282                                                         P_("The GIcon being displayed"),
283                                                         G_TYPE_ICON,
284                                                         GTK_PARAM_READWRITE));
285 
286 
287 
288   gtk_cell_renderer_class_set_accessible_type (cell_class, GTK_TYPE_IMAGE_CELL_ACCESSIBLE);
289 }
290 
291 static void
gtk_cell_renderer_pixbuf_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)292 gtk_cell_renderer_pixbuf_get_property (GObject        *object,
293 				       guint           param_id,
294 				       GValue         *value,
295 				       GParamSpec     *pspec)
296 {
297   GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
298   GtkCellRendererPixbufPrivate *priv = cellpixbuf->priv;
299 
300   switch (param_id)
301     {
302     case PROP_PIXBUF:
303       g_value_set_object (value, gtk_image_definition_get_pixbuf (priv->image_def));
304       break;
305     case PROP_PIXBUF_EXPANDER_OPEN:
306       g_value_set_object (value, priv->pixbuf_expander_open);
307       break;
308     case PROP_PIXBUF_EXPANDER_CLOSED:
309       g_value_set_object (value, priv->pixbuf_expander_closed);
310       break;
311     case PROP_SURFACE:
312       g_value_set_boxed (value, gtk_image_definition_get_surface (priv->image_def));
313       break;
314     case PROP_STOCK_ID:
315       g_value_set_string (value, gtk_image_definition_get_stock (priv->image_def));
316       break;
317     case PROP_STOCK_SIZE:
318       g_value_set_uint (value, priv->icon_size);
319       break;
320     case PROP_STOCK_DETAIL:
321       g_value_set_string (value, priv->stock_detail);
322       break;
323     case PROP_FOLLOW_STATE:
324       g_value_set_boolean (value, priv->follow_state);
325       break;
326     case PROP_ICON_NAME:
327       g_value_set_string (value, gtk_image_definition_get_icon_name (priv->image_def));
328       break;
329     case PROP_GICON:
330       g_value_set_object (value, gtk_image_definition_get_gicon (priv->image_def));
331       break;
332     default:
333       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
334       break;
335     }
336 }
337 
338 static void
notify_storage_type(GtkCellRendererPixbuf * cellpixbuf,GtkImageType storage_type)339 notify_storage_type (GtkCellRendererPixbuf *cellpixbuf,
340                      GtkImageType           storage_type)
341 {
342   switch (storage_type)
343     {
344     case GTK_IMAGE_SURFACE:
345       g_object_notify (G_OBJECT (cellpixbuf), "surface");
346       break;
347     case GTK_IMAGE_PIXBUF:
348       g_object_notify (G_OBJECT (cellpixbuf), "pixbuf");
349       break;
350     case GTK_IMAGE_STOCK:
351       g_object_notify (G_OBJECT (cellpixbuf), "stock-id");
352       break;
353     case GTK_IMAGE_ICON_NAME:
354       g_object_notify (G_OBJECT (cellpixbuf), "icon-name");
355       break;
356     case GTK_IMAGE_GICON:
357       g_object_notify (G_OBJECT (cellpixbuf), "gicon");
358       break;
359     default:
360     case GTK_IMAGE_ANIMATION:
361       g_assert_not_reached ();
362     case GTK_IMAGE_EMPTY:
363       break;
364     }
365 }
366 
367 static void
take_image_definition(GtkCellRendererPixbuf * cellpixbuf,GtkImageDefinition * def)368 take_image_definition (GtkCellRendererPixbuf *cellpixbuf,
369                        GtkImageDefinition    *def)
370 {
371   GtkCellRendererPixbufPrivate *priv;
372   GtkImageType old_storage_type, new_storage_type;
373 
374   if (def == NULL)
375     def = gtk_image_definition_new_empty ();
376 
377   priv = cellpixbuf->priv;
378   old_storage_type = gtk_image_definition_get_storage_type (priv->image_def);
379   new_storage_type = gtk_image_definition_get_storage_type (def);
380 
381   if (new_storage_type != old_storage_type)
382     notify_storage_type (cellpixbuf, old_storage_type);
383 
384   gtk_image_definition_unref (priv->image_def);
385   priv->image_def = def;
386 }
387 
388 static void
gtk_cell_renderer_pixbuf_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)389 gtk_cell_renderer_pixbuf_set_property (GObject      *object,
390 				       guint         param_id,
391 				       const GValue *value,
392 				       GParamSpec   *pspec)
393 {
394   GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
395   GtkCellRendererPixbufPrivate *priv = cellpixbuf->priv;
396 
397   switch (param_id)
398     {
399     case PROP_PIXBUF:
400       take_image_definition (cellpixbuf, gtk_image_definition_new_pixbuf (g_value_get_object (value), 1));
401       break;
402     case PROP_PIXBUF_EXPANDER_OPEN:
403       if (priv->pixbuf_expander_open)
404         g_object_unref (priv->pixbuf_expander_open);
405       priv->pixbuf_expander_open = (GdkPixbuf*) g_value_dup_object (value);
406       break;
407     case PROP_PIXBUF_EXPANDER_CLOSED:
408       if (priv->pixbuf_expander_closed)
409         g_object_unref (priv->pixbuf_expander_closed);
410       priv->pixbuf_expander_closed = (GdkPixbuf*) g_value_dup_object (value);
411       break;
412     case PROP_SURFACE:
413       take_image_definition (cellpixbuf, gtk_image_definition_new_surface (g_value_get_boxed (value)));
414       break;
415     case PROP_STOCK_ID:
416       take_image_definition (cellpixbuf, gtk_image_definition_new_stock (g_value_get_string (value)));
417       break;
418     case PROP_STOCK_SIZE:
419       priv->icon_size = g_value_get_uint (value);
420       break;
421     case PROP_STOCK_DETAIL:
422       g_free (priv->stock_detail);
423       priv->stock_detail = g_value_dup_string (value);
424       break;
425     case PROP_ICON_NAME:
426       take_image_definition (cellpixbuf, gtk_image_definition_new_icon_name (g_value_get_string (value)));
427       break;
428     case PROP_FOLLOW_STATE:
429       priv->follow_state = g_value_get_boolean (value);
430       break;
431     case PROP_GICON:
432       take_image_definition (cellpixbuf, gtk_image_definition_new_gicon (g_value_get_object (value)));
433       break;
434     default:
435       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
436       break;
437     }
438 }
439 
440 /**
441  * gtk_cell_renderer_pixbuf_new:
442  *
443  * Creates a new #GtkCellRendererPixbuf. Adjust rendering
444  * parameters using object properties. Object properties can be set
445  * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
446  * can bind a property to a value in a #GtkTreeModel. For example, you
447  * can bind the “pixbuf” property on the cell renderer to a pixbuf value
448  * in the model, thus rendering a different image in each row of the
449  * #GtkTreeView.
450  *
451  * Returns: the new cell renderer
452  **/
453 GtkCellRenderer *
gtk_cell_renderer_pixbuf_new(void)454 gtk_cell_renderer_pixbuf_new (void)
455 {
456   return g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF, NULL);
457 }
458 
459 static GtkIconHelper *
create_icon_helper(GtkCellRendererPixbuf * cellpixbuf,GtkWidget * widget)460 create_icon_helper (GtkCellRendererPixbuf *cellpixbuf,
461                     GtkWidget             *widget)
462 {
463   GtkCellRendererPixbufPrivate *priv = cellpixbuf->priv;
464   GtkIconHelper *helper;
465 
466   helper = gtk_icon_helper_new (gtk_style_context_get_node (gtk_widget_get_style_context (widget)), widget);
467   _gtk_icon_helper_set_use_fallback (helper, TRUE);
468   _gtk_icon_helper_set_force_scale_pixbuf (helper, TRUE);
469   _gtk_icon_helper_set_definition (helper, priv->image_def);
470   if (gtk_image_definition_get_storage_type (priv->image_def) != GTK_IMAGE_PIXBUF)
471     _gtk_icon_helper_set_icon_size (helper, priv->icon_size);
472 
473   return helper;
474 }
475 
476 static void
gtk_cell_renderer_pixbuf_get_size(GtkCellRenderer * cell,GtkWidget * widget,const GdkRectangle * cell_area,gint * x_offset,gint * y_offset,gint * width,gint * height)477 gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer    *cell,
478 				   GtkWidget          *widget,
479 				   const GdkRectangle *cell_area,
480 				   gint               *x_offset,
481 				   gint               *y_offset,
482 				   gint               *width,
483 				   gint               *height)
484 {
485   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
486   GtkCellRendererPixbufPrivate *priv = cellpixbuf->priv;
487   gint pixbuf_width  = 0;
488   gint pixbuf_height = 0;
489   gint calc_width;
490   gint calc_height;
491   gint xpad, ypad;
492   GtkStyleContext *context;
493   GtkIconHelper *icon_helper;
494 
495   context = gtk_widget_get_style_context (widget);
496   gtk_style_context_save (context);
497   gtk_style_context_add_class (context, GTK_STYLE_CLASS_IMAGE);
498   icon_helper = create_icon_helper (cellpixbuf, widget);
499 
500   if (!_gtk_icon_helper_get_is_empty (icon_helper))
501     _gtk_icon_helper_get_size (icon_helper,
502                                &pixbuf_width, &pixbuf_height);
503 
504   g_object_unref (icon_helper);
505   gtk_style_context_restore (context);
506 
507   if (priv->pixbuf_expander_open)
508     {
509       pixbuf_width  = MAX (pixbuf_width, gdk_pixbuf_get_width (priv->pixbuf_expander_open));
510       pixbuf_height = MAX (pixbuf_height, gdk_pixbuf_get_height (priv->pixbuf_expander_open));
511     }
512   if (priv->pixbuf_expander_closed)
513     {
514       pixbuf_width  = MAX (pixbuf_width, gdk_pixbuf_get_width (priv->pixbuf_expander_closed));
515       pixbuf_height = MAX (pixbuf_height, gdk_pixbuf_get_height (priv->pixbuf_expander_closed));
516     }
517 
518   gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
519   calc_width  = (gint) xpad * 2 + pixbuf_width;
520   calc_height = (gint) ypad * 2 + pixbuf_height;
521 
522   if (cell_area && pixbuf_width > 0 && pixbuf_height > 0)
523     {
524       gfloat xalign, yalign;
525 
526       gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
527       if (x_offset)
528 	{
529 	  *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
530                         (1.0 - xalign) : xalign) *
531                        (cell_area->width - calc_width));
532 	  *x_offset = MAX (*x_offset, 0);
533 	}
534       if (y_offset)
535 	{
536 	  *y_offset = (yalign *
537                        (cell_area->height - calc_height));
538           *y_offset = MAX (*y_offset, 0);
539 	}
540     }
541   else
542     {
543       if (x_offset) *x_offset = 0;
544       if (y_offset) *y_offset = 0;
545     }
546 
547   if (width)
548     *width = calc_width;
549 
550   if (height)
551     *height = calc_height;
552 }
553 
554 static void
gtk_cell_renderer_pixbuf_render(GtkCellRenderer * cell,cairo_t * cr,GtkWidget * widget,const GdkRectangle * background_area,const GdkRectangle * cell_area,GtkCellRendererState flags)555 gtk_cell_renderer_pixbuf_render (GtkCellRenderer      *cell,
556                                  cairo_t              *cr,
557 				 GtkWidget            *widget,
558 				 const GdkRectangle   *background_area,
559 				 const GdkRectangle   *cell_area,
560 				 GtkCellRendererState  flags)
561 
562 {
563   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
564   GtkCellRendererPixbufPrivate *priv = cellpixbuf->priv;
565   GtkStyleContext *context;
566   GdkRectangle pix_rect;
567   GdkRectangle draw_rect;
568   gboolean is_expander;
569   gint xpad, ypad;
570   GtkIconHelper *icon_helper = NULL;
571 
572   gtk_cell_renderer_pixbuf_get_size (cell, widget, (GdkRectangle *) cell_area,
573 				     &pix_rect.x,
574                                      &pix_rect.y,
575                                      &pix_rect.width,
576                                      &pix_rect.height);
577 
578   gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
579   pix_rect.x += cell_area->x + xpad;
580   pix_rect.y += cell_area->y + ypad;
581   pix_rect.width -= xpad * 2;
582   pix_rect.height -= ypad * 2;
583 
584   if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect))
585     return;
586 
587   context = gtk_widget_get_style_context (widget);
588   gtk_style_context_save (context);
589 
590   gtk_style_context_add_class (context, GTK_STYLE_CLASS_IMAGE);
591 
592   g_object_get (cell, "is-expander", &is_expander, NULL);
593   if (is_expander)
594     {
595       gboolean is_expanded;
596 
597       g_object_get (cell, "is-expanded", &is_expanded, NULL);
598 
599       if (is_expanded && priv->pixbuf_expander_open != NULL)
600         {
601           icon_helper = gtk_icon_helper_new (gtk_style_context_get_node (context), widget);
602           _gtk_icon_helper_set_pixbuf (icon_helper, priv->pixbuf_expander_open);
603         }
604       else if (!is_expanded && priv->pixbuf_expander_closed != NULL)
605         {
606           icon_helper = gtk_icon_helper_new (gtk_style_context_get_node (context), widget);
607           _gtk_icon_helper_set_pixbuf (icon_helper, priv->pixbuf_expander_closed);
608         }
609     }
610 
611   if (icon_helper == NULL)
612     icon_helper = create_icon_helper (cellpixbuf, widget);
613 
614   _gtk_icon_helper_draw (icon_helper,
615                          cr,
616                          pix_rect.x, pix_rect.y);
617   g_object_unref (icon_helper);
618 
619   gtk_style_context_restore (context);
620 }
621