gtkimage.c 55.4 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
16
 */
17 18

/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21 22 23 24
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

25
#include "config.h"
26

27
#include <math.h>
28
#include <string.h>
29
#include <cairo-gobject.h>
30

Elliot Lee's avatar
Elliot Lee committed
31
#include "gtkcontainer.h"
32
#include "gtkcssstylepropertyprivate.h"
33
#include "gtkiconhelperprivate.h"
34
#include "gtkimageprivate.h"
35 36
#include "deprecated/gtkiconfactory.h"
#include "deprecated/gtkstock.h"
37
#include "gtkicontheme.h"
38
#include "gtksizerequest.h"
Havoc Pennington's avatar
Havoc Pennington committed
39
#include "gtkintl.h"
40
#include "gtkprivate.h"
41
#include "gtktypebuiltins.h"
42 43 44
#include "gtkcssshadowsvalueprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
Matthias Clasen's avatar
Matthias Clasen committed
45
#include "gtkcsscustomgadgetprivate.h"
Elliot Lee's avatar
Elliot Lee committed
46

47 48
#include "a11y/gtkimageaccessible.h"

49 50 51 52 53 54 55 56 57
/**
 * SECTION:gtkimage
 * @Short_description: A widget displaying an image
 * @Title: GtkImage
 * @See_also:#GdkPixbuf
 *
 * The #GtkImage widget displays an image. Various kinds of object
 * can be displayed as an image; most typically, you would load a
 * #GdkPixbuf ("pixel buffer") from a file, and then display that.
58
 * There’s a convenience function to do this, gtk_image_new_from_file(),
59
 * used as follows:
60
 * |[<!-- language="C" -->
61 62
 *   GtkWidget *image;
 *   image = gtk_image_new_from_file ("myfile.png");
63
 * ]|
64
 * If the file isn’t loaded successfully, the image will contain a
65
 * “broken image” icon similar to that used in many web browsers.
66 67 68 69 70 71 72 73 74 75 76 77
 * If you want to handle errors in loading the file yourself,
 * for example by displaying an error message, then load the image with
 * gdk_pixbuf_new_from_file(), then create the #GtkImage with
 * gtk_image_new_from_pixbuf().
 *
 * The image file may contain an animation, if so the #GtkImage will
 * display an animation (#GdkPixbufAnimation) instead of a static image.
 *
 * #GtkImage is a subclass of #GtkMisc, which implies that you can
 * align it (center, left, right) and add padding to it, using
 * #GtkMisc methods.
 *
78
 * #GtkImage is a “no window” widget (has no #GdkWindow of its own),
79 80 81
 * so by default does not receive events. If you want to receive events
 * on the image, such as button clicks, place the image inside a
 * #GtkEventBox, then connect to the event signals on the event box.
82 83 84
 *
 * ## Handling button press events on a #GtkImage.
 *
85
 * |[<!-- language="C" -->
86 87 88 89 90
 *   static gboolean
 *   button_press_callback (GtkWidget      *event_box,
 *                          GdkEventButton *event,
 *                          gpointer        data)
 *   {
91
 *     g_print ("Event box clicked at coordinates %f,%f\n",
92 93
 *              event->x, event->y);
 *
94 95 96
 *     // Returning TRUE means we handled the event, so the signal
 *     // emission should be stopped (don’t call any further callbacks
 *     // that may be connected). Return FALSE to continue invoking callbacks.
97 98 99 100 101 102 103 104 105 106 107
 *     return TRUE;
 *   }
 *
 *   static GtkWidget*
 *   create_image (void)
 *   {
 *     GtkWidget *image;
 *     GtkWidget *event_box;
 *
 *     image = gtk_image_new_from_file ("myfile.png");
 *
108
 *     event_box = gtk_event_box_new ();
109 110 111 112 113 114 115 116 117 118
 *
 *     gtk_container_add (GTK_CONTAINER (event_box), image);
 *
 *     g_signal_connect (G_OBJECT (event_box),
 *                       "button_press_event",
 *                       G_CALLBACK (button_press_callback),
 *                       image);
 *
 *     return image;
 *   }
119
 * ]|
120 121 122 123 124 125 126 127 128 129
 *
 * When handling events on the event box, keep in mind that coordinates
 * in the image may be different from event box coordinates due to
 * the alignment and padding settings on the image (see #GtkMisc).
 * The simplest way to solve this is to set the alignment to 0.0
 * (left/top), and set the padding to zero. Then the origin of
 * the image will be the same as the origin of the event box.
 *
 * Sometimes an application will want to avoid depending on external data
 * files, such as image files. GTK+ comes with a program to avoid this,
130
 * called “gdk-pixbuf-csource”. This library
131 132 133
 * allows you to convert an image into a C variable declaration, which
 * can then be loaded into a #GdkPixbuf using
 * gdk_pixbuf_new_from_inline().
134 135 136 137
 *
 * # CSS nodes
 *
 * GtkImage has a single CSS node with the name image.
138 139
 */

140

141
struct _GtkImagePrivate
142
{
143 144 145
  GtkIconHelper *icon_helper;

  GdkPixbufAnimationIter *animation_iter;
146 147
  gint animation_timeout;

Matthias Clasen's avatar
Matthias Clasen committed
148 149
  GtkCssGadget *gadget;

150
  float baseline_align;
151 152

  gchar                *filename;       /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */
153
  gchar                *resource_path;  /* Only used with GTK_IMAGE_PIXBUF */
154 155
};

156

Havoc Pennington's avatar
Havoc Pennington committed
157
#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
158 159
static gint gtk_image_draw                 (GtkWidget    *widget,
                                            cairo_t      *cr);
160 161
static void gtk_image_size_allocate        (GtkWidget    *widget,
                                            GtkAllocation*allocation);
162 163 164 165 166 167 168 169
static void gtk_image_unmap                (GtkWidget    *widget);
static void gtk_image_unrealize            (GtkWidget    *widget);
static void gtk_image_get_preferred_width  (GtkWidget    *widget,
                                            gint         *minimum,
                                            gint         *natural);
static void gtk_image_get_preferred_height (GtkWidget    *widget,
                                            gint         *minimum,
                                            gint         *natural);
170 171 172 173 174 175
static void gtk_image_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
								   gint       width,
								   gint      *minimum,
								   gint      *natural,
								   gint      *minimum_baseline,
								   gint      *natural_baseline);
176

Matthias Clasen's avatar
Matthias Clasen committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
static void gtk_image_get_content_size (GtkCssGadget   *gadget,
                                        GtkOrientation  orientation,
                                        gint            for_size,
                                        gint           *minimum,
                                        gint           *natural,
                                        gint           *minimum_baseline,
                                        gint           *natural_baseline,
                                        gpointer        unused);
static gboolean gtk_image_render_contents (GtkCssGadget *gadget,
                                           cairo_t      *cr,
                                           int           x,
                                           int           y,
                                           int           width,
                                           int           height,
                                           gpointer      data);

193
static void gtk_image_style_updated        (GtkWidget    *widget);
194
static void gtk_image_finalize             (GObject      *object);
195 196 197 198 199 200 201 202 203 204 205
static void gtk_image_reset                (GtkImage     *image);

static void gtk_image_set_property         (GObject      *object,
                                            guint         prop_id,
                                            const GValue *value,
                                            GParamSpec   *pspec);
static void gtk_image_get_property         (GObject      *object,
                                            guint         prop_id,
                                            GValue       *value,
                                            GParamSpec   *pspec);

Havoc Pennington's avatar
Havoc Pennington committed
206 207 208 209
enum
{
  PROP_0,
  PROP_PIXBUF,
210
  PROP_SURFACE,
Havoc Pennington's avatar
Havoc Pennington committed
211 212 213 214
  PROP_FILE,
  PROP_STOCK,
  PROP_ICON_SET,
  PROP_ICON_SIZE,
215
  PROP_PIXEL_SIZE,
Havoc Pennington's avatar
Havoc Pennington committed
216
  PROP_PIXBUF_ANIMATION,
217
  PROP_ICON_NAME,
218
  PROP_STORAGE_TYPE,
219
  PROP_GICON,
220
  PROP_RESOURCE,
221 222
  PROP_USE_FALLBACK,
  NUM_PROPERTIES
Havoc Pennington's avatar
Havoc Pennington committed
223 224
};

225 226
static GParamSpec *image_props[NUM_PROPERTIES] = { NULL, };

Matthias Clasen's avatar
Matthias Clasen committed
227
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
228
G_DEFINE_TYPE_WITH_PRIVATE (GtkImage, gtk_image, GTK_TYPE_MISC)
Matthias Clasen's avatar
Matthias Clasen committed
229
G_GNUC_END_IGNORE_DEPRECATIONS
Elliot Lee's avatar
Elliot Lee committed
230 231 232 233

static void
gtk_image_class_init (GtkImageClass *class)
{
Havoc Pennington's avatar
Havoc Pennington committed
234
  GObjectClass *gobject_class;
Elliot Lee's avatar
Elliot Lee committed
235 236
  GtkWidgetClass *widget_class;

Havoc Pennington's avatar
Havoc Pennington committed
237 238 239 240
  gobject_class = G_OBJECT_CLASS (class);
  
  gobject_class->set_property = gtk_image_set_property;
  gobject_class->get_property = gtk_image_get_property;
241
  gobject_class->finalize = gtk_image_finalize;
242

Havoc Pennington's avatar
Havoc Pennington committed
243
  widget_class = GTK_WIDGET_CLASS (class);
244
  widget_class->draw = gtk_image_draw;
245 246
  widget_class->get_preferred_width = gtk_image_get_preferred_width;
  widget_class->get_preferred_height = gtk_image_get_preferred_height;
247
  widget_class->get_preferred_height_and_baseline_for_width = gtk_image_get_preferred_height_and_baseline_for_width;
248
  widget_class->size_allocate = gtk_image_size_allocate;
Havoc Pennington's avatar
Havoc Pennington committed
249
  widget_class->unmap = gtk_image_unmap;
250
  widget_class->unrealize = gtk_image_unrealize;
251
  widget_class->style_updated = gtk_image_style_updated;
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272

  image_props[PROP_PIXBUF] =
      g_param_spec_object ("pixbuf",
                           P_("Pixbuf"),
                           P_("A GdkPixbuf to display"),
                           GDK_TYPE_PIXBUF,
                           GTK_PARAM_READWRITE);

  image_props[PROP_SURFACE] =
      g_param_spec_boxed ("surface",
                          P_("Surface"),
                          P_("A cairo_surface_t to display"),
                          CAIRO_GOBJECT_TYPE_SURFACE,
                          GTK_PARAM_READWRITE);

  image_props[PROP_FILE] =
      g_param_spec_string ("file",
                           P_("Filename"),
                           P_("Filename to load and display"),
                           NULL,
                           GTK_PARAM_READWRITE);
Havoc Pennington's avatar
Havoc Pennington committed
273

274 275 276 277 278
  /**
   * GtkImage:stock:
   *
   * Deprecated: 3.10: Use #GtkImage:icon-name instead.
   */
279 280 281 282 283 284 285
  image_props[PROP_STOCK] =
      g_param_spec_string ("stock",
                           P_("Stock ID"),
                           P_("Stock ID for a stock image to display"),
                           NULL,
                           GTK_PARAM_READWRITE | G_PARAM_DEPRECATED);

286 287 288 289 290 291
  /**
   * GtkImage:icon-set:
   *
   * Deprecated: 3.10: Use #GtkImage:icon-name instead.
   */
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
292 293 294 295 296 297
  image_props[PROP_ICON_SET] =
      g_param_spec_boxed ("icon-set",
                          P_("Icon set"),
                          P_("Icon set to display"),
                          GTK_TYPE_ICON_SET,
                          GTK_PARAM_READWRITE | G_PARAM_DEPRECATED);
298 299
  G_GNUC_END_IGNORE_DEPRECATIONS;

300 301 302 303 304 305 306 307
  image_props[PROP_ICON_SIZE] =
      g_param_spec_int ("icon-size",
                        P_("Icon size"),
                        P_("Symbolic size to use for stock icon, icon set or named icon"),
                        0, G_MAXINT,
                        DEFAULT_ICON_SIZE,
                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

308 309 310
  /**
   * GtkImage:pixel-size:
   *
311
   * The "pixel-size" property can be used to specify a fixed size
312 313
   * overriding the #GtkImage:icon-size property for images of type
   * %GTK_IMAGE_ICON_NAME.
314 315 316
   *
   * Since: 2.6
   */
317 318 319 320 321 322 323 324 325 326 327 328 329 330
  image_props[PROP_PIXEL_SIZE] =
      g_param_spec_int ("pixel-size",
                        P_("Pixel size"),
                        P_("Pixel size to use for named icon"),
                        -1, G_MAXINT,
                        -1,
                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  image_props[PROP_PIXBUF_ANIMATION] =
      g_param_spec_object ("pixbuf-animation",
                           P_("Animation"),
                           P_("GdkPixbufAnimation to display"),
                           GDK_TYPE_PIXBUF_ANIMATION,
                           GTK_PARAM_READWRITE);
331 332 333 334

  /**
   * GtkImage:icon-name:
   *
335
   * The name of the icon in the icon theme. If the icon theme is
336 337 338 339
   * changed, the image will be updated automatically.
   *
   * Since: 2.6
   */
340 341 342 343 344 345 346
  image_props[PROP_ICON_NAME] =
      g_param_spec_string ("icon-name",
                           P_("Icon Name"),
                           P_("The name of the icon from the icon theme"),
                           NULL,
                           GTK_PARAM_READWRITE);

347 348 349 350 351 352 353 354 355
  /**
   * GtkImage:gicon:
   *
   * The GIcon displayed in the GtkImage. For themed icons,
   * If the icon theme is changed, the image will be updated
   * automatically.
   *
   * Since: 2.14
   */
356 357 358 359 360 361
  image_props[PROP_GICON] =
      g_param_spec_object ("gicon",
                           P_("Icon"),
                           P_("The GIcon being displayed"),
                           G_TYPE_ICON,
                           GTK_PARAM_READWRITE);
362 363 364 365 366 367 368 369

  /**
   * GtkImage:resource:
   *
   * A path to a resource file to display.
   *
   * Since: 3.8
   */
370 371 372 373 374 375 376 377 378 379 380 381 382 383
  image_props[PROP_RESOURCE] =
      g_param_spec_string ("resource",
                           P_("Resource"),
                           P_("The resource path being displayed"),
                           NULL,
                           GTK_PARAM_READWRITE);

  image_props[PROP_STORAGE_TYPE] =
      g_param_spec_enum ("storage-type",
                         P_("Storage type"),
                         P_("The representation being used for image data"),
                         GTK_TYPE_IMAGE_TYPE,
                         GTK_IMAGE_EMPTY,
                         GTK_PARAM_READABLE);
384

385 386 387 388 389 390 391 392 393 394
  /**
   * GtkImage:use-fallback:
   *
   * Whether the icon displayed in the GtkImage will use
   * standard icon names fallback. The value of this property
   * is only relevant for images of type %GTK_IMAGE_ICON_NAME
   * and %GTK_IMAGE_GICON.
   *
   * Since: 3.0
   */
395 396 397 398 399 400 401 402
  image_props[PROP_USE_FALLBACK] =
      g_param_spec_boolean ("use-fallback",
                            P_("Use Fallback"),
                            P_("Whether to use icon names fallback"),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  g_object_class_install_properties (gobject_class, NUM_PROPERTIES, image_props);
403

404
  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_IMAGE_ACCESSIBLE);
405
  gtk_widget_class_set_css_name (widget_class, "image");
Elliot Lee's avatar
Elliot Lee committed
406 407 408 409 410
}

static void
gtk_image_init (GtkImage *image)
{
411
  GtkImagePrivate *priv;
Matthias Clasen's avatar
Matthias Clasen committed
412
  GtkCssNode *widget_node;
413

414
  image->priv = gtk_image_get_instance_private (image);
415
  priv = image->priv;
416

417
  widget_node = gtk_widget_get_css_node (GTK_WIDGET (image));
418
  gtk_widget_set_has_window (GTK_WIDGET (image), FALSE);
419 420

  priv->icon_helper = gtk_icon_helper_new (widget_node, GTK_WIDGET (image));
421
  _gtk_icon_helper_set_icon_size (priv->icon_helper, DEFAULT_ICON_SIZE);
Matthias Clasen's avatar
Matthias Clasen committed
422 423 424 425 426 427 428 429

  priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
                                                     GTK_WIDGET (image),
                                                     gtk_image_get_content_size,
                                                     NULL,
                                                     gtk_image_render_contents,
                                                     NULL, NULL);

Elliot Lee's avatar
Elliot Lee committed
430 431
}

432
static void
433
gtk_image_finalize (GObject *object)
434
{
435
  GtkImage *image = GTK_IMAGE (object);
436

437
  g_clear_object (&image->priv->icon_helper);
Matthias Clasen's avatar
Matthias Clasen committed
438 439
  g_clear_object (&image->priv->gadget);

440
  g_free (image->priv->filename);
441
  g_free (image->priv->resource_path);
442

443 444
  G_OBJECT_CLASS (gtk_image_parent_class)->finalize (object);
};
445

Matthias Clasen's avatar
Matthias Clasen committed
446
static void
Havoc Pennington's avatar
Havoc Pennington committed
447 448 449 450 451
gtk_image_set_property (GObject      *object,
			guint         prop_id,
			const GValue *value,
			GParamSpec   *pspec)
{
452
  GtkImage *image = GTK_IMAGE (object);
453
  GtkImagePrivate *priv = image->priv;
454
  GtkIconSize icon_size = _gtk_icon_helper_get_icon_size (priv->icon_helper);
Havoc Pennington's avatar
Havoc Pennington committed
455

456 457 458
  if (icon_size == GTK_ICON_SIZE_INVALID)
    icon_size = DEFAULT_ICON_SIZE;

Havoc Pennington's avatar
Havoc Pennington committed
459 460 461
  switch (prop_id)
    {
    case PROP_PIXBUF:
462
      gtk_image_set_from_pixbuf (image, g_value_get_object (value));
Havoc Pennington's avatar
Havoc Pennington committed
463
      break;
464
    case PROP_SURFACE:
465
      gtk_image_set_from_surface (image, g_value_get_boxed (value));
466
      break;
Havoc Pennington's avatar
Havoc Pennington committed
467
    case PROP_FILE:
468
      gtk_image_set_from_file (image, g_value_get_string (value));
Havoc Pennington's avatar
Havoc Pennington committed
469 470
      break;
    case PROP_STOCK:
471
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
472
      gtk_image_set_from_stock (image, g_value_get_string (value), icon_size);
473
      G_GNUC_END_IGNORE_DEPRECATIONS;
Havoc Pennington's avatar
Havoc Pennington committed
474 475
      break;
    case PROP_ICON_SET:
476
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
477
      gtk_image_set_from_icon_set (image, g_value_get_boxed (value), icon_size);
478
      G_GNUC_END_IGNORE_DEPRECATIONS;
Havoc Pennington's avatar
Havoc Pennington committed
479 480
      break;
    case PROP_ICON_SIZE:
481
      if (_gtk_icon_helper_set_icon_size (priv->icon_helper, g_value_get_int (value)))
482 483 484 485
        {
          g_object_notify_by_pspec (object, pspec);
          gtk_widget_queue_resize (GTK_WIDGET (image));
        }
Havoc Pennington's avatar
Havoc Pennington committed
486
      break;
487
    case PROP_PIXEL_SIZE:
488
      gtk_image_set_pixel_size (image, g_value_get_int (value));
489
      break;
Havoc Pennington's avatar
Havoc Pennington committed
490
    case PROP_PIXBUF_ANIMATION:
491
      gtk_image_set_from_animation (image, g_value_get_object (value));
Havoc Pennington's avatar
Havoc Pennington committed
492
      break;
493
    case PROP_ICON_NAME:
494
      gtk_image_set_from_icon_name (image, g_value_get_string (value), icon_size);
495
      break;
496
    case PROP_GICON:
497
      gtk_image_set_from_gicon (image, g_value_get_object (value), icon_size);
498
      break;
499 500 501
    case PROP_RESOURCE:
      gtk_image_set_from_resource (image, g_value_get_string (value));
      break;
502

503
    case PROP_USE_FALLBACK:
504 505
      if (_gtk_icon_helper_set_use_fallback (priv->icon_helper, g_value_get_boolean (value)))
        g_object_notify_by_pspec (object, pspec);
506 507
      break;

Havoc Pennington's avatar
Havoc Pennington committed
508 509 510 511 512 513 514 515 516 517 518 519
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void 
gtk_image_get_property (GObject     *object,
			guint        prop_id,
			GValue      *value,
			GParamSpec  *pspec)
{
520
  GtkImage *image = GTK_IMAGE (object);
521
  GtkImagePrivate *priv = image->priv;
Havoc Pennington's avatar
Havoc Pennington committed
522 523 524 525

  switch (prop_id)
    {
    case PROP_PIXBUF:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
526
      g_value_set_object (value, _gtk_icon_helper_peek_pixbuf (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
527
      break;
528 529 530
    case PROP_SURFACE:
      g_value_set_boxed (value, _gtk_icon_helper_peek_surface (priv->icon_helper));
      break;
531 532 533
    case PROP_FILE:
      g_value_set_string (value, priv->filename);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
534
    case PROP_STOCK:
535
      g_value_set_string (value, _gtk_icon_helper_get_stock_id (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
536 537
      break;
    case PROP_ICON_SET:
538
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
539
      g_value_set_boxed (value, _gtk_icon_helper_peek_icon_set (priv->icon_helper));
540 541
      G_GNUC_END_IGNORE_DEPRECATIONS;
      break;
Havoc Pennington's avatar
Havoc Pennington committed
542
    case PROP_ICON_SIZE:
543
      g_value_set_int (value, _gtk_icon_helper_get_icon_size (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
544
      break;
545
    case PROP_PIXEL_SIZE:
546
      g_value_set_int (value, _gtk_icon_helper_get_pixel_size (priv->icon_helper));
547
      break;
Havoc Pennington's avatar
Havoc Pennington committed
548
    case PROP_PIXBUF_ANIMATION:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
549
      g_value_set_object (value, _gtk_icon_helper_peek_animation (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
550
      break;
551
    case PROP_ICON_NAME:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
552
      g_value_set_string (value, _gtk_icon_helper_get_icon_name (priv->icon_helper));
553
      break;
554
    case PROP_GICON:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
555
      g_value_set_object (value, _gtk_icon_helper_peek_gicon (priv->icon_helper));
Havoc Pennington's avatar
Havoc Pennington committed
556
      break;
557 558 559
    case PROP_RESOURCE:
      g_value_set_string (value, priv->resource_path);
      break;
560
    case PROP_USE_FALLBACK:
561
      g_value_set_boolean (value, _gtk_icon_helper_get_use_fallback (priv->icon_helper));
562
      break;
563 564 565
    case PROP_STORAGE_TYPE:
      g_value_set_enum (value, _gtk_icon_helper_get_storage_type (priv->icon_helper));
      break;
Havoc Pennington's avatar
Havoc Pennington committed
566 567 568 569 570 571
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

572

573 574
/**
 * gtk_image_new_from_file:
575
 * @filename: (type filename): a filename
576
 * 
Havoc Pennington's avatar
Havoc Pennington committed
577
 * Creates a new #GtkImage displaying the file @filename. If the file
578
 * isn’t found or can’t be loaded, the resulting #GtkImage will
579
 * display a “broken image” icon. This function never returns %NULL,
Havoc Pennington's avatar
Havoc Pennington committed
580 581 582 583 584 585 586 587 588 589 590 591 592
 * it always returns a valid #GtkImage widget.
 *
 * If the file contains an animation, the image will contain an
 * animation.
 *
 * If you need to detect failures to load the file, use
 * gdk_pixbuf_new_from_file() to load the file yourself, then create
 * the #GtkImage from the pixbuf. (Or for animations, use
 * gdk_pixbuf_animation_new_from_file()).
 *
 * The storage type (gtk_image_get_storage_type()) of the returned
 * image is not defined, it will be whatever is appropriate for
 * displaying the file.
593
 * 
594
 * Returns: a new #GtkImage
595
 **/
596 597 598 599 600
GtkWidget*
gtk_image_new_from_file   (const gchar *filename)
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
601
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
602 603 604 605 606 607

  gtk_image_set_from_file (image, filename);

  return GTK_WIDGET (image);
}

608 609 610 611 612
/**
 * gtk_image_new_from_resource:
 * @resource_path: a resource path
 *
 * Creates a new #GtkImage displaying the resource file @resource_path. If the file
613
 * isn’t found or can’t be loaded, the resulting #GtkImage will
614
 * display a “broken image” icon. This function never returns %NULL,
615 616 617 618 619 620 621 622 623 624 625 626 627 628
 * it always returns a valid #GtkImage widget.
 *
 * If the file contains an animation, the image will contain an
 * animation.
 *
 * If you need to detect failures to load the file, use
 * gdk_pixbuf_new_from_file() to load the file yourself, then create
 * the #GtkImage from the pixbuf. (Or for animations, use
 * gdk_pixbuf_animation_new_from_file()).
 *
 * The storage type (gtk_image_get_storage_type()) of the returned
 * image is not defined, it will be whatever is appropriate for
 * displaying the file.
 *
629
 * Returns: a new #GtkImage
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
 *
 * Since: 3.4
 **/
GtkWidget*
gtk_image_new_from_resource (const gchar *resource_path)
{
  GtkImage *image;

  image = g_object_new (GTK_TYPE_IMAGE, NULL);

  gtk_image_set_from_resource (image, resource_path);

  return GTK_WIDGET (image);
}

645 646
/**
 * gtk_image_new_from_pixbuf:
647 648
 * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL
 *
649 650 651 652 653
 * Creates a new #GtkImage displaying @pixbuf.
 * The #GtkImage does not assume a reference to the
 * pixbuf; you still need to unref it if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
 * 
654 655
 * Note that this function just creates an #GtkImage from the pixbuf. The
 * #GtkImage created will not react to state changes. Should you want that, 
656
 * you should use gtk_image_new_from_icon_name().
657
 * 
658
 * Returns: a new #GtkImage
659
 **/
660 661 662 663 664
GtkWidget*
gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
665
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
666 667 668 669 670 671

  gtk_image_set_from_pixbuf (image, pixbuf);

  return GTK_WIDGET (image);  
}

672 673 674 675 676 677 678 679 680
/**
 * gtk_image_new_from_surface:
 * @surface: (allow-none): a #cairo_surface_t, or %NULL
 *
 * Creates a new #GtkImage displaying @surface.
 * The #GtkImage does not assume a reference to the
 * surface; you still need to unref it if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
 * 
681
 * Returns: a new #GtkImage
682 683
 *
 * Since: 3.10
684 685 686 687 688 689 690 691 692 693 694 695 696
 **/
GtkWidget*
gtk_image_new_from_surface (cairo_surface_t *surface)
{
  GtkImage *image;

  image = g_object_new (GTK_TYPE_IMAGE, NULL);

  gtk_image_set_from_surface (image, surface);

  return GTK_WIDGET (image);  
}

697 698 699
/**
 * gtk_image_new_from_stock:
 * @stock_id: a stock icon name
700
 * @size: (type int): a stock icon size
701 702
 * 
 * Creates a #GtkImage displaying a stock icon. Sample stock icon
703
 * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. Sample stock sizes
704
 * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
705
 * icon name isn’t known, the image will be empty.
706 707
 * You can register your own stock icon names, see
 * gtk_icon_factory_add_default() and gtk_icon_factory_add().
708
 * 
709
 * Returns: a new #GtkImage displaying the stock icon
710 711
 *
 * Deprecated: 3.10: Use gtk_image_new_from_icon_name() instead.
712
 **/
713 714
GtkWidget*
gtk_image_new_from_stock (const gchar    *stock_id,
715
                          GtkIconSize     size)
716 717 718
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
719
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
720

721
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
722
  gtk_image_set_from_stock (image, stock_id, size);
723
  G_GNUC_END_IGNORE_DEPRECATIONS;
724 725 726 727

  return GTK_WIDGET (image);
}

728 729 730
/**
 * gtk_image_new_from_icon_set:
 * @icon_set: a #GtkIconSet
731
 * @size: (type int): a stock icon size
732 733 734
 *
 * Creates a #GtkImage displaying an icon set. Sample stock sizes are
 * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
735
 * this function, usually it’s better to create a #GtkIconFactory, put
736 737 738 739 740 741 742 743 744
 * your icon sets in the icon factory, add the icon factory to the
 * list of default factories with gtk_icon_factory_add_default(), and
 * then use gtk_image_new_from_stock(). This will allow themes to
 * override the icon you ship with your application.
 *
 * The #GtkImage does not assume a reference to the
 * icon set; you still need to unref it if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
 * 
745
 * Returns: a new #GtkImage
746 747
 *
 * Deprecated: 3.10: Use gtk_image_new_from_icon_name() instead.
748
 **/
749 750
GtkWidget*
gtk_image_new_from_icon_set (GtkIconSet     *icon_set,
751
                             GtkIconSize     size)
752 753 754
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
755
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
756

757 758
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;

759
  gtk_image_set_from_icon_set (image, icon_set, size);
Elliot Lee's avatar
Elliot Lee committed
760

761 762
  G_GNUC_END_IGNORE_DEPRECATIONS;

Elliot Lee's avatar
Elliot Lee committed
763 764 765
  return GTK_WIDGET (image);
}

Havoc Pennington's avatar
Havoc Pennington committed
766 767 768 769 770 771 772 773
/**
 * gtk_image_new_from_animation:
 * @animation: an animation
 * 
 * Creates a #GtkImage displaying the given animation.
 * The #GtkImage does not assume a reference to the
 * animation; you still need to unref it if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
774 775 776 777 778 779
 *
 * Note that the animation frames are shown using a timeout with
 * #G_PRIORITY_DEFAULT. When using animations to indicate busyness,
 * keep in mind that the animation will only be shown if the main loop
 * is not busy with something that has a higher priority.
 *
780
 * Returns: a new #GtkImage widget
Havoc Pennington's avatar
Havoc Pennington committed
781 782 783 784 785 786 787 788
 **/
GtkWidget*
gtk_image_new_from_animation (GdkPixbufAnimation *animation)
{
  GtkImage *image;

  g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL);
  
Manish Singh's avatar
Manish Singh committed
789
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
Havoc Pennington's avatar
Havoc Pennington committed
790 791 792 793 794 795

  gtk_image_set_from_animation (image, animation);

  return GTK_WIDGET (image);
}

796 797 798
/**
 * gtk_image_new_from_icon_name:
 * @icon_name: an icon name
799
 * @size: (type int): a stock icon size
800 801
 * 
 * Creates a #GtkImage displaying an icon from the current icon theme.
802
 * If the icon name isn’t known, a “broken image” icon will be
803 804 805
 * displayed instead.  If the current icon theme is changed, the icon
 * will be updated appropriately.
 * 
806
 * Returns: a new #GtkImage displaying the themed icon
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
 *
 * Since: 2.6
 **/
GtkWidget*
gtk_image_new_from_icon_name (const gchar    *icon_name,
			      GtkIconSize     size)
{
  GtkImage *image;

  image = g_object_new (GTK_TYPE_IMAGE, NULL);

  gtk_image_set_from_icon_name (image, icon_name, size);

  return GTK_WIDGET (image);
}

823 824 825
/**
 * gtk_image_new_from_gicon:
 * @icon: an icon
826
 * @size: (type int): a stock icon size
827 828
 * 
 * Creates a #GtkImage displaying an icon from the current icon theme.
829
 * If the icon name isn’t known, a “broken image” icon will be
830 831 832
 * displayed instead.  If the current icon theme is changed, the icon
 * will be updated appropriately.
 * 
833
 * Returns: a new #GtkImage displaying the themed icon
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
 *
 * Since: 2.14
 **/
GtkWidget*
gtk_image_new_from_gicon (GIcon *icon,
			  GtkIconSize     size)
{
  GtkImage *image;

  image = g_object_new (GTK_TYPE_IMAGE, NULL);

  gtk_image_set_from_gicon (image, icon, size);

  return GTK_WIDGET (image);
}

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
typedef struct {
  GtkImage *image;
  gint scale_factor;
} LoaderData;

static void
on_loader_size_prepared (GdkPixbufLoader *loader,
			 gint             width,
			 gint             height,
			 gpointer         user_data)
{
  LoaderData *loader_data = user_data;
  gint scale_factor;
  GdkPixbufFormat *format;

  /* Let the regular icon helper code path handle non-scalable images */
  format = gdk_pixbuf_loader_get_format (loader);
  if (!gdk_pixbuf_format_is_scalable (format))
    {
      loader_data->scale_factor = 1;
      return;
    }

  scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (loader_data->image));
  gdk_pixbuf_loader_set_size (loader, width * scale_factor, height * scale_factor);
  loader_data->scale_factor = scale_factor;
}

static GdkPixbufAnimation *
load_scalable_with_loader (GtkImage    *image,
			   const gchar *file_path,
			   const gchar *resource_path,
			   gint        *scale_factor_out)
{
  GdkPixbufLoader *loader;
  GBytes *bytes;
  char *contents;
  gsize length;
  gboolean res;
  GdkPixbufAnimation *animation;
  LoaderData loader_data;

  animation = NULL;
  bytes = NULL;

  loader = gdk_pixbuf_loader_new ();
  loader_data.image = image;

  g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), &loader_data);

  if (resource_path != NULL)
    {
      bytes = g_resources_lookup_data (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
    }
  else if (file_path != NULL)
    {
      res = g_file_get_contents (file_path, &contents, &length, NULL);
      if (res)
	bytes = g_bytes_new_take (contents, length);
    }
  else
    {
      g_assert_not_reached ();
    }

  if (!bytes)
    goto out;

  if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
    goto out;

  if (!gdk_pixbuf_loader_close (loader, NULL))
    goto out;

  animation = gdk_pixbuf_loader_get_animation (loader);
  if (animation != NULL)
    {
      g_object_ref (animation);
      if (scale_factor_out != NULL)
	*scale_factor_out = loader_data.scale_factor;
    }

 out:
933
  gdk_pixbuf_loader_close (loader, NULL);
934 935 936 937 938 939
  g_object_unref (loader);
  g_bytes_unref (bytes);

  return animation;
}

940 941 942
/**
 * gtk_image_set_from_file:
 * @image: a #GtkImage
943
 * @filename: (type filename) (allow-none): a filename or %NULL
944 945 946
 *
 * See gtk_image_new_from_file() for details.
 **/
947 948 949 950
void
gtk_image_set_from_file   (GtkImage    *image,
                           const gchar *filename)
{
951
  GtkImagePrivate *priv;
Havoc Pennington's avatar
Havoc Pennington committed
952
  GdkPixbufAnimation *anim;
953
  gint scale_factor;
954
  
955
  g_return_if_fail (GTK_IS_IMAGE (image));
Havoc Pennington's avatar
Havoc Pennington committed
956

957 958
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
959
  g_object_freeze_notify (G_OBJECT (image));
960 961
  
  gtk_image_clear (image);
962 963

  if (filename == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
964
    {
965
      priv->filename = NULL;
Havoc Pennington's avatar
Havoc Pennington committed
966 967 968
      g_object_thaw_notify (G_OBJECT (image));
      return;
    }
969

970
  anim = load_scalable_with_loader (image, filename, NULL, &scale_factor);
971

Havoc Pennington's avatar
Havoc Pennington committed
972
  if (anim == NULL)
973
    {
974 975 976
      gtk_image_set_from_icon_name (image,
                                    "image-missing",
                                    DEFAULT_ICON_SIZE);
Havoc Pennington's avatar
Havoc Pennington committed
977
      g_object_thaw_notify (G_OBJECT (image));
978 979
      return;
    }
980

Havoc Pennington's avatar
Havoc Pennington committed
981 982 983 984
  /* We could just unconditionally set_from_animation,
   * but it's nicer for memory if we toss the animation
   * if it's just a single pixbuf
   */
985

Havoc Pennington's avatar
Havoc Pennington committed
986
  if (gdk_pixbuf_animation_is_static_image (anim))
987 988
    gtk_image_set_from_pixbuf (image,
			       gdk_pixbuf_animation_get_static_image (anim));
Havoc Pennington's avatar
Havoc Pennington committed
989
  else
990
    gtk_image_set_from_animation (image, anim);
Havoc Pennington's avatar
Havoc Pennington committed
991

992 993
  _gtk_icon_helper_set_pixbuf_scale (priv->icon_helper, scale_factor);

Manish Singh's avatar
Manish Singh committed
994
  g_object_unref (anim);
Havoc Pennington's avatar
Havoc Pennington committed
995

996
  priv->filename = g_strdup (filename);
997
  
Havoc Pennington's avatar
Havoc Pennington committed
998
  g_object_thaw_notify (G_OBJECT (image));
999 1000
}

1001 1002 1003 1004 1005 1006 1007 1008
/**
 * gtk_image_set_from_resource:
 * @image: a #GtkImage
 * @resource_path: (allow-none): a resource path or %NULL
 *
 * See gtk_image_new_from_resource() for details.
 **/
void
Benjamin Otte's avatar
Benjamin Otte committed
1009 1010
gtk_image_set_from_resource (GtkImage    *image,
			     const gchar *resource_path)
1011
{
1012
  GtkImagePrivate *priv;
1013
  GdkPixbufAnimation *animation;
1014
  gint scale_factor;
1015 1016 1017

  g_return_if_fail (GTK_IS_IMAGE (image));

1018 1019
  priv = image->priv;

1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
  g_object_freeze_notify (G_OBJECT (image));

  gtk_image_clear (image);

  if (resource_path == NULL)
    {
      g_object_thaw_notify (G_OBJECT (image));
      return;
    }

1030
  animation = load_scalable_with_loader (image, NULL, resource_path, &scale_factor);
1031

1032
  if (animation == NULL)
1033
    {
1034 1035 1036
      gtk_image_set_from_icon_name (image,
                                    "image-missing",
                                    DEFAULT_ICON_SIZE);
1037 1038 1039 1040
      g_object_thaw_notify (G_OBJECT (image));
      return;
    }

1041 1042 1043 1044
  if (gdk_pixbuf_animation_is_static_image (animation))
    gtk_image_set_from_pixbuf (image, gdk_pixbuf_animation_get_static_image (animation));
  else
    gtk_image_set_from_animation (image, animation);
1045 1046

  _gtk_icon_helper_set_pixbuf_scale (priv->icon_helper, scale_factor);
1047

1048 1049
  priv->resource_path = g_strdup (resource_path);

1050
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_RESOURCE]);
1051

1052
  g_object_unref (animation);
1053 1054 1055 1056 1057

  g_object_thaw_notify (G_OBJECT (image));
}


1058 1059 1060
/**
 * gtk_image_set_from_pixbuf:
 * @image: a #GtkImage
1061
 * @pixbuf: (allow-none): a #GdkPixbuf or %NULL
1062
 *
1063
 * See gtk_image_new_from_pixbuf() for details.
1064
 **/
1065 1066 1067 1068
void
gtk_image_set_from_pixbuf (GtkImage  *image,
                           GdkPixbuf *pixbuf)
{
1069
  GtkImagePrivate *priv;
1070

1071
  g_return_if_fail (GTK_IS_IMAGE (image));
1072 1073
  g_return_if_fail (pixbuf == NULL ||
                    GDK_IS_PIXBUF (pixbuf));
Havoc Pennington's avatar
Havoc Pennington committed
1074

1075 1076
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
1077
  g_object_freeze_notify (G_OBJECT (image));
1078 1079
  
  gtk_image_clear (image);
1080 1081

  if (pixbuf != NULL)
1082
    _gtk_icon_helper_set_pixbuf (priv->icon_helper, pixbuf);
Havoc Pennington's avatar
Havoc Pennington committed
1083

1084
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PIXBUF]);
1085
  
Havoc Pennington's avatar
Havoc Pennington committed
1086
  g_object_thaw_notify (G_OBJECT (image));
1087 1088
}

1089 1090 1091 1092
/**
 * gtk_image_set_from_stock:
 * @image: a #GtkImage
 * @stock_id: a stock icon name
1093
 * @size: (type int): a stock icon size
1094
 *
1095
 * See gtk_image_new_from_stock() for details.
1096 1097
 *
 * Deprecated: 3.10: Use gtk_image_set_from_icon_name() instead.
1098
 **/
1099 1100 1101
void
gtk_image_set_from_stock  (GtkImage       *image,
                           const gchar    *stock_id,
1102
                           GtkIconSize     size)
1103
{
1104
  GtkImagePrivate *priv;
Havoc Pennington's avatar
Havoc Pennington committed
1105
  gchar *new_id;
1106

1107
  g_return_if_fail (GTK_IS_IMAGE (image));
Havoc Pennington's avatar
Havoc Pennington committed
1108

1109 1110
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
1111 1112 1113
  g_object_freeze_notify (G_OBJECT (image));

  new_id = g_strdup (stock_id);
1114
  gtk_image_clear (image);
1115

Havoc Pennington's avatar
Havoc Pennington committed
1116 1117
  if (new_id)
    {
1118 1119
      _gtk_icon_helper_set_stock_id (priv->icon_helper, new_id, size);
      g_free (new_id);
1120
    }
Havoc Pennington's avatar
Havoc Pennington committed
1121

1122 1123 1124
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_STOCK]);
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SIZE]);

Havoc Pennington's avatar
Havoc Pennington committed
1125
  g_object_thaw_notify (G_OBJECT (image));
1126 1127
}

1128 1129 1130 1131
/**
 * gtk_image_set_from_icon_set:
 * @image: a #GtkImage
 * @icon_set: a #GtkIconSet
1132
 * @size: (type int): a stock icon size
1133 1134
 *
 * See gtk_image_new_from_icon_set() for details.
1135 1136
 *
 * Deprecated: 3.10: Use gtk_image_set_from_icon_name() instead.
1137
 **/
1138 1139 1140
void
gtk_image_set_from_icon_set  (GtkImage       *image,
                              GtkIconSet     *icon_set,
1141
                              GtkIconSize     size)
1142
{
1143
  GtkImagePrivate *priv;
1144

1145 1146
  g_return_if_fail (GTK_IS_IMAGE (image));

1147 1148
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
1149
  g_object_freeze_notify (G_OBJECT (image));
1150

1151 1152
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;

1153 1154
  if (icon_set)
    gtk_icon_set_ref (icon_set);
1155

1156
  gtk_image_clear (image);
1157 1158

  if (icon_set)
1159
    {
1160 1161
      _gtk_icon_helper_set_icon_set (priv->icon_helper, icon_set, size);
      gtk_icon_set_unref (icon_set);
1162
    }
1163 1164 1165

  G_GNUC_END_IGNORE_DEPRECATIONS;

1166 1167 1168
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SET]);
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SIZE]);

Havoc Pennington's avatar
Havoc Pennington committed
1169
  g_object_thaw_notify (G_OBJECT (image));
1170 1171
}

Havoc Pennington's avatar
Havoc Pennington committed
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
/**
 * gtk_image_set_from_animation:
 * @image: a #GtkImage
 * @animation: the #GdkPixbufAnimation
 * 
 * Causes the #GtkImage to display the given animation (or display
 * nothing, if you set the animation to %NULL).
 **/
void
gtk_image_set_from_animation (GtkImage           *image,
                              GdkPixbufAnimation *animation)
{
1184
  GtkImagePrivate *priv;
1185

Havoc Pennington's avatar
Havoc Pennington committed
1186 1187 1188
  g_return_if_fail (GTK_IS_IMAGE (image));
  g_return_if_fail (animation == NULL ||
                    GDK_IS_PIXBUF_ANIMATION (animation));
Havoc Pennington's avatar
Havoc Pennington committed
1189

1190 1191
  priv = image->priv;

Havoc Pennington's avatar
Havoc Pennington committed
1192
  g_object_freeze_notify (G_OBJECT (image));
Havoc Pennington's avatar
Havoc Pennington committed
1193 1194
  
  if (animation)
Manish Singh's avatar
Manish Singh committed
1195
    g_object_ref (animation);
Havoc Pennington's avatar
Havoc Pennington committed
1196

1197
  gtk_image_clear (image);
Havoc Pennington's avatar
Havoc Pennington committed
1198 1199 1200

  if (animation != NULL)
    {
1201 1202
      _gtk_icon_helper_set_animation (priv->icon_helper, animation);
      g_object_unref (animation);
Havoc Pennington's avatar
Havoc Pennington committed
1203
    }
Havoc Pennington's avatar
Havoc Pennington committed
1204

1205 1206
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PIXBUF_ANIMATION]);

Havoc Pennington's avatar
Havoc Pennington committed
1207
  g_object_thaw_notify (G_OBJECT (image));
Havoc Pennington's avatar
Havoc Pennington committed
1208 1209
}

1210 1211 1212 1213
/**
 * gtk_image_set_from_icon_name:
 * @image: a #GtkImage
 * @icon_name: an icon name
1214
 * @size: (type int): an icon size
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
 *
 * See gtk_image_new_from_icon_name() for details.
 * 
 * Since: 2.6
 **/
void
gtk_image_set_from_icon_name  (GtkImage       *image,
			       const gchar    *icon_name,
			       GtkIconSize     size)
{
1225
  GtkImagePrivate *priv;
1226
  gchar *new_name;
1227

1228 1229
  g_return_if_fail (GTK_IS_IMAGE (image));

1230 1231
  priv = image->priv;

1232 1233 1234
  g_object_freeze_notify (G_OBJECT (image));

  new_name = g_strdup (icon_name);
1235
  gtk_image_clear (image);
1236 1237 1238

  if (new_name)
    {
1239 1240
      _gtk_icon_helper_set_icon_name (priv->icon_helper, new_name, size);
      g_free (new_name);
1241 1242
    }

1243 1244
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_NAME]);
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SIZE]);
1245
  
1246 1247 1248
  g_object_thaw_notify (G_OBJECT (image));
}

1249 1250 1251 1252
/**
 * gtk_image_set_from_gicon:
 * @image: a #GtkImage
 * @icon: an icon
1253
 * @size: (type int): an icon size
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263
 *
 * See gtk_image_new_from_gicon() for details.
 * 
 * Since: 2.14
 **/
void
gtk_image_set_from_gicon  (GtkImage       *image,
			   GIcon          *icon,
			   GtkIconSize     size)
{
1264
  GtkImagePrivate *priv;
1265

1266 1267
  g_return_if_fail (GTK_IS_IMAGE (image));

1268 1269
  priv = image->priv;

1270 1271 1272 1273
  g_object_freeze_notify (G_OBJECT (image));

  if (icon)
    g_object_ref (icon);
1274

1275
  gtk_image_clear (image);
1276 1277 1278

  if (icon)
    {
1279 1280
      _gtk_icon_helper_set_gicon (priv->icon_helper, icon, size);
      g_object_unref (icon);
1281 1282
    }

1283 1284
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_GICON]);
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_ICON_SIZE]);
1285
  
1286 1287 1288
  g_object_thaw_notify (G_OBJECT (image));
}

1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
/**
 * gtk_image_set_from_surface:
 * @image: a #GtkImage
 * @surface: a cairo_surface_t
 *
 * See gtk_image_new_from_surface() for details.
 * 
 * Since: 3.10
 **/
void
gtk_image_set_from_surface (GtkImage       *image,
			    cairo_surface_t *surface)
{
  GtkImagePrivate *priv;

  g_return_if_fail (GTK_IS_IMAGE (image));

  priv = image->priv;

  g_object_freeze_notify (G_OBJECT (image));

  if (surface)
    cairo_surface_reference (surface);

1313
  gtk_image_clear (image);
1314 1315 1316 1317 1318 1319 1320

  if (surface)
    {
      _gtk_icon_helper_set_surface (priv->icon_helper, surface);
      cairo_surface_destroy (surface);
    }

1321
  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_SURFACE]);
1322
  
1323 1324 1325
  g_object_thaw_notify (G_OBJECT (image));
}

1326 1327 1328 1329 1330 1331 1332 1333
/**
 * gtk_image_get_storage_type:
 * @image: a #GtkImage
 * 
 * Gets the type of representation being used by the #GtkImage
 * to store image data. If the #GtkImage has no image data,
 * the return value will be %GTK_IMAGE_EMPTY.
 * 
1334
 * Returns: image representation being used
1335
 **/
1336 1337 1338 1339 1340
GtkImageType
gtk_image_get_storage_type (GtkImage *image)
{
  g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);

1341
  return _gtk_icon_helper_get_storage_type (image->priv->icon_helper);
1342 1343
}

1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
/**
 * gtk_image_get_pixbuf:
 * @image: a #GtkImage
 *
 * Gets the #GdkPixbuf being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
 * The caller of this function does not own a reference to the
 * returned pixbuf.
 * 
1354
 * Returns: (transfer none): the displayed pixbuf, or %NULL if
1355
 * the image is empty
1356
 **/
1357 1358 1359 1360 1361
GdkPixbuf*
gtk_image_get_pixbuf (GtkImage *image)
{
  g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);

1362
  return _gtk_icon_helper_peek_pixbuf (image->priv->icon_helper);
1363 1364
}

1365 1366 1367
/**
 * gtk_image_get_stock:
 * @image: a #GtkImage
1368 1369
 * @stock_id: (out) (transfer none) (allow-none): place to store a
 *     stock icon name, or %NULL
1370 1371
 * @size: (out) (allow-none) (type int): place to store a stock icon
 *     size, or %NULL
1372 1373 1374 1375
 *
 * Gets the stock icon name and size being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_STOCK (see gtk_image_get_storage_type()).
1376
 * The returned string is owned by the #GtkImage and should not
1377
 * be freed.
1378 1379
 *
 * Deprecated: 3.10: Use gtk_image_get_icon_name() instead.
1380
 **/
1381 1382 1383
void
gtk_image_get_stock  (GtkImage        *image,
                      gchar          **stock_id,
1384
                      GtkIconSize     *size)
1385
{
1386
  GtkImagePrivate *priv;
1387

1388 1389
  g_return_if_fail (GTK_IS_IMAGE (image