1 | /* GTK - The GIMP Toolkit |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser 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 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | /* |
19 | * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS |
20 | * file for a list of people on the GTK+ Team. See the ChangeLog |
21 | * files for a list of changes. These files are distributed with |
22 | * GTK+ at ftp://ftp.gtk.org/pub/gtk/. |
23 | */ |
24 | |
25 | #include "config.h" |
26 | |
27 | #include "gtkimageprivate.h" |
28 | |
29 | #include "gtkiconhelperprivate.h" |
30 | #include "gtkicontheme.h" |
31 | #include "gtkintl.h" |
32 | #include "gtkprivate.h" |
33 | #include "gtksnapshot.h" |
34 | #include "gtktypebuiltins.h" |
35 | #include "gtkwidgetprivate.h" |
36 | #include "gdkpixbufutilsprivate.h" |
37 | |
38 | #include <math.h> |
39 | #include <string.h> |
40 | #include <cairo-gobject.h> |
41 | |
42 | /** |
43 | * GtkImage: |
44 | * |
45 | * The `GtkImage` widget displays an image. |
46 | * |
47 | * ![An example GtkImage](image.png) |
48 | * |
49 | * Various kinds of object can be displayed as an image; most typically, |
50 | * you would load a `GdkTexture` from a file, using the convenience function |
51 | * [ctor@Gtk.Image.new_from_file], for instance: |
52 | * |
53 | * ```c |
54 | * GtkWidget *image = gtk_image_new_from_file ("myfile.png"); |
55 | * ``` |
56 | * |
57 | * If the file isn’t loaded successfully, the image will contain a |
58 | * “broken image” icon similar to that used in many web browsers. |
59 | * |
60 | * If you want to handle errors in loading the file yourself, |
61 | * for example by displaying an error message, then load the image with |
62 | * [ctor@Gdk.Texture.new_from_file], then create the `GtkImage` with |
63 | * [ctor@Gtk.Image.new_from_paintable]. |
64 | * |
65 | * Sometimes an application will want to avoid depending on external data |
66 | * files, such as image files. See the documentation of `GResource` inside |
67 | * GIO, for details. In this case, [property@Gtk.Image:resource], |
68 | * [ctor@Gtk.Image.new_from_resource], and [method@Gtk.Image.set_from_resource] |
69 | * should be used. |
70 | * |
71 | * `GtkImage` displays its image as an icon, with a size that is determined |
72 | * by the application. See [class@Gtk.Picture] if you want to show an image |
73 | * at is actual size. |
74 | * |
75 | * ## CSS nodes |
76 | * |
77 | * `GtkImage` has a single CSS node with the name `image`. The style classes |
78 | * `.normal-icons` or `.large-icons` may appear, depending on the |
79 | * [property@Gtk.Image:icon-size] property. |
80 | * |
81 | * ## Accessibility |
82 | * |
83 | * `GtkImage` uses the `GTK_ACCESSIBLE_ROLE_IMG` role. |
84 | */ |
85 | |
86 | typedef struct _GtkImageClass GtkImageClass; |
87 | |
88 | struct _GtkImage |
89 | { |
90 | GtkWidget parent_instance; |
91 | |
92 | GtkIconHelper *icon_helper; |
93 | GtkIconSize icon_size; |
94 | |
95 | float baseline_align; |
96 | |
97 | char *filename; |
98 | char *resource_path; |
99 | }; |
100 | |
101 | struct _GtkImageClass |
102 | { |
103 | GtkWidgetClass parent_class; |
104 | }; |
105 | |
106 | |
107 | static void gtk_image_snapshot (GtkWidget *widget, |
108 | GtkSnapshot *snapshot); |
109 | static void gtk_image_unrealize (GtkWidget *widget); |
110 | static void gtk_image_measure (GtkWidget *widget, |
111 | GtkOrientation orientation, |
112 | int for_size, |
113 | int *minimum, |
114 | int *natural, |
115 | int *minimum_baseline, |
116 | int *natural_baseline); |
117 | |
118 | static void gtk_image_css_changed (GtkWidget *widget, |
119 | GtkCssStyleChange *change); |
120 | static void gtk_image_system_setting_changed (GtkWidget *widget, |
121 | GtkSystemSetting setting); |
122 | static void gtk_image_finalize (GObject *object); |
123 | |
124 | static void gtk_image_set_property (GObject *object, |
125 | guint prop_id, |
126 | const GValue *value, |
127 | GParamSpec *pspec); |
128 | static void gtk_image_get_property (GObject *object, |
129 | guint prop_id, |
130 | GValue *value, |
131 | GParamSpec *pspec); |
132 | |
133 | enum |
134 | { |
135 | PROP_0, |
136 | PROP_PAINTABLE, |
137 | PROP_FILE, |
138 | PROP_ICON_SIZE, |
139 | PROP_PIXEL_SIZE, |
140 | PROP_ICON_NAME, |
141 | PROP_STORAGE_TYPE, |
142 | PROP_GICON, |
143 | PROP_RESOURCE, |
144 | PROP_USE_FALLBACK, |
145 | NUM_PROPERTIES |
146 | }; |
147 | |
148 | static GParamSpec *image_props[NUM_PROPERTIES] = { NULL, }; |
149 | |
150 | G_DEFINE_TYPE (GtkImage, gtk_image, GTK_TYPE_WIDGET) |
151 | |
152 | static void |
153 | gtk_image_class_init (GtkImageClass *class) |
154 | { |
155 | GObjectClass *gobject_class; |
156 | GtkWidgetClass *widget_class; |
157 | |
158 | gobject_class = G_OBJECT_CLASS (class); |
159 | |
160 | gobject_class->set_property = gtk_image_set_property; |
161 | gobject_class->get_property = gtk_image_get_property; |
162 | gobject_class->finalize = gtk_image_finalize; |
163 | |
164 | widget_class = GTK_WIDGET_CLASS (class); |
165 | widget_class->snapshot = gtk_image_snapshot; |
166 | widget_class->measure = gtk_image_measure; |
167 | widget_class->unrealize = gtk_image_unrealize; |
168 | widget_class->css_changed = gtk_image_css_changed; |
169 | widget_class->system_setting_changed = gtk_image_system_setting_changed; |
170 | |
171 | /** |
172 | * GtkImage:paintable: (attributes org.gtk.Property.get=gtk_image_get_paintable org.gtk.Property.set=gtk_image_set_from_paintable) |
173 | * |
174 | * The `GdkPaintable` to display. |
175 | */ |
176 | image_props[PROP_PAINTABLE] = |
177 | g_param_spec_object (name: "paintable" , |
178 | P_("Paintable" ), |
179 | P_("A GdkPaintable to display" ), |
180 | GDK_TYPE_PAINTABLE, |
181 | GTK_PARAM_READWRITE); |
182 | |
183 | /** |
184 | * GtkImage:file: (attributes org.gtk.Property.set=gtk_image_set_from_file) |
185 | * |
186 | * The `GFile to display. |
187 | */ |
188 | image_props[PROP_FILE] = |
189 | g_param_spec_string (name: "file" , |
190 | P_("Filename" ), |
191 | P_("Filename to load and display" ), |
192 | NULL, |
193 | GTK_PARAM_READWRITE); |
194 | |
195 | /** |
196 | * GtkImage:icon-size: (attributes org.gtk.Property.get=gtk_image_get_icon_size org.gtk.Property.set=gtk_image_set_icon_size org.gtk.Property.set=gtk_image_set_icon_size) |
197 | * |
198 | * The symbolic size to display icons at. |
199 | */ |
200 | image_props[PROP_ICON_SIZE] = |
201 | g_param_spec_enum (name: "icon-size" , |
202 | P_("Icon size" ), |
203 | P_("Symbolic size to use for icon set or named icon" ), |
204 | enum_type: GTK_TYPE_ICON_SIZE, |
205 | default_value: GTK_ICON_SIZE_INHERIT, |
206 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); |
207 | |
208 | /** |
209 | * GtkImage:pixel-size: (attributes org.gtk.Property.get=gtk_image_get_pixel_size org.gtk.Property.set=gtk_image_set_pixel_size) |
210 | * |
211 | * The size in pixels to display icons at. |
212 | * |
213 | * If set to a value != -1, this property overrides the |
214 | * [property@Gtk.Image:icon-size] property for images of type |
215 | * `GTK_IMAGE_ICON_NAME`. |
216 | */ |
217 | image_props[PROP_PIXEL_SIZE] = |
218 | g_param_spec_int (name: "pixel-size" , |
219 | P_("Pixel size" ), |
220 | P_("Pixel size to use for named icon" ), |
221 | minimum: -1, G_MAXINT, |
222 | default_value: -1, |
223 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); |
224 | |
225 | /** |
226 | * GtkImage:icon-name: (attributes org.gtk.Property.get=gtk_image_get_icon_name org.gtk.Property.set=gtk_image_set_from_icon_name) |
227 | * |
228 | * The name of the icon in the icon theme. |
229 | * |
230 | * If the icon theme is changed, the image will be updated automatically. |
231 | */ |
232 | image_props[PROP_ICON_NAME] = |
233 | g_param_spec_string (name: "icon-name" , |
234 | P_("Icon Name" ), |
235 | P_("The name of the icon from the icon theme" ), |
236 | NULL, |
237 | GTK_PARAM_READWRITE); |
238 | |
239 | /** |
240 | * GtkImage:gicon: (attributes org.gtk.Property.get=gtk_image_get_gicon org.gtk.Property.set=gtk_image_set_from_gicon) |
241 | * |
242 | * The `GIcon` displayed in the GtkImage. |
243 | * |
244 | * For themed icons, If the icon theme is changed, the image will be updated |
245 | * automatically. |
246 | */ |
247 | image_props[PROP_GICON] = |
248 | g_param_spec_object (name: "gicon" , |
249 | P_("Icon" ), |
250 | P_("The GIcon being displayed" ), |
251 | G_TYPE_ICON, |
252 | GTK_PARAM_READWRITE); |
253 | |
254 | /** |
255 | * GtkImage:resource: (attributes org.gtk.Property.set=gtk_image_set_from_resource) |
256 | * |
257 | * A path to a resource file to display. |
258 | */ |
259 | image_props[PROP_RESOURCE] = |
260 | g_param_spec_string (name: "resource" , |
261 | P_("Resource" ), |
262 | P_("The resource path being displayed" ), |
263 | NULL, |
264 | GTK_PARAM_READWRITE); |
265 | |
266 | /** |
267 | * GtkImage:storage-type: (attributes org.gtk.Property.get=gtk_image_get_storage_type) |
268 | * |
269 | * The representation being used for image data. |
270 | */ |
271 | image_props[PROP_STORAGE_TYPE] = |
272 | g_param_spec_enum (name: "storage-type" , |
273 | P_("Storage type" ), |
274 | P_("The representation being used for image data" ), |
275 | enum_type: GTK_TYPE_IMAGE_TYPE, |
276 | default_value: GTK_IMAGE_EMPTY, |
277 | GTK_PARAM_READABLE); |
278 | |
279 | /** |
280 | * GtkImage:use-fallback: |
281 | * |
282 | * Whether the icon displayed in the `GtkImage` will use |
283 | * standard icon names fallback. |
284 | * |
285 | * The value of this property is only relevant for images of type |
286 | * %GTK_IMAGE_ICON_NAME and %GTK_IMAGE_GICON. |
287 | */ |
288 | image_props[PROP_USE_FALLBACK] = |
289 | g_param_spec_boolean (name: "use-fallback" , |
290 | P_("Use Fallback" ), |
291 | P_("Whether to use icon names fallback" ), |
292 | FALSE, |
293 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); |
294 | |
295 | g_object_class_install_properties (oclass: gobject_class, n_pspecs: NUM_PROPERTIES, pspecs: image_props); |
296 | |
297 | gtk_widget_class_set_css_name (widget_class, I_("image" )); |
298 | |
299 | gtk_widget_class_set_accessible_role (widget_class, accessible_role: GTK_ACCESSIBLE_ROLE_IMG); |
300 | } |
301 | |
302 | static void |
303 | gtk_image_init (GtkImage *image) |
304 | { |
305 | GtkCssNode *widget_node; |
306 | |
307 | widget_node = gtk_widget_get_css_node (GTK_WIDGET (image)); |
308 | |
309 | image->icon_helper = gtk_icon_helper_new (css_node: widget_node, GTK_WIDGET (image)); |
310 | } |
311 | |
312 | static void |
313 | gtk_image_finalize (GObject *object) |
314 | { |
315 | GtkImage *image = GTK_IMAGE (object); |
316 | |
317 | gtk_image_clear (image); |
318 | |
319 | g_clear_object (&image->icon_helper); |
320 | |
321 | g_free (mem: image->filename); |
322 | g_free (mem: image->resource_path); |
323 | |
324 | G_OBJECT_CLASS (gtk_image_parent_class)->finalize (object); |
325 | }; |
326 | |
327 | static void |
328 | gtk_image_set_property (GObject *object, |
329 | guint prop_id, |
330 | const GValue *value, |
331 | GParamSpec *pspec) |
332 | { |
333 | GtkImage *image = GTK_IMAGE (object); |
334 | |
335 | switch (prop_id) |
336 | { |
337 | case PROP_PAINTABLE: |
338 | gtk_image_set_from_paintable (image, paintable: g_value_get_object (value)); |
339 | break; |
340 | case PROP_FILE: |
341 | gtk_image_set_from_file (image, filename: g_value_get_string (value)); |
342 | break; |
343 | case PROP_ICON_SIZE: |
344 | gtk_image_set_icon_size (image, icon_size: g_value_get_enum (value)); |
345 | break; |
346 | case PROP_PIXEL_SIZE: |
347 | gtk_image_set_pixel_size (image, pixel_size: g_value_get_int (value)); |
348 | break; |
349 | case PROP_ICON_NAME: |
350 | gtk_image_set_from_icon_name (image, icon_name: g_value_get_string (value)); |
351 | break; |
352 | case PROP_GICON: |
353 | gtk_image_set_from_gicon (image, icon: g_value_get_object (value)); |
354 | break; |
355 | case PROP_RESOURCE: |
356 | gtk_image_set_from_resource (image, resource_path: g_value_get_string (value)); |
357 | break; |
358 | |
359 | case PROP_USE_FALLBACK: |
360 | if (_gtk_icon_helper_set_use_fallback (self: image->icon_helper, use_fallback: g_value_get_boolean (value))) |
361 | g_object_notify_by_pspec (object, pspec); |
362 | break; |
363 | |
364 | default: |
365 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
366 | break; |
367 | } |
368 | } |
369 | |
370 | static void |
371 | gtk_image_get_property (GObject *object, |
372 | guint prop_id, |
373 | GValue *value, |
374 | GParamSpec *pspec) |
375 | { |
376 | GtkImage *image = GTK_IMAGE (object); |
377 | |
378 | switch (prop_id) |
379 | { |
380 | case PROP_PAINTABLE: |
381 | g_value_set_object (value, v_object: _gtk_icon_helper_peek_paintable (self: image->icon_helper)); |
382 | break; |
383 | case PROP_FILE: |
384 | g_value_set_string (value, v_string: image->filename); |
385 | break; |
386 | case PROP_ICON_SIZE: |
387 | g_value_set_enum (value, v_enum: image->icon_size); |
388 | break; |
389 | case PROP_PIXEL_SIZE: |
390 | g_value_set_int (value, v_int: _gtk_icon_helper_get_pixel_size (self: image->icon_helper)); |
391 | break; |
392 | case PROP_ICON_NAME: |
393 | g_value_set_string (value, v_string: _gtk_icon_helper_get_icon_name (self: image->icon_helper)); |
394 | break; |
395 | case PROP_GICON: |
396 | g_value_set_object (value, v_object: _gtk_icon_helper_peek_gicon (self: image->icon_helper)); |
397 | break; |
398 | case PROP_RESOURCE: |
399 | g_value_set_string (value, v_string: image->resource_path); |
400 | break; |
401 | case PROP_USE_FALLBACK: |
402 | g_value_set_boolean (value, v_boolean: _gtk_icon_helper_get_use_fallback (self: image->icon_helper)); |
403 | break; |
404 | case PROP_STORAGE_TYPE: |
405 | g_value_set_enum (value, v_enum: _gtk_icon_helper_get_storage_type (self: image->icon_helper)); |
406 | break; |
407 | default: |
408 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
409 | break; |
410 | } |
411 | } |
412 | |
413 | |
414 | /** |
415 | * gtk_image_new_from_file: |
416 | * @filename: (type filename): a filename |
417 | * |
418 | * Creates a new `GtkImage` displaying the file @filename. |
419 | * |
420 | * If the file isn’t found or can’t be loaded, the resulting `GtkImage` |
421 | * will display a “broken image” icon. This function never returns %NULL, |
422 | * it always returns a valid `GtkImage` widget. |
423 | * |
424 | * If you need to detect failures to load the file, use |
425 | * [ctor@Gdk.Texture.new_from_file] to load the file yourself, |
426 | * then create the `GtkImage` from the texture. |
427 | * |
428 | * The storage type (see [method@Gtk.Image.get_storage_type]) |
429 | * of the returned image is not defined, it will be whatever |
430 | * is appropriate for displaying the file. |
431 | * |
432 | * Returns: a new `GtkImage` |
433 | */ |
434 | GtkWidget* |
435 | gtk_image_new_from_file (const char *filename) |
436 | { |
437 | GtkImage *image; |
438 | |
439 | image = g_object_new (GTK_TYPE_IMAGE, NULL); |
440 | |
441 | gtk_image_set_from_file (image, filename); |
442 | |
443 | return GTK_WIDGET (image); |
444 | } |
445 | |
446 | /** |
447 | * gtk_image_new_from_resource: |
448 | * @resource_path: a resource path |
449 | * |
450 | * Creates a new `GtkImage` displaying the resource file @resource_path. |
451 | * |
452 | * If the file isn’t found or can’t be loaded, the resulting `GtkImage` will |
453 | * display a “broken image” icon. This function never returns %NULL, |
454 | * it always returns a valid `GtkImage` widget. |
455 | * |
456 | * If you need to detect failures to load the file, use |
457 | * [ctor@GdkPixbuf.Pixbuf.new_from_file] to load the file yourself, |
458 | * then create the `GtkImage` from the pixbuf. |
459 | * |
460 | * The storage type (see [method@Gtk.Image.get_storage_type]) of |
461 | * the returned image is not defined, it will be whatever is |
462 | * appropriate for displaying the file. |
463 | * |
464 | * Returns: a new `GtkImage` |
465 | */ |
466 | GtkWidget* |
467 | gtk_image_new_from_resource (const char *resource_path) |
468 | { |
469 | GtkImage *image; |
470 | |
471 | image = g_object_new (GTK_TYPE_IMAGE, NULL); |
472 | |
473 | gtk_image_set_from_resource (image, resource_path); |
474 | |
475 | return GTK_WIDGET (image); |
476 | } |
477 | |
478 | /** |
479 | * gtk_image_new_from_pixbuf: |
480 | * @pixbuf: (nullable): a `GdkPixbuf` |
481 | * |
482 | * Creates a new `GtkImage` displaying @pixbuf. |
483 | * |
484 | * The `GtkImage` does not assume a reference to the pixbuf; you still |
485 | * need to unref it if you own references. `GtkImage` will add its own |
486 | * reference rather than adopting yours. |
487 | * |
488 | * This is a helper for [ctor@Gtk.Image.new_from_paintable], and you can't |
489 | * get back the exact pixbuf once this is called, only a texture. |
490 | * |
491 | * Note that this function just creates an `GtkImage` from the pixbuf. |
492 | * The `GtkImage` created will not react to state changes. Should you |
493 | * want that, you should use [ctor@Gtk.Image.new_from_icon_name]. |
494 | * |
495 | * Returns: a new `GtkImage` |
496 | */ |
497 | GtkWidget* |
498 | gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf) |
499 | { |
500 | GtkImage *image; |
501 | |
502 | image = g_object_new (GTK_TYPE_IMAGE, NULL); |
503 | |
504 | gtk_image_set_from_pixbuf (image, pixbuf); |
505 | |
506 | return GTK_WIDGET (image); |
507 | } |
508 | |
509 | /** |
510 | * gtk_image_new_from_paintable: |
511 | * @paintable: (nullable): a `GdkPaintable` |
512 | * |
513 | * Creates a new `GtkImage` displaying @paintable. |
514 | * |
515 | * The `GtkImage` does not assume a reference to the paintable; you still |
516 | * need to unref it if you own references. `GtkImage` will add its own |
517 | * reference rather than adopting yours. |
518 | * |
519 | * The `GtkImage` will track changes to the @paintable and update |
520 | * its size and contents in response to it. |
521 | * |
522 | * Returns: a new `GtkImage` |
523 | */ |
524 | GtkWidget* |
525 | gtk_image_new_from_paintable (GdkPaintable *paintable) |
526 | { |
527 | GtkImage *image; |
528 | |
529 | image = g_object_new (GTK_TYPE_IMAGE, NULL); |
530 | |
531 | gtk_image_set_from_paintable (image, paintable); |
532 | |
533 | return GTK_WIDGET (image); |
534 | } |
535 | |
536 | /** |
537 | * gtk_image_new_from_icon_name: |
538 | * @icon_name: (nullable): an icon name |
539 | * |
540 | * Creates a `GtkImage` displaying an icon from the current icon theme. |
541 | * |
542 | * If the icon name isn’t known, a “broken image” icon will be |
543 | * displayed instead. If the current icon theme is changed, the icon |
544 | * will be updated appropriately. |
545 | * |
546 | * Returns: a new `GtkImage` displaying the themed icon |
547 | */ |
548 | GtkWidget* |
549 | gtk_image_new_from_icon_name (const char *icon_name) |
550 | { |
551 | GtkImage *image; |
552 | |
553 | image = g_object_new (GTK_TYPE_IMAGE, NULL); |
554 | |
555 | gtk_image_set_from_icon_name (image, icon_name); |
556 | |
557 | return GTK_WIDGET (image); |
558 | } |
559 | |
560 | /** |
561 | * gtk_image_new_from_gicon: |
562 | * @icon: an icon |
563 | * |
564 | * Creates a `GtkImage` displaying an icon from the current icon theme. |
565 | * |
566 | * If the icon name isn’t known, a “broken image” icon will be |
567 | * displayed instead. If the current icon theme is changed, the icon |
568 | * will be updated appropriately. |
569 | * |
570 | * Returns: a new `GtkImage` displaying the themed icon |
571 | */ |
572 | GtkWidget* |
573 | gtk_image_new_from_gicon (GIcon *icon) |
574 | { |
575 | GtkImage *image; |
576 | |
577 | image = g_object_new (GTK_TYPE_IMAGE, NULL); |
578 | |
579 | gtk_image_set_from_gicon (image, icon); |
580 | |
581 | return GTK_WIDGET (image); |
582 | } |
583 | |
584 | /** |
585 | * gtk_image_set_from_file: (attributes org.gtk.Method.set_property=file) |
586 | * @image: a `GtkImage` |
587 | * @filename: (type filename) (nullable): a filename |
588 | * |
589 | * Sets a `GtkImage` to show a file. |
590 | * |
591 | * See [ctor@Gtk.Image.new_from_file] for details. |
592 | */ |
593 | void |
594 | gtk_image_set_from_file (GtkImage *image, |
595 | const char *filename) |
596 | { |
597 | int scale_factor; |
598 | GdkPaintable *paintable; |
599 | |
600 | g_return_if_fail (GTK_IS_IMAGE (image)); |
601 | |
602 | g_object_freeze_notify (G_OBJECT (image)); |
603 | |
604 | gtk_image_clear (image); |
605 | |
606 | if (filename == NULL) |
607 | { |
608 | image->filename = NULL; |
609 | g_object_thaw_notify (G_OBJECT (image)); |
610 | return; |
611 | } |
612 | |
613 | scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (image)); |
614 | paintable = gdk_paintable_new_from_path_scaled (path: filename, scale_factor); |
615 | |
616 | if (paintable == NULL) |
617 | { |
618 | gtk_image_set_from_icon_name (image, icon_name: "image-missing" ); |
619 | g_object_thaw_notify (G_OBJECT (image)); |
620 | return; |
621 | } |
622 | |
623 | gtk_image_set_from_paintable (image, paintable); |
624 | |
625 | g_object_unref (object: paintable); |
626 | |
627 | image->filename = g_strdup (str: filename); |
628 | |
629 | g_object_thaw_notify (G_OBJECT (image)); |
630 | } |
631 | |
632 | #ifndef GDK_PIXBUF_MAGIC_NUMBER |
633 | #define GDK_PIXBUF_MAGIC_NUMBER (0x47646b50) /* 'GdkP' */ |
634 | #endif |
635 | |
636 | static gboolean |
637 | resource_is_pixdata (const char *resource_path) |
638 | { |
639 | const guint8 *stream; |
640 | guint32 magic; |
641 | gsize data_size; |
642 | GBytes *bytes; |
643 | gboolean ret = FALSE; |
644 | |
645 | bytes = g_resources_lookup_data (path: resource_path, lookup_flags: 0, NULL); |
646 | if (bytes == NULL) |
647 | return FALSE; |
648 | |
649 | stream = g_bytes_get_data (bytes, size: &data_size); |
650 | if (data_size < sizeof(guint32)) |
651 | goto out; |
652 | |
653 | magic = (stream[0] << 24) + (stream[1] << 16) + (stream[2] << 8) + stream[3]; |
654 | if (magic == GDK_PIXBUF_MAGIC_NUMBER) |
655 | ret = TRUE; |
656 | |
657 | out: |
658 | g_bytes_unref (bytes); |
659 | return ret; |
660 | } |
661 | |
662 | /** |
663 | * gtk_image_set_from_resource: (attributes org.gtk.Method.set_property=resource) |
664 | * @image: a `GtkImage` |
665 | * @resource_path: (nullable): a resource path |
666 | * |
667 | * Sets a `GtkImage` to show a resource. |
668 | * |
669 | * See [ctor@Gtk.Image.new_from_resource] for details. |
670 | */ |
671 | void |
672 | gtk_image_set_from_resource (GtkImage *image, |
673 | const char *resource_path) |
674 | { |
675 | int scale_factor; |
676 | GdkPaintable *paintable; |
677 | |
678 | g_return_if_fail (GTK_IS_IMAGE (image)); |
679 | |
680 | g_object_freeze_notify (G_OBJECT (image)); |
681 | |
682 | gtk_image_clear (image); |
683 | |
684 | if (resource_path == NULL) |
685 | { |
686 | g_object_thaw_notify (G_OBJECT (image)); |
687 | return; |
688 | } |
689 | |
690 | if (resource_is_pixdata (resource_path)) |
691 | { |
692 | g_warning ("GdkPixdata format images are not supported, remove the \"to-pixdata\" option from your GResource files" ); |
693 | paintable = NULL; |
694 | } |
695 | else |
696 | { |
697 | scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (image)); |
698 | paintable = gdk_paintable_new_from_resource_scaled (path: resource_path, scale_factor); |
699 | } |
700 | |
701 | if (paintable == NULL) |
702 | { |
703 | gtk_image_set_from_icon_name (image, icon_name: "image-missing" ); |
704 | g_object_thaw_notify (G_OBJECT (image)); |
705 | return; |
706 | } |
707 | |
708 | gtk_image_set_from_paintable (image, paintable); |
709 | |
710 | g_object_unref (object: paintable); |
711 | |
712 | image->resource_path = g_strdup (str: resource_path); |
713 | |
714 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_RESOURCE]); |
715 | |
716 | g_object_thaw_notify (G_OBJECT (image)); |
717 | } |
718 | |
719 | |
720 | /** |
721 | * gtk_image_set_from_pixbuf: (attributes org.gtk.Method.set_property=paintable) |
722 | * @image: a `GtkImage` |
723 | * @pixbuf: (nullable): a `GdkPixbuf` or `NULL` |
724 | * |
725 | * Sets a `GtkImage` to show a `GdkPixbuf`. |
726 | * |
727 | * See [ctor@Gtk.Image.new_from_pixbuf] for details. |
728 | * |
729 | * Note: This is a helper for [method@Gtk.Image.set_from_paintable], |
730 | * and you can't get back the exact pixbuf once this is called, |
731 | * only a paintable. |
732 | */ |
733 | void |
734 | gtk_image_set_from_pixbuf (GtkImage *image, |
735 | GdkPixbuf *pixbuf) |
736 | { |
737 | GdkTexture *texture; |
738 | |
739 | g_return_if_fail (GTK_IS_IMAGE (image)); |
740 | g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf)); |
741 | |
742 | if (pixbuf) |
743 | texture = gdk_texture_new_for_pixbuf (pixbuf); |
744 | else |
745 | texture = NULL; |
746 | |
747 | gtk_image_set_from_paintable (image, paintable: GDK_PAINTABLE (ptr: texture)); |
748 | |
749 | if (texture) |
750 | g_object_unref (object: texture); |
751 | } |
752 | |
753 | /** |
754 | * gtk_image_set_from_icon_name: (attributes org.gtk.Method.set_property=icon-name) |
755 | * @image: a `GtkImage` |
756 | * @icon_name: (nullable): an icon name |
757 | * |
758 | * Sets a `GtkImage` to show a named icon. |
759 | * |
760 | * See [ctor@Gtk.Image.new_from_icon_name] for details. |
761 | */ |
762 | void |
763 | gtk_image_set_from_icon_name (GtkImage *image, |
764 | const char *icon_name) |
765 | { |
766 | g_return_if_fail (GTK_IS_IMAGE (image)); |
767 | |
768 | g_object_freeze_notify (G_OBJECT (image)); |
769 | |
770 | gtk_image_clear (image); |
771 | |
772 | if (icon_name) |
773 | _gtk_icon_helper_set_icon_name (self: image->icon_helper, icon_name); |
774 | |
775 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_ICON_NAME]); |
776 | |
777 | g_object_thaw_notify (G_OBJECT (image)); |
778 | } |
779 | |
780 | /** |
781 | * gtk_image_set_from_gicon: (attributes org.gtk.Method.set_property=gicon) |
782 | * @image: a `GtkImage` |
783 | * @icon: an icon |
784 | * |
785 | * Sets a `GtkImage` to show a `GIcon`. |
786 | * |
787 | * See [ctor@Gtk.Image.new_from_gicon] for details. |
788 | */ |
789 | void |
790 | gtk_image_set_from_gicon (GtkImage *image, |
791 | GIcon *icon) |
792 | { |
793 | g_return_if_fail (GTK_IS_IMAGE (image)); |
794 | |
795 | g_object_freeze_notify (G_OBJECT (image)); |
796 | |
797 | if (icon) |
798 | g_object_ref (icon); |
799 | |
800 | gtk_image_clear (image); |
801 | |
802 | if (icon) |
803 | { |
804 | _gtk_icon_helper_set_gicon (self: image->icon_helper, gicon: icon); |
805 | g_object_unref (object: icon); |
806 | } |
807 | |
808 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_GICON]); |
809 | |
810 | g_object_thaw_notify (G_OBJECT (image)); |
811 | } |
812 | |
813 | static void |
814 | gtk_image_paintable_invalidate_contents (GdkPaintable *paintable, |
815 | GtkImage *image) |
816 | { |
817 | gtk_widget_queue_draw (GTK_WIDGET (image)); |
818 | } |
819 | |
820 | static void |
821 | gtk_image_paintable_invalidate_size (GdkPaintable *paintable, |
822 | GtkImage *image) |
823 | { |
824 | gtk_icon_helper_invalidate (self: image->icon_helper); |
825 | } |
826 | |
827 | /** |
828 | * gtk_image_set_from_paintable: (attributes org.gtk.Method.set_property=paintable) |
829 | * @image: a `GtkImage` |
830 | * @paintable: (nullable): a `GdkPaintable` |
831 | * |
832 | * Sets a `GtkImage` to show a `GdkPaintable`. |
833 | * |
834 | * See [ctor@Gtk.Image.new_from_paintable] for details. |
835 | */ |
836 | void |
837 | gtk_image_set_from_paintable (GtkImage *image, |
838 | GdkPaintable *paintable) |
839 | { |
840 | g_return_if_fail (GTK_IS_IMAGE (image)); |
841 | g_return_if_fail (paintable == NULL || GDK_IS_PAINTABLE (paintable)); |
842 | |
843 | g_object_freeze_notify (G_OBJECT (image)); |
844 | |
845 | if (paintable) |
846 | g_object_ref (paintable); |
847 | |
848 | gtk_image_clear (image); |
849 | |
850 | if (paintable) |
851 | { |
852 | const guint flags = gdk_paintable_get_flags (paintable); |
853 | |
854 | _gtk_icon_helper_set_paintable (self: image->icon_helper, paintable); |
855 | |
856 | if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0) |
857 | g_signal_connect (paintable, |
858 | "invalidate-contents" , |
859 | G_CALLBACK (gtk_image_paintable_invalidate_contents), |
860 | image); |
861 | |
862 | if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0) |
863 | g_signal_connect (paintable, |
864 | "invalidate-size" , |
865 | G_CALLBACK (gtk_image_paintable_invalidate_size), |
866 | image); |
867 | g_object_unref (object: paintable); |
868 | } |
869 | |
870 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_PAINTABLE]); |
871 | |
872 | g_object_thaw_notify (G_OBJECT (image)); |
873 | } |
874 | |
875 | /** |
876 | * gtk_image_get_storage_type: (attributes org.gtk.Method.get_property=storage-type) |
877 | * @image: a `GtkImage` |
878 | * |
879 | * Gets the type of representation being used by the `GtkImage` |
880 | * to store image data. |
881 | * |
882 | * If the `GtkImage` has no image data, the return value will |
883 | * be %GTK_IMAGE_EMPTY. |
884 | * |
885 | * Returns: image representation being used |
886 | */ |
887 | GtkImageType |
888 | gtk_image_get_storage_type (GtkImage *image) |
889 | { |
890 | g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY); |
891 | |
892 | return _gtk_icon_helper_get_storage_type (self: image->icon_helper); |
893 | } |
894 | |
895 | /** |
896 | * gtk_image_get_paintable: (attributes org.gtk.Method.get_property=paintable) |
897 | * @image: a `GtkImage` |
898 | * |
899 | * Gets the image `GdkPaintable` being displayed by the `GtkImage`. |
900 | * |
901 | * The storage type of the image must be %GTK_IMAGE_EMPTY or |
902 | * %GTK_IMAGE_PAINTABLE (see [method@Gtk.Image.get_storage_type]). |
903 | * The caller of this function does not own a reference to the |
904 | * returned paintable. |
905 | * |
906 | * Returns: (nullable) (transfer none): the displayed paintable |
907 | */ |
908 | GdkPaintable * |
909 | gtk_image_get_paintable (GtkImage *image) |
910 | { |
911 | g_return_val_if_fail (GTK_IS_IMAGE (image), NULL); |
912 | |
913 | return _gtk_icon_helper_peek_paintable (self: image->icon_helper); |
914 | } |
915 | |
916 | /** |
917 | * gtk_image_get_icon_name: (attributes org.gtk.Method.get_property=icon-name) |
918 | * @image: a `GtkImage` |
919 | * |
920 | * Gets the icon name and size being displayed by the `GtkImage`. |
921 | * |
922 | * The storage type of the image must be %GTK_IMAGE_EMPTY or |
923 | * %GTK_IMAGE_ICON_NAME (see [method@Gtk.Image.get_storage_type]). |
924 | * The returned string is owned by the `GtkImage` and should not |
925 | * be freed. |
926 | * |
927 | * Returns: (transfer none) (nullable): the icon name |
928 | */ |
929 | const char * |
930 | gtk_image_get_icon_name (GtkImage *image) |
931 | { |
932 | g_return_val_if_fail (GTK_IS_IMAGE (image), NULL); |
933 | |
934 | return _gtk_icon_helper_get_icon_name (self: image->icon_helper); |
935 | } |
936 | |
937 | /** |
938 | * gtk_image_get_gicon: (attributes org.gtk.Method.get_property=gicon) |
939 | * @image: a `GtkImage` |
940 | * |
941 | * Gets the `GIcon` being displayed by the `GtkImage`. |
942 | * |
943 | * The storage type of the image must be %GTK_IMAGE_EMPTY or |
944 | * %GTK_IMAGE_GICON (see [method@Gtk.Image.get_storage_type]). |
945 | * The caller of this function does not own a reference to the |
946 | * returned `GIcon`. |
947 | * |
948 | * Returns: (transfer none) (nullable): a `GIcon` |
949 | **/ |
950 | GIcon * |
951 | gtk_image_get_gicon (GtkImage *image) |
952 | { |
953 | g_return_val_if_fail (GTK_IS_IMAGE (image), NULL); |
954 | |
955 | return _gtk_icon_helper_peek_gicon (self: image->icon_helper); |
956 | } |
957 | |
958 | /** |
959 | * gtk_image_new: |
960 | * |
961 | * Creates a new empty `GtkImage` widget. |
962 | * |
963 | * Returns: a newly created `GtkImage` widget. |
964 | */ |
965 | GtkWidget* |
966 | gtk_image_new (void) |
967 | { |
968 | return g_object_new (GTK_TYPE_IMAGE, NULL); |
969 | } |
970 | |
971 | static void |
972 | gtk_image_unrealize (GtkWidget *widget) |
973 | { |
974 | GtkImage *image = GTK_IMAGE (widget); |
975 | |
976 | gtk_icon_helper_invalidate (self: image->icon_helper); |
977 | |
978 | GTK_WIDGET_CLASS (gtk_image_parent_class)->unrealize (widget); |
979 | } |
980 | |
981 | static float |
982 | gtk_image_get_baseline_align (GtkImage *image) |
983 | { |
984 | PangoContext *pango_context; |
985 | PangoFontMetrics *metrics; |
986 | |
987 | if (image->baseline_align == 0.0) |
988 | { |
989 | pango_context = gtk_widget_get_pango_context (GTK_WIDGET (image)); |
990 | metrics = pango_context_get_metrics (context: pango_context, NULL, NULL); |
991 | image->baseline_align = |
992 | (float)pango_font_metrics_get_ascent (metrics) / |
993 | (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics)); |
994 | |
995 | pango_font_metrics_unref (metrics); |
996 | } |
997 | |
998 | return image->baseline_align; |
999 | } |
1000 | |
1001 | static void |
1002 | gtk_image_snapshot (GtkWidget *widget, |
1003 | GtkSnapshot *snapshot) |
1004 | { |
1005 | GtkImage *image = GTK_IMAGE (widget); |
1006 | double ratio; |
1007 | int x, y, width, height, baseline; |
1008 | double w, h; |
1009 | |
1010 | width = gtk_widget_get_width (widget); |
1011 | height = gtk_widget_get_height (widget); |
1012 | ratio = gdk_paintable_get_intrinsic_aspect_ratio (paintable: GDK_PAINTABLE (ptr: image->icon_helper)); |
1013 | |
1014 | if (ratio == 0) |
1015 | { |
1016 | gdk_paintable_snapshot (paintable: GDK_PAINTABLE (ptr: image->icon_helper), snapshot, width, height); |
1017 | } |
1018 | else |
1019 | { |
1020 | double image_ratio = (double) width / height; |
1021 | |
1022 | if (ratio > image_ratio) |
1023 | { |
1024 | w = width; |
1025 | h = width / ratio; |
1026 | } |
1027 | else |
1028 | { |
1029 | w = height * ratio; |
1030 | h = height; |
1031 | } |
1032 | |
1033 | x = (width - ceil (x: w)) / 2; |
1034 | |
1035 | baseline = gtk_widget_get_allocated_baseline (widget); |
1036 | if (baseline == -1) |
1037 | y = floor(x: height - ceil (x: h)) / 2; |
1038 | else |
1039 | y = CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - ceil (h)); |
1040 | |
1041 | if (x != 0 || y != 0) |
1042 | { |
1043 | gtk_snapshot_save (snapshot); |
1044 | gtk_snapshot_translate (snapshot, point: &GRAPHENE_POINT_INIT (x, y)); |
1045 | gdk_paintable_snapshot (paintable: GDK_PAINTABLE (ptr: image->icon_helper), snapshot, width: w, height: h); |
1046 | gtk_snapshot_restore (snapshot); |
1047 | } |
1048 | else |
1049 | { |
1050 | gdk_paintable_snapshot (paintable: GDK_PAINTABLE (ptr: image->icon_helper), snapshot, width: w, height: h); |
1051 | } |
1052 | } |
1053 | } |
1054 | |
1055 | static void |
1056 | gtk_image_notify_for_storage_type (GtkImage *image, |
1057 | GtkImageType storage_type) |
1058 | { |
1059 | switch (storage_type) |
1060 | { |
1061 | case GTK_IMAGE_ICON_NAME: |
1062 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_ICON_NAME]); |
1063 | break; |
1064 | case GTK_IMAGE_GICON: |
1065 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_GICON]); |
1066 | break; |
1067 | case GTK_IMAGE_PAINTABLE: |
1068 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_PAINTABLE]); |
1069 | break; |
1070 | case GTK_IMAGE_EMPTY: |
1071 | default: |
1072 | break; |
1073 | } |
1074 | } |
1075 | |
1076 | void |
1077 | gtk_image_set_from_definition (GtkImage *image, |
1078 | GtkImageDefinition *def) |
1079 | { |
1080 | g_return_if_fail (GTK_IS_IMAGE (image)); |
1081 | |
1082 | g_object_freeze_notify (G_OBJECT (image)); |
1083 | |
1084 | gtk_image_clear (image); |
1085 | |
1086 | if (def != NULL) |
1087 | { |
1088 | _gtk_icon_helper_set_definition (self: image->icon_helper, def); |
1089 | |
1090 | gtk_image_notify_for_storage_type (image, storage_type: gtk_image_definition_get_storage_type (def)); |
1091 | } |
1092 | |
1093 | g_object_thaw_notify (G_OBJECT (image)); |
1094 | } |
1095 | |
1096 | GtkImageDefinition * |
1097 | gtk_image_get_definition (GtkImage *image) |
1098 | { |
1099 | return gtk_icon_helper_get_definition (self: image->icon_helper); |
1100 | } |
1101 | |
1102 | /** |
1103 | * gtk_image_clear: |
1104 | * @image: a `GtkImage` |
1105 | * |
1106 | * Resets the image to be empty. |
1107 | */ |
1108 | void |
1109 | gtk_image_clear (GtkImage *image) |
1110 | { |
1111 | GtkImageType storage_type; |
1112 | |
1113 | g_object_freeze_notify (G_OBJECT (image)); |
1114 | storage_type = gtk_image_get_storage_type (image); |
1115 | |
1116 | if (storage_type != GTK_IMAGE_EMPTY) |
1117 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_STORAGE_TYPE]); |
1118 | |
1119 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_ICON_SIZE]); |
1120 | |
1121 | gtk_image_notify_for_storage_type (image, storage_type); |
1122 | |
1123 | if (image->filename) |
1124 | { |
1125 | g_free (mem: image->filename); |
1126 | image->filename = NULL; |
1127 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_FILE]); |
1128 | } |
1129 | |
1130 | if (image->resource_path) |
1131 | { |
1132 | g_free (mem: image->resource_path); |
1133 | image->resource_path = NULL; |
1134 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_RESOURCE]); |
1135 | } |
1136 | |
1137 | if (storage_type == GTK_IMAGE_PAINTABLE) |
1138 | { |
1139 | GdkPaintable *paintable = _gtk_icon_helper_peek_paintable (self: image->icon_helper); |
1140 | const guint flags = gdk_paintable_get_flags (paintable); |
1141 | |
1142 | if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0) |
1143 | g_signal_handlers_disconnect_by_func (paintable, |
1144 | gtk_image_paintable_invalidate_contents, |
1145 | image); |
1146 | |
1147 | if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0) |
1148 | g_signal_handlers_disconnect_by_func (paintable, |
1149 | gtk_image_paintable_invalidate_size, |
1150 | image); |
1151 | } |
1152 | |
1153 | _gtk_icon_helper_clear (self: image->icon_helper); |
1154 | |
1155 | g_object_thaw_notify (G_OBJECT (image)); |
1156 | } |
1157 | |
1158 | static void |
1159 | gtk_image_measure (GtkWidget *widget, |
1160 | GtkOrientation orientation, |
1161 | int for_size, |
1162 | int *minimum, |
1163 | int *natural, |
1164 | int *minimum_baseline, |
1165 | int *natural_baseline) |
1166 | { |
1167 | GtkImage *image = GTK_IMAGE (widget); |
1168 | float baseline_align; |
1169 | |
1170 | *minimum = *natural = gtk_icon_helper_get_size (self: image->icon_helper); |
1171 | |
1172 | if (orientation == GTK_ORIENTATION_VERTICAL) |
1173 | { |
1174 | baseline_align = gtk_image_get_baseline_align (GTK_IMAGE (widget)); |
1175 | if (minimum_baseline) |
1176 | *minimum_baseline = *minimum * baseline_align; |
1177 | if (natural_baseline) |
1178 | *natural_baseline = *natural * baseline_align; |
1179 | } |
1180 | } |
1181 | |
1182 | static void |
1183 | gtk_image_css_changed (GtkWidget *widget, |
1184 | GtkCssStyleChange *change) |
1185 | { |
1186 | GtkImage *image = GTK_IMAGE (widget); |
1187 | |
1188 | gtk_icon_helper_invalidate_for_change (self: image->icon_helper, change); |
1189 | |
1190 | GTK_WIDGET_CLASS (gtk_image_parent_class)->css_changed (widget, change); |
1191 | |
1192 | image->baseline_align = 0.0; |
1193 | } |
1194 | |
1195 | static void |
1196 | gtk_image_system_setting_changed (GtkWidget *widget, |
1197 | GtkSystemSetting setting) |
1198 | { |
1199 | GtkImage *image = GTK_IMAGE (widget); |
1200 | |
1201 | if (setting == GTK_SYSTEM_SETTING_ICON_THEME) |
1202 | gtk_icon_helper_invalidate (self: image->icon_helper); |
1203 | |
1204 | GTK_WIDGET_CLASS (gtk_image_parent_class)->system_setting_changed (widget, setting); |
1205 | } |
1206 | |
1207 | /** |
1208 | * gtk_image_set_pixel_size: (attributes org.gtk.Method.set_property=pixel-size) |
1209 | * @image: a `GtkImage` |
1210 | * @pixel_size: the new pixel size |
1211 | * |
1212 | * Sets the pixel size to use for named icons. |
1213 | * |
1214 | * If the pixel size is set to a value != -1, it is used instead |
1215 | * of the icon size set by [method@Gtk.Image.set_from_icon_name]. |
1216 | */ |
1217 | void |
1218 | gtk_image_set_pixel_size (GtkImage *image, |
1219 | int pixel_size) |
1220 | { |
1221 | g_return_if_fail (GTK_IS_IMAGE (image)); |
1222 | |
1223 | if (_gtk_icon_helper_set_pixel_size (self: image->icon_helper, pixel_size)) |
1224 | { |
1225 | if (gtk_widget_get_visible (GTK_WIDGET (image))) |
1226 | gtk_widget_queue_resize (GTK_WIDGET (image)); |
1227 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_PIXEL_SIZE]); |
1228 | } |
1229 | } |
1230 | |
1231 | /** |
1232 | * gtk_image_get_pixel_size: (attributes org.gtk.Method.get_property=pixel-size) |
1233 | * @image: a `GtkImage` |
1234 | * |
1235 | * Gets the pixel size used for named icons. |
1236 | * |
1237 | * Returns: the pixel size used for named icons. |
1238 | */ |
1239 | int |
1240 | gtk_image_get_pixel_size (GtkImage *image) |
1241 | { |
1242 | g_return_val_if_fail (GTK_IS_IMAGE (image), -1); |
1243 | |
1244 | return _gtk_icon_helper_get_pixel_size (self: image->icon_helper); |
1245 | } |
1246 | |
1247 | /** |
1248 | * gtk_image_set_icon_size: (attributes org.gtk.Method.set_property=icon-size) |
1249 | * @image: a `GtkImage` |
1250 | * @icon_size: the new icon size |
1251 | * |
1252 | * Suggests an icon size to the theme for named icons. |
1253 | */ |
1254 | void |
1255 | gtk_image_set_icon_size (GtkImage *image, |
1256 | GtkIconSize icon_size) |
1257 | { |
1258 | g_return_if_fail (GTK_IS_IMAGE (image)); |
1259 | |
1260 | if (image->icon_size == icon_size) |
1261 | return; |
1262 | |
1263 | image->icon_size = icon_size; |
1264 | gtk_icon_size_set_style_classes (cssnode: gtk_widget_get_css_node (GTK_WIDGET (image)), icon_size); |
1265 | g_object_notify_by_pspec (G_OBJECT (image), pspec: image_props[PROP_ICON_SIZE]); |
1266 | } |
1267 | |
1268 | /** |
1269 | * gtk_image_get_icon_size: (attributes org.gtk.Method.get_property=icon-size) |
1270 | * @image: a `GtkImage` |
1271 | * |
1272 | * Gets the icon size used by the @image when rendering icons. |
1273 | * |
1274 | * Returns: the image size used by icons |
1275 | */ |
1276 | GtkIconSize |
1277 | gtk_image_get_icon_size (GtkImage *image) |
1278 | { |
1279 | g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_ICON_SIZE_INHERIT); |
1280 | |
1281 | return image->icon_size; |
1282 | } |
1283 | |
1284 | void |
1285 | gtk_image_get_image_size (GtkImage *image, |
1286 | int *width, |
1287 | int *height) |
1288 | { |
1289 | *width = *height = gtk_icon_helper_get_size (self: image->icon_helper); |
1290 | } |
1291 | |