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 | |
20 | #include "gtkcellrendererpixbuf.h" |
21 | |
22 | #include "gtkiconhelperprivate.h" |
23 | #include "gtkicontheme.h" |
24 | #include "gtkintl.h" |
25 | #include "gtkprivate.h" |
26 | #include "gtksnapshot.h" |
27 | #include "gtkstylecontextprivate.h" |
28 | #include "gtktypebuiltins.h" |
29 | |
30 | #include <cairo-gobject.h> |
31 | #include <stdlib.h> |
32 | |
33 | /** |
34 | * GtkCellRendererPixbuf: |
35 | * |
36 | * Renders a pixbuf in a cell |
37 | * |
38 | * A `GtkCellRendererPixbuf` can be used to render an image in a cell. It allows |
39 | * to render either a given `GdkPixbuf` (set via the |
40 | * `GtkCellRendererPixbuf:pixbuf` property) or a named icon (set via the |
41 | * `GtkCellRendererPixbuf:icon-name` property). |
42 | * |
43 | * To support the tree view, `GtkCellRendererPixbuf` also supports rendering two |
44 | * alternative pixbufs, when the `GtkCellRenderer:is-expander` property is %TRUE. |
45 | * If the `GtkCellRenderer:is-expanded property` is %TRUE and the |
46 | * `GtkCellRendererPixbuf:pixbuf-expander-open` property is set to a pixbuf, it |
47 | * renders that pixbuf, if the `GtkCellRenderer:is-expanded` property is %FALSE |
48 | * and the `GtkCellRendererPixbuf:pixbuf-expander-closed` property is set to a |
49 | * pixbuf, it renders that one. |
50 | */ |
51 | |
52 | |
53 | static void gtk_cell_renderer_pixbuf_get_property (GObject *object, |
54 | guint param_id, |
55 | GValue *value, |
56 | GParamSpec *pspec); |
57 | static void gtk_cell_renderer_pixbuf_set_property (GObject *object, |
58 | guint param_id, |
59 | const GValue *value, |
60 | GParamSpec *pspec); |
61 | static void gtk_cell_renderer_pixbuf_get_size (GtkCellRendererPixbuf *self, |
62 | GtkWidget *widget, |
63 | const GdkRectangle *rectangle, |
64 | int *x_offset, |
65 | int *y_offset, |
66 | int *width, |
67 | int *height); |
68 | static void gtk_cell_renderer_pixbuf_snapshot (GtkCellRenderer *cell, |
69 | GtkSnapshot *snapshot, |
70 | GtkWidget *widget, |
71 | const GdkRectangle *background_area, |
72 | const GdkRectangle *cell_area, |
73 | GtkCellRendererState flags); |
74 | |
75 | |
76 | enum { |
77 | PROP_0, |
78 | PROP_PIXBUF, |
79 | PROP_PIXBUF_EXPANDER_OPEN, |
80 | PROP_PIXBUF_EXPANDER_CLOSED, |
81 | PROP_TEXTURE, |
82 | PROP_ICON_SIZE, |
83 | PROP_ICON_NAME, |
84 | PROP_GICON |
85 | }; |
86 | |
87 | typedef struct _GtkCellRendererPixbufPrivate GtkCellRendererPixbufPrivate; |
88 | typedef struct _GtkCellRendererPixbufClass GtkCellRendererPixbufClass; |
89 | |
90 | struct _GtkCellRendererPixbuf |
91 | { |
92 | GtkCellRenderer parent; |
93 | }; |
94 | |
95 | struct _GtkCellRendererPixbufClass |
96 | { |
97 | GtkCellRendererClass parent_class; |
98 | }; |
99 | |
100 | struct _GtkCellRendererPixbufPrivate |
101 | { |
102 | GtkImageDefinition *image_def; |
103 | GtkIconSize icon_size; |
104 | |
105 | GdkPixbuf *pixbuf_expander_open; |
106 | GdkPixbuf *pixbuf_expander_closed; |
107 | GdkTexture *texture_expander_open; |
108 | GdkTexture *texture_expander_closed; |
109 | }; |
110 | |
111 | G_DEFINE_TYPE_WITH_PRIVATE (GtkCellRendererPixbuf, gtk_cell_renderer_pixbuf, GTK_TYPE_CELL_RENDERER) |
112 | |
113 | static void |
114 | gtk_cell_renderer_pixbuf_init (GtkCellRendererPixbuf *cellpixbuf) |
115 | { |
116 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self: cellpixbuf); |
117 | |
118 | priv->image_def = gtk_image_definition_new_empty (); |
119 | } |
120 | |
121 | static void |
122 | gtk_cell_renderer_pixbuf_finalize (GObject *object) |
123 | { |
124 | GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object); |
125 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self: cellpixbuf); |
126 | |
127 | gtk_image_definition_unref (def: priv->image_def); |
128 | |
129 | g_clear_object (&priv->pixbuf_expander_open); |
130 | g_clear_object (&priv->pixbuf_expander_closed); |
131 | g_clear_object (&priv->texture_expander_open); |
132 | g_clear_object (&priv->texture_expander_closed); |
133 | |
134 | G_OBJECT_CLASS (gtk_cell_renderer_pixbuf_parent_class)->finalize (object); |
135 | } |
136 | |
137 | static GtkSizeRequestMode |
138 | gtk_cell_renderer_pixbuf_get_request_mode (GtkCellRenderer *cell) |
139 | { |
140 | return GTK_SIZE_REQUEST_CONSTANT_SIZE; |
141 | } |
142 | |
143 | static void |
144 | gtk_cell_renderer_pixbuf_get_preferred_width (GtkCellRenderer *cell, |
145 | GtkWidget *widget, |
146 | int *minimum, |
147 | int *natural) |
148 | { |
149 | int size = 0; |
150 | |
151 | gtk_cell_renderer_pixbuf_get_size (GTK_CELL_RENDERER_PIXBUF (cell), widget, NULL, |
152 | NULL, NULL, width: &size, NULL); |
153 | |
154 | if (minimum != NULL) |
155 | *minimum = size; |
156 | |
157 | if (natural != NULL) |
158 | *natural = size; |
159 | } |
160 | |
161 | static void |
162 | gtk_cell_renderer_pixbuf_get_preferred_height (GtkCellRenderer *cell, |
163 | GtkWidget *widget, |
164 | int *minimum, |
165 | int *natural) |
166 | { |
167 | int size = 0; |
168 | |
169 | gtk_cell_renderer_pixbuf_get_size (GTK_CELL_RENDERER_PIXBUF (cell), widget, NULL, |
170 | NULL, NULL, NULL, height: &size); |
171 | |
172 | if (minimum != NULL) |
173 | *minimum = size; |
174 | |
175 | if (natural != NULL) |
176 | *natural = size; |
177 | } |
178 | |
179 | static void |
180 | gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class) |
181 | { |
182 | GObjectClass *object_class = G_OBJECT_CLASS (class); |
183 | GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class); |
184 | |
185 | object_class->finalize = gtk_cell_renderer_pixbuf_finalize; |
186 | |
187 | object_class->get_property = gtk_cell_renderer_pixbuf_get_property; |
188 | object_class->set_property = gtk_cell_renderer_pixbuf_set_property; |
189 | |
190 | cell_class->get_request_mode = gtk_cell_renderer_pixbuf_get_request_mode; |
191 | cell_class->get_preferred_width = gtk_cell_renderer_pixbuf_get_preferred_width; |
192 | cell_class->get_preferred_height = gtk_cell_renderer_pixbuf_get_preferred_height; |
193 | cell_class->snapshot = gtk_cell_renderer_pixbuf_snapshot; |
194 | |
195 | g_object_class_install_property (oclass: object_class, |
196 | property_id: PROP_PIXBUF, |
197 | pspec: g_param_spec_object (name: "pixbuf" , |
198 | P_("Pixbuf Object" ), |
199 | P_("The pixbuf to render" ), |
200 | GDK_TYPE_PIXBUF, |
201 | GTK_PARAM_WRITABLE)); |
202 | |
203 | g_object_class_install_property (oclass: object_class, |
204 | property_id: PROP_PIXBUF_EXPANDER_OPEN, |
205 | pspec: g_param_spec_object (name: "pixbuf-expander-open" , |
206 | P_("Pixbuf Expander Open" ), |
207 | P_("Pixbuf for open expander" ), |
208 | GDK_TYPE_PIXBUF, |
209 | GTK_PARAM_READWRITE)); |
210 | |
211 | g_object_class_install_property (oclass: object_class, |
212 | property_id: PROP_PIXBUF_EXPANDER_CLOSED, |
213 | pspec: g_param_spec_object (name: "pixbuf-expander-closed" , |
214 | P_("Pixbuf Expander Closed" ), |
215 | P_("Pixbuf for closed expander" ), |
216 | GDK_TYPE_PIXBUF, |
217 | GTK_PARAM_READWRITE)); |
218 | |
219 | /** |
220 | * GtkCellRendererPixbuf:texture: |
221 | */ |
222 | g_object_class_install_property (oclass: object_class, |
223 | property_id: PROP_TEXTURE, |
224 | pspec: g_param_spec_object (name: "texture" , |
225 | P_("Texture" ), |
226 | P_("The texture to render" ), |
227 | GDK_TYPE_TEXTURE, |
228 | GTK_PARAM_READWRITE)); |
229 | |
230 | /** |
231 | * GtkCellRendererPixbuf:icon-size: |
232 | * |
233 | * The `GtkIconSize` value that specifies the size of the rendered icon. |
234 | */ |
235 | g_object_class_install_property (oclass: object_class, |
236 | property_id: PROP_ICON_SIZE, |
237 | pspec: g_param_spec_enum (name: "icon-size" , |
238 | P_("Icon Size" ), |
239 | P_("The GtkIconSize value that specifies the size of the rendered icon" ), |
240 | enum_type: GTK_TYPE_ICON_SIZE, |
241 | default_value: GTK_ICON_SIZE_INHERIT, |
242 | GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY)); |
243 | |
244 | /** |
245 | * GtkCellRendererPixbuf:icon-name: |
246 | * |
247 | * The name of the themed icon to display. |
248 | * This property only has an effect if not overridden by the "pixbuf" property. |
249 | */ |
250 | g_object_class_install_property (oclass: object_class, |
251 | property_id: PROP_ICON_NAME, |
252 | pspec: g_param_spec_string (name: "icon-name" , |
253 | P_("Icon Name" ), |
254 | P_("The name of the icon from the icon theme" ), |
255 | NULL, |
256 | GTK_PARAM_READWRITE)); |
257 | |
258 | /** |
259 | * GtkCellRendererPixbuf:gicon: |
260 | * |
261 | * The GIcon representing the icon to display. |
262 | * If the icon theme is changed, the image will be updated |
263 | * automatically. |
264 | */ |
265 | g_object_class_install_property (oclass: object_class, |
266 | property_id: PROP_GICON, |
267 | pspec: g_param_spec_object (name: "gicon" , |
268 | P_("Icon" ), |
269 | P_("The GIcon being displayed" ), |
270 | G_TYPE_ICON, |
271 | GTK_PARAM_READWRITE)); |
272 | } |
273 | |
274 | static void |
275 | gtk_cell_renderer_pixbuf_get_property (GObject *object, |
276 | guint param_id, |
277 | GValue *value, |
278 | GParamSpec *pspec) |
279 | { |
280 | GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object); |
281 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self: cellpixbuf); |
282 | |
283 | switch (param_id) |
284 | { |
285 | case PROP_PIXBUF_EXPANDER_OPEN: |
286 | g_value_set_object (value, v_object: priv->pixbuf_expander_open); |
287 | break; |
288 | case PROP_PIXBUF_EXPANDER_CLOSED: |
289 | g_value_set_object (value, v_object: priv->pixbuf_expander_closed); |
290 | break; |
291 | case PROP_TEXTURE: |
292 | g_value_set_object (value, v_object: gtk_image_definition_get_paintable (def: priv->image_def)); |
293 | break; |
294 | case PROP_ICON_SIZE: |
295 | g_value_set_enum (value, v_enum: priv->icon_size); |
296 | break; |
297 | case PROP_ICON_NAME: |
298 | g_value_set_string (value, v_string: gtk_image_definition_get_icon_name (def: priv->image_def)); |
299 | break; |
300 | case PROP_GICON: |
301 | g_value_set_object (value, v_object: gtk_image_definition_get_gicon (def: priv->image_def)); |
302 | break; |
303 | default: |
304 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); |
305 | break; |
306 | } |
307 | } |
308 | |
309 | static void |
310 | notify_storage_type (GtkCellRendererPixbuf *cellpixbuf, |
311 | GtkImageType storage_type) |
312 | { |
313 | switch (storage_type) |
314 | { |
315 | case GTK_IMAGE_PAINTABLE: |
316 | g_object_notify (G_OBJECT (cellpixbuf), property_name: "texture" ); |
317 | break; |
318 | case GTK_IMAGE_ICON_NAME: |
319 | g_object_notify (G_OBJECT (cellpixbuf), property_name: "icon-name" ); |
320 | break; |
321 | case GTK_IMAGE_GICON: |
322 | g_object_notify (G_OBJECT (cellpixbuf), property_name: "gicon" ); |
323 | break; |
324 | default: |
325 | g_assert_not_reached (); |
326 | case GTK_IMAGE_EMPTY: |
327 | break; |
328 | } |
329 | } |
330 | |
331 | static void |
332 | take_image_definition (GtkCellRendererPixbuf *cellpixbuf, |
333 | GtkImageDefinition *def) |
334 | { |
335 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self: cellpixbuf); |
336 | GtkImageType old_storage_type, new_storage_type; |
337 | |
338 | if (def == NULL) |
339 | def = gtk_image_definition_new_empty (); |
340 | |
341 | old_storage_type = gtk_image_definition_get_storage_type (def: priv->image_def); |
342 | new_storage_type = gtk_image_definition_get_storage_type (def); |
343 | |
344 | if (new_storage_type != old_storage_type) |
345 | notify_storage_type (cellpixbuf, storage_type: old_storage_type); |
346 | |
347 | gtk_image_definition_unref (def: priv->image_def); |
348 | priv->image_def = def; |
349 | } |
350 | |
351 | static void |
352 | gtk_cell_renderer_pixbuf_set_icon_size (GtkCellRendererPixbuf *cellpixbuf, |
353 | GtkIconSize icon_size) |
354 | { |
355 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self: cellpixbuf); |
356 | |
357 | if (priv->icon_size == icon_size) |
358 | return; |
359 | |
360 | priv->icon_size = icon_size; |
361 | g_object_notify (G_OBJECT (cellpixbuf), property_name: "icon-size" ); |
362 | } |
363 | |
364 | static void |
365 | gtk_cell_renderer_pixbuf_set_property (GObject *object, |
366 | guint param_id, |
367 | const GValue *value, |
368 | GParamSpec *pspec) |
369 | { |
370 | GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object); |
371 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self: cellpixbuf); |
372 | GdkTexture *texture; |
373 | GdkPixbuf *pixbuf; |
374 | |
375 | switch (param_id) |
376 | { |
377 | case PROP_PIXBUF: |
378 | pixbuf = g_value_get_object (value); |
379 | if (pixbuf) |
380 | texture = gdk_texture_new_for_pixbuf (pixbuf); |
381 | else |
382 | texture = NULL; |
383 | take_image_definition (cellpixbuf, def: gtk_image_definition_new_paintable (paintable: GDK_PAINTABLE (ptr: texture))); |
384 | break; |
385 | case PROP_PIXBUF_EXPANDER_OPEN: |
386 | g_clear_object (&priv->pixbuf_expander_open); |
387 | g_clear_object (&priv->texture_expander_open); |
388 | priv->pixbuf_expander_open = (GdkPixbuf*) g_value_dup_object (value); |
389 | priv->texture_expander_open = gdk_texture_new_for_pixbuf (pixbuf: priv->pixbuf_expander_open); |
390 | break; |
391 | case PROP_PIXBUF_EXPANDER_CLOSED: |
392 | g_clear_object (&priv->pixbuf_expander_closed); |
393 | g_clear_object (&priv->texture_expander_closed); |
394 | priv->pixbuf_expander_closed = (GdkPixbuf*) g_value_dup_object (value); |
395 | priv->texture_expander_closed = gdk_texture_new_for_pixbuf (pixbuf: priv->pixbuf_expander_open); |
396 | break; |
397 | case PROP_TEXTURE: |
398 | take_image_definition (cellpixbuf, def: gtk_image_definition_new_paintable (paintable: g_value_get_object (value))); |
399 | break; |
400 | case PROP_ICON_SIZE: |
401 | gtk_cell_renderer_pixbuf_set_icon_size (cellpixbuf, icon_size: g_value_get_enum (value)); |
402 | break; |
403 | case PROP_ICON_NAME: |
404 | take_image_definition (cellpixbuf, def: gtk_image_definition_new_icon_name (icon_name: g_value_get_string (value))); |
405 | break; |
406 | case PROP_GICON: |
407 | take_image_definition (cellpixbuf, def: gtk_image_definition_new_gicon (gicon: g_value_get_object (value))); |
408 | break; |
409 | default: |
410 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); |
411 | break; |
412 | } |
413 | } |
414 | |
415 | /** |
416 | * gtk_cell_renderer_pixbuf_new: |
417 | * |
418 | * Creates a new `GtkCellRendererPixbuf`. Adjust rendering |
419 | * parameters using object properties. Object properties can be set |
420 | * globally (with g_object_set()). Also, with `GtkTreeViewColumn`, you |
421 | * can bind a property to a value in a `GtkTreeModel`. For example, you |
422 | * can bind the “pixbuf” property on the cell renderer to a pixbuf value |
423 | * in the model, thus rendering a different image in each row of the |
424 | * `GtkTreeView`. |
425 | * |
426 | * Returns: the new cell renderer |
427 | **/ |
428 | GtkCellRenderer * |
429 | gtk_cell_renderer_pixbuf_new (void) |
430 | { |
431 | return g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF, NULL); |
432 | } |
433 | |
434 | static GtkIconHelper * |
435 | create_icon_helper (GtkCellRendererPixbuf *cellpixbuf, |
436 | GtkWidget *widget) |
437 | { |
438 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self: cellpixbuf); |
439 | GtkIconHelper *icon_helper; |
440 | |
441 | icon_helper = gtk_icon_helper_new (css_node: gtk_style_context_get_node (context: gtk_widget_get_style_context (widget)), |
442 | owner: widget); |
443 | _gtk_icon_helper_set_use_fallback (self: icon_helper, TRUE); |
444 | _gtk_icon_helper_set_definition (self: icon_helper, def: priv->image_def); |
445 | |
446 | return icon_helper; |
447 | } |
448 | |
449 | static void |
450 | gtk_cell_renderer_pixbuf_get_size (GtkCellRendererPixbuf *self, |
451 | GtkWidget *widget, |
452 | const GdkRectangle *cell_area, |
453 | int *x_offset, |
454 | int *y_offset, |
455 | int *width, |
456 | int *height) |
457 | { |
458 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self); |
459 | GtkCellRenderer *cell = GTK_CELL_RENDERER (self); |
460 | int pixbuf_width; |
461 | int pixbuf_height; |
462 | int calc_width; |
463 | int calc_height; |
464 | int xpad, ypad; |
465 | GtkStyleContext *context; |
466 | GtkIconHelper *icon_helper; |
467 | |
468 | context = gtk_widget_get_style_context (widget); |
469 | gtk_style_context_save (context); |
470 | gtk_style_context_add_class (context, class_name: "image" ); |
471 | gtk_icon_size_set_style_classes (cssnode: gtk_style_context_get_node (context), icon_size: priv->icon_size); |
472 | icon_helper = create_icon_helper (cellpixbuf: self, widget); |
473 | |
474 | if (_gtk_icon_helper_get_is_empty (self: icon_helper)) |
475 | pixbuf_width = pixbuf_height = 0; |
476 | else if (gtk_image_definition_get_paintable (def: priv->image_def)) |
477 | { |
478 | GdkPaintable *paintable = gtk_image_definition_get_paintable (def: priv->image_def); |
479 | pixbuf_width = gdk_paintable_get_intrinsic_width (paintable); |
480 | pixbuf_height = gdk_paintable_get_intrinsic_height (paintable); |
481 | } |
482 | else |
483 | pixbuf_width = pixbuf_height = gtk_icon_helper_get_size (self: icon_helper); |
484 | |
485 | g_object_unref (object: icon_helper); |
486 | gtk_style_context_restore (context); |
487 | |
488 | if (priv->pixbuf_expander_open) |
489 | { |
490 | pixbuf_width = MAX (pixbuf_width, gdk_pixbuf_get_width (priv->pixbuf_expander_open)); |
491 | pixbuf_height = MAX (pixbuf_height, gdk_pixbuf_get_height (priv->pixbuf_expander_open)); |
492 | } |
493 | if (priv->pixbuf_expander_closed) |
494 | { |
495 | pixbuf_width = MAX (pixbuf_width, gdk_pixbuf_get_width (priv->pixbuf_expander_closed)); |
496 | pixbuf_height = MAX (pixbuf_height, gdk_pixbuf_get_height (priv->pixbuf_expander_closed)); |
497 | } |
498 | |
499 | gtk_cell_renderer_get_padding (cell, xpad: &xpad, ypad: &ypad); |
500 | calc_width = (int) xpad * 2 + pixbuf_width; |
501 | calc_height = (int) ypad * 2 + pixbuf_height; |
502 | |
503 | if (cell_area && pixbuf_width > 0 && pixbuf_height > 0) |
504 | { |
505 | float xalign, yalign; |
506 | |
507 | gtk_cell_renderer_get_alignment (cell, xalign: &xalign, yalign: &yalign); |
508 | if (x_offset) |
509 | { |
510 | *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? |
511 | (1.0 - xalign) : xalign) * |
512 | (cell_area->width - calc_width)); |
513 | *x_offset = MAX (*x_offset, 0); |
514 | } |
515 | if (y_offset) |
516 | { |
517 | *y_offset = (yalign * |
518 | (cell_area->height - calc_height)); |
519 | *y_offset = MAX (*y_offset, 0); |
520 | } |
521 | } |
522 | else |
523 | { |
524 | if (x_offset) *x_offset = 0; |
525 | if (y_offset) *y_offset = 0; |
526 | } |
527 | |
528 | if (width) |
529 | *width = calc_width; |
530 | |
531 | if (height) |
532 | *height = calc_height; |
533 | } |
534 | |
535 | static void |
536 | gtk_cell_renderer_pixbuf_snapshot (GtkCellRenderer *cell, |
537 | GtkSnapshot *snapshot, |
538 | GtkWidget *widget, |
539 | const GdkRectangle *background_area, |
540 | const GdkRectangle *cell_area, |
541 | GtkCellRendererState flags) |
542 | |
543 | { |
544 | GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (cell); |
545 | GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self: cellpixbuf); |
546 | GtkStyleContext *context; |
547 | GdkRectangle pix_rect; |
548 | gboolean is_expander; |
549 | int xpad, ypad; |
550 | GtkIconHelper *icon_helper; |
551 | |
552 | gtk_cell_renderer_pixbuf_get_size (self: cellpixbuf, widget, |
553 | cell_area, |
554 | x_offset: &pix_rect.x, |
555 | y_offset: &pix_rect.y, |
556 | width: &pix_rect.width, |
557 | height: &pix_rect.height); |
558 | |
559 | gtk_cell_renderer_get_padding (cell, xpad: &xpad, ypad: &ypad); |
560 | pix_rect.x += cell_area->x + xpad; |
561 | pix_rect.y += cell_area->y + ypad; |
562 | pix_rect.width -= xpad * 2; |
563 | pix_rect.height -= ypad * 2; |
564 | |
565 | if (!gdk_rectangle_intersect (src1: cell_area, src2: &pix_rect, NULL)) |
566 | return; |
567 | |
568 | context = gtk_widget_get_style_context (widget); |
569 | gtk_style_context_save (context); |
570 | |
571 | gtk_style_context_add_class (context, class_name: "image" ); |
572 | gtk_icon_size_set_style_classes (cssnode: gtk_style_context_get_node (context), icon_size: priv->icon_size); |
573 | |
574 | is_expander = gtk_cell_renderer_get_is_expander (cell); |
575 | if (is_expander) |
576 | { |
577 | gboolean is_expanded = gtk_cell_renderer_get_is_expanded (cell);; |
578 | |
579 | if (is_expanded && priv->pixbuf_expander_open != NULL) |
580 | { |
581 | icon_helper = gtk_icon_helper_new (css_node: gtk_style_context_get_node (context), owner: widget); |
582 | _gtk_icon_helper_set_paintable (self: icon_helper, paintable: GDK_PAINTABLE (ptr: priv->texture_expander_open)); |
583 | } |
584 | else if (!is_expanded && priv->pixbuf_expander_closed != NULL) |
585 | { |
586 | icon_helper = gtk_icon_helper_new (css_node: gtk_style_context_get_node (context), owner: widget); |
587 | _gtk_icon_helper_set_paintable (self: icon_helper, paintable: GDK_PAINTABLE (ptr: priv->texture_expander_closed)); |
588 | } |
589 | else |
590 | { |
591 | icon_helper = create_icon_helper (cellpixbuf, widget); |
592 | } |
593 | } |
594 | else |
595 | { |
596 | icon_helper = create_icon_helper (cellpixbuf, widget); |
597 | } |
598 | |
599 | gtk_snapshot_save (snapshot); |
600 | gtk_snapshot_translate (snapshot, point: &GRAPHENE_POINT_INIT (pix_rect.x, pix_rect.y)); |
601 | gdk_paintable_snapshot (paintable: GDK_PAINTABLE (ptr: icon_helper), snapshot, width: pix_rect.width, height: pix_rect.height); |
602 | gtk_snapshot_restore (snapshot); |
603 | |
604 | g_object_unref (object: icon_helper); |
605 | gtk_style_context_restore (context); |
606 | } |
607 | |