gtkimage.c 60.4 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1
2
3
4
/* GTK - The GIMP Toolkit
 * 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
15
16
17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19
20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22
23
24
25
26
 * 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/. 
 */

27
#include <config.h>
28
#include <math.h>
29
#include "gtkalias.h"
Elliot Lee's avatar
Elliot Lee committed
30
31
#include "gtkcontainer.h"
#include "gtkimage.h"
32
#include "gtkiconfactory.h"
33
#include "gtkstock.h"
34
#include "gtkicontheme.h"
Havoc Pennington's avatar
Havoc Pennington committed
35
#include "gtkintl.h"
Havoc Pennington's avatar
Havoc Pennington committed
36
#include <string.h>
Elliot Lee's avatar
Elliot Lee committed
37

38
39
40
41
42
43
44
45
typedef struct _GtkImagePrivate GtkImagePrivate;

struct _GtkImagePrivate
{
  gint pixel_size;
};

#define GTK_IMAGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_IMAGE, GtkImagePrivate))
46
47


Havoc Pennington's avatar
Havoc Pennington committed
48
49
#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON

50
51
52
53
static void gtk_image_class_init   (GtkImageClass  *klass);
static void gtk_image_init         (GtkImage       *image);
static gint gtk_image_expose       (GtkWidget      *widget,
                                    GdkEventExpose *event);
Havoc Pennington's avatar
Havoc Pennington committed
54
static void gtk_image_unmap        (GtkWidget      *widget);
55
static void gtk_image_unrealize    (GtkWidget      *widget);
56
57
static void gtk_image_size_request (GtkWidget      *widget,
                                    GtkRequisition *requisition);
58
59
static void gtk_image_style_set    (GtkWidget      *widget,
				    GtkStyle       *prev_style);
60
static void gtk_image_destroy      (GtkObject      *object);
61
static void gtk_image_clear        (GtkImage       *image);
62
static void gtk_image_reset        (GtkImage       *image);
63
64
static void gtk_image_calc_size    (GtkImage       *image);

65
66
67
static void gtk_image_update_size  (GtkImage       *image,
                                    gint            image_width,
                                    gint            image_height);
Elliot Lee's avatar
Elliot Lee committed
68

Havoc Pennington's avatar
Havoc Pennington committed
69
70
71
72
73
74
75
76
77
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);

78
static gpointer parent_class;
Elliot Lee's avatar
Elliot Lee committed
79

Havoc Pennington's avatar
Havoc Pennington committed
80
81
82
83
84
85
86
87
88
89
90
enum
{
  PROP_0,
  PROP_PIXBUF,
  PROP_PIXMAP,
  PROP_IMAGE,
  PROP_MASK,
  PROP_FILE,
  PROP_STOCK,
  PROP_ICON_SET,
  PROP_ICON_SIZE,
91
  PROP_PIXEL_SIZE,
Havoc Pennington's avatar
Havoc Pennington committed
92
  PROP_PIXBUF_ANIMATION,
93
  PROP_ICON_NAME,
Havoc Pennington's avatar
Havoc Pennington committed
94
95
96
  PROP_STORAGE_TYPE
};

Manish Singh's avatar
Manish Singh committed
97
GType
98
gtk_image_get_type (void)
Elliot Lee's avatar
Elliot Lee committed
99
{
Manish Singh's avatar
Manish Singh committed
100
  static GType image_type = 0;
Elliot Lee's avatar
Elliot Lee committed
101
102
103

  if (!image_type)
    {
Manish Singh's avatar
Manish Singh committed
104
      static const GTypeInfo image_info =
Elliot Lee's avatar
Elliot Lee committed
105
106
      {
	sizeof (GtkImageClass),
Manish Singh's avatar
Manish Singh committed
107
108
109
110
111
112
113
114
	NULL,		/* base_init */
	NULL,		/* base_finalize */
	(GClassInitFunc) gtk_image_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
	sizeof (GtkImage),
	0,		/* n_preallocs */
	(GInstanceInitFunc) gtk_image_init,
Elliot Lee's avatar
Elliot Lee committed
115
116
      };

Manish Singh's avatar
Manish Singh committed
117
118
      image_type = g_type_register_static (GTK_TYPE_MISC, "GtkImage",
					   &image_info, 0);
Elliot Lee's avatar
Elliot Lee committed
119
120
121
122
123
124
125
126
    }

  return image_type;
}

static void
gtk_image_class_init (GtkImageClass *class)
{
Havoc Pennington's avatar
Havoc Pennington committed
127
  GObjectClass *gobject_class;
128
  GtkObjectClass *object_class;
Elliot Lee's avatar
Elliot Lee committed
129
130
  GtkWidgetClass *widget_class;

131
  parent_class = g_type_class_peek_parent (class);
132

Havoc Pennington's avatar
Havoc Pennington committed
133
134
135
136
137
138
  gobject_class = G_OBJECT_CLASS (class);
  
  gobject_class->set_property = gtk_image_set_property;
  gobject_class->get_property = gtk_image_get_property;
  
  object_class = GTK_OBJECT_CLASS (class);
139
  
140
141
  object_class->destroy = gtk_image_destroy;

Havoc Pennington's avatar
Havoc Pennington committed
142
143
  widget_class = GTK_WIDGET_CLASS (class);
  
Elliot Lee's avatar
Elliot Lee committed
144
  widget_class->expose_event = gtk_image_expose;
145
  widget_class->size_request = gtk_image_size_request;
Havoc Pennington's avatar
Havoc Pennington committed
146
  widget_class->unmap = gtk_image_unmap;
147
  widget_class->unrealize = gtk_image_unrealize;
148
  widget_class->style_set = gtk_image_style_set;
Havoc Pennington's avatar
Havoc Pennington committed
149
150
151
152
  
  g_object_class_install_property (gobject_class,
                                   PROP_PIXBUF,
                                   g_param_spec_object ("pixbuf",
153
154
                                                        P_("Pixbuf"),
                                                        P_("A GdkPixbuf to display"),
Havoc Pennington's avatar
Havoc Pennington committed
155
156
157
158
159
160
                                                        GDK_TYPE_PIXBUF,
                                                        G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_PIXMAP,
                                   g_param_spec_object ("pixmap",
161
162
                                                        P_("Pixmap"),
                                                        P_("A GdkPixmap to display"),
Havoc Pennington's avatar
Havoc Pennington committed
163
164
165
166
167
168
                                                        GDK_TYPE_PIXMAP,
                                                        G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_IMAGE,
                                   g_param_spec_object ("image",
169
170
                                                        P_("Image"),
                                                        P_("A GdkImage to display"),
Havoc Pennington's avatar
Havoc Pennington committed
171
172
173
174
175
176
                                                        GDK_TYPE_IMAGE,
                                                        G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_MASK,
                                   g_param_spec_object ("mask",
177
178
                                                        P_("Mask"),
                                                        P_("Mask bitmap to use with GdkImage or GdkPixmap"),
Havoc Pennington's avatar
Havoc Pennington committed
179
180
181
182
183
184
                                                        GDK_TYPE_PIXMAP,
                                                        G_PARAM_READWRITE));
  
  g_object_class_install_property (gobject_class,
                                   PROP_FILE,
                                   g_param_spec_string ("file",
185
186
                                                        P_("Filename"),
                                                        P_("Filename to load and display"),
Havoc Pennington's avatar
Havoc Pennington committed
187
188
189
190
191
192
193
                                                        NULL,
                                                        G_PARAM_WRITABLE));
  

  g_object_class_install_property (gobject_class,
                                   PROP_STOCK,
                                   g_param_spec_string ("stock",
194
195
                                                        P_("Stock ID"),
                                                        P_("Stock ID for a stock image to display"),
Havoc Pennington's avatar
Havoc Pennington committed
196
197
198
199
200
201
                                                        NULL,
                                                        G_PARAM_READWRITE));
  
  g_object_class_install_property (gobject_class,
                                   PROP_ICON_SET,
                                   g_param_spec_boxed ("icon_set",
202
203
                                                       P_("Icon set"),
                                                       P_("Icon set to display"),
Havoc Pennington's avatar
Havoc Pennington committed
204
205
206
207
208
209
                                                       GTK_TYPE_ICON_SET,
                                                       G_PARAM_READWRITE));
  
  g_object_class_install_property (gobject_class,
                                   PROP_ICON_SIZE,
                                   g_param_spec_int ("icon_size",
210
                                                     P_("Icon size"),
211
                                                     P_("Symbolic size to use for stock icon, icon set or named icon"),
Havoc Pennington's avatar
Havoc Pennington committed
212
213
214
                                                     0, G_MAXINT,
                                                     DEFAULT_ICON_SIZE,
                                                     G_PARAM_READWRITE));
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  /**
   * GtkImage:pixel-size:
   *
   * The :pixel-size property can be used to specify a fixed size
   * overriding the :icon-size property for images of type 
   * %GTK_IMAGE_ICON_NAME. 
   *
   * Since: 2.6
   */
  g_object_class_install_property (gobject_class,
				   PROP_PIXEL_SIZE,
				   g_param_spec_int ("pixel_size",
						     P_("Pixel size"),
						     P_("Pixel size to use for named icon"),
						     -1, G_MAXINT,
						     -1,
						     G_PARAM_READWRITE));
  
Havoc Pennington's avatar
Havoc Pennington committed
233
234
235
  g_object_class_install_property (gobject_class,
                                   PROP_PIXBUF_ANIMATION,
                                   g_param_spec_object ("pixbuf_animation",
236
237
                                                        P_("Animation"),
                                                        P_("GdkPixbufAnimation to display"),
Havoc Pennington's avatar
Havoc Pennington committed
238
239
                                                        GDK_TYPE_PIXBUF_ANIMATION,
                                                        G_PARAM_READWRITE));
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

  /**
   * GtkImage:icon-name:
   *
   * The name of the icon in the icon theme.  If the icon theme is
   * changed, the image will be updated automatically.
   *
   * Since: 2.6
   */
  g_object_class_install_property (gobject_class,
                                   PROP_ICON_NAME,
                                   g_param_spec_string ("icon_name",
                                                        P_("Icon Name"),
                                                        P_("The name of the icon from the icon theme"),
                                                        NULL,
                                                        G_PARAM_READWRITE));
Havoc Pennington's avatar
Havoc Pennington committed
256
257
258
259
  
  g_object_class_install_property (gobject_class,
                                   PROP_STORAGE_TYPE,
                                   g_param_spec_enum ("storage_type",
260
261
                                                      P_("Storage type"),
                                                      P_("The representation being used for image data"),
Havoc Pennington's avatar
Havoc Pennington committed
262
263
264
                                                      GTK_TYPE_IMAGE_TYPE,
                                                      GTK_IMAGE_EMPTY,
                                                      G_PARAM_READABLE));
265
266

  g_type_class_add_private (object_class, sizeof (GtkImagePrivate));
Elliot Lee's avatar
Elliot Lee committed
267
268
269
270
271
}

static void
gtk_image_init (GtkImage *image)
{
272
273
  GtkImagePrivate *priv = GTK_IMAGE_GET_PRIVATE (image);

Elliot Lee's avatar
Elliot Lee committed
274
275
  GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);

276
  image->storage_type = GTK_IMAGE_EMPTY;
Havoc Pennington's avatar
Havoc Pennington committed
277
278
  image->icon_size = DEFAULT_ICON_SIZE;
  image->mask = NULL;
279
280

  priv->pixel_size = -1;
Elliot Lee's avatar
Elliot Lee committed
281
282
}

283
284
285
286
287
288
289
290
291
292
static void
gtk_image_destroy (GtkObject *object)
{
  GtkImage *image = GTK_IMAGE (object);

  gtk_image_clear (image);
  
  GTK_OBJECT_CLASS (parent_class)->destroy (object);
}

Havoc Pennington's avatar
Havoc Pennington committed
293
294
295
296
297
298
299
static void 
gtk_image_set_property (GObject      *object,
			guint         prop_id,
			const GValue *value,
			GParamSpec   *pspec)
{
  GtkImage *image;
300
  GtkImagePrivate *priv;
Havoc Pennington's avatar
Havoc Pennington committed
301
302

  image = GTK_IMAGE (object);
303
  priv = GTK_IMAGE_GET_PRIVATE (image);
Havoc Pennington's avatar
Havoc Pennington committed
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  
  switch (prop_id)
    {
    case PROP_PIXBUF:
      gtk_image_set_from_pixbuf (image,
                                 g_value_get_object (value));
      break;
    case PROP_PIXMAP:
      gtk_image_set_from_pixmap (image,
                                 g_value_get_object (value),
                                 image->mask);
      break;
    case PROP_IMAGE:
      gtk_image_set_from_image (image,
                                g_value_get_object (value),
                                image->mask);
      break;
    case PROP_MASK:
      if (image->storage_type == GTK_IMAGE_PIXMAP)
        gtk_image_set_from_pixmap (image,
                                   image->data.pixmap.pixmap,
                                   g_value_get_object (value));
      else if (image->storage_type == GTK_IMAGE_IMAGE)
        gtk_image_set_from_image (image,
                                  image->data.image.image,
                                  g_value_get_object (value));
      else
        {
          GdkBitmap *mask;

          mask = g_value_get_object (value);

          if (mask)
Manish Singh's avatar
Manish Singh committed
337
            g_object_ref (mask);
Havoc Pennington's avatar
Havoc Pennington committed
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
          
          gtk_image_reset (image);

          image->mask = mask;
        }
      break;
    case PROP_FILE:
      gtk_image_set_from_file (image,
                               g_value_get_string (value));
      break;
    case PROP_STOCK:
      gtk_image_set_from_stock (image, g_value_get_string (value),
                                image->icon_size);
      break;
    case PROP_ICON_SET:
      gtk_image_set_from_icon_set (image, g_value_get_boxed (value),
                                   image->icon_size);
      break;
    case PROP_ICON_SIZE:
      if (image->storage_type == GTK_IMAGE_STOCK)
        gtk_image_set_from_stock (image,
                                  image->data.stock.stock_id,
                                  g_value_get_int (value));
      else if (image->storage_type == GTK_IMAGE_ICON_SET)
        gtk_image_set_from_icon_set (image,
                                     image->data.icon_set.icon_set,
                                     g_value_get_int (value));
365
366
367
368
      else if (image->storage_type == GTK_IMAGE_ICON_NAME)
        gtk_image_set_from_icon_name (image,
				      image->data.name.icon_name,
				      g_value_get_int (value));
Havoc Pennington's avatar
Havoc Pennington committed
369
370
371
372
      else
        /* Save to be used when STOCK or ICON_SET property comes in */
        image->icon_size = g_value_get_int (value);
      break;
373
374
375
    case PROP_PIXEL_SIZE:
      priv->pixel_size = g_value_get_int (value);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
376
377
378
379
    case PROP_PIXBUF_ANIMATION:
      gtk_image_set_from_animation (image,
                                    g_value_get_object (value));
      break;
380
381
382
    case PROP_ICON_NAME:
      gtk_image_set_from_icon_name (image, g_value_get_string (value),
				    image->icon_size);
Havoc Pennington's avatar
Havoc Pennington committed
383
384
385
386
387
388
389
390
391
392
393
394
395
    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)
{
  GtkImage *image;
396
  GtkImagePrivate *priv;
Havoc Pennington's avatar
Havoc Pennington committed
397
398

  image = GTK_IMAGE (object);
399
  priv = GTK_IMAGE_GET_PRIVATE (image);
Havoc Pennington's avatar
Havoc Pennington committed
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

  /* The "getter" functions whine if you try to get the wrong
   * storage type. This function is instead robust against that,
   * so that GUI builders don't have to jump through hoops
   * to avoid g_warning
   */
  
  switch (prop_id)
    {
    case PROP_PIXBUF:
      if (image->storage_type != GTK_IMAGE_PIXBUF)
        g_value_set_object (value, NULL);
      else
        g_value_set_object (value,
                            gtk_image_get_pixbuf (image));
      break;
    case PROP_PIXMAP:
      if (image->storage_type != GTK_IMAGE_PIXMAP)
        g_value_set_object (value, NULL);
      else
        g_value_set_object (value,
                            image->data.pixmap.pixmap);
      break;
    case PROP_MASK:
      g_value_set_object (value, image->mask);
      break;
    case PROP_IMAGE:
      if (image->storage_type != GTK_IMAGE_IMAGE)
        g_value_set_object (value, NULL);
      else
        g_value_set_object (value,
                            image->data.image.image);
      break;
    case PROP_STOCK:
      if (image->storage_type != GTK_IMAGE_STOCK)
        g_value_set_string (value, NULL);
      else
        g_value_set_string (value,
                            image->data.stock.stock_id);
      break;
    case PROP_ICON_SET:
      if (image->storage_type != GTK_IMAGE_ICON_SET)
        g_value_set_boxed (value, NULL);
      else
        g_value_set_boxed (value,
                           image->data.icon_set.icon_set);
      break;      
    case PROP_ICON_SIZE:
      g_value_set_int (value, image->icon_size);
      break;
450
451
452
    case PROP_PIXEL_SIZE:
      g_value_set_int (value, priv->pixel_size);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
453
454
455
456
457
458
459
    case PROP_PIXBUF_ANIMATION:
      if (image->storage_type != GTK_IMAGE_ANIMATION)
        g_value_set_object (value, NULL);
      else
        g_value_set_object (value,
                            image->data.anim.anim);
      break;
460
461
462
463
464
465
466
    case PROP_ICON_NAME:
      if (image->storage_type != GTK_IMAGE_ICON_NAME)
	g_value_set_object (value, NULL);
      else
	g_value_set_string (value,
			    image->data.name.icon_name);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
467
468
469
470
471
472
473
474
475
476
    case PROP_STORAGE_TYPE:
      g_value_set_enum (value, image->storage_type);
      break;
      
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

477

478
479
480
481
482
483
/**
 * gtk_image_new_from_pixmap:
 * @pixmap: a #GdkPixmap, or %NULL
 * @mask: a #GdkBitmap, or %NULL
 * 
 * Creates a #GtkImage widget displaying @pixmap with a @mask.
Matthias Clasen's avatar
Matthias Clasen committed
484
 * A #GdkPixmap is a server-side image buffer in the pixel format of the
485
486
487
488
489
490
 * current display. The #GtkImage does not assume a reference to the
 * pixmap or mask; you still need to unref them if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
 * 
 * Return value: a new #GtkImage
 **/
Elliot Lee's avatar
Elliot Lee committed
491
GtkWidget*
492
493
gtk_image_new_from_pixmap (GdkPixmap *pixmap,
                           GdkBitmap *mask)
Elliot Lee's avatar
Elliot Lee committed
494
495
496
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
497
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
498
499
500
501
502
503

  gtk_image_set_from_pixmap (image, pixmap, mask);

  return GTK_WIDGET (image);
}

504
505
506
507
508
509
510
511
512
513
514
515
516
517
/**
 * gtk_image_new_from_image:
 * @image: a #GdkImage, or %NULL
 * @mask: a #GdkBitmap, or %NULL 
 * 
 * Creates a #GtkImage widget displaying a @image with a @mask.
 * A #GdkImage is a client-side image buffer in the pixel format of the
 * current display.
 * The #GtkImage does not assume a reference to the
 * image or mask; you still need to unref them if you own references.
 * #GtkImage will add its own reference rather than adopting yours.
 * 
 * Return value: a new #GtkImage
 **/
518
519
520
521
522
GtkWidget*
gtk_image_new_from_image  (GdkImage  *gdk_image,
                           GdkBitmap *mask)
{
  GtkImage *image;
Elliot Lee's avatar
Elliot Lee committed
523

Manish Singh's avatar
Manish Singh committed
524
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
Elliot Lee's avatar
Elliot Lee committed
525

526
527
528
529
530
  gtk_image_set_from_image (image, gdk_image, mask);

  return GTK_WIDGET (image);
}

531
532
533
534
/**
 * gtk_image_new_from_file:
 * @filename: a filename
 * 
Havoc Pennington's avatar
Havoc Pennington committed
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
 * Creates a new #GtkImage displaying the file @filename. If the file
 * isn't found or can't be loaded, the resulting #GtkImage will
 * display a "broken image" icon. This function never returns %NULL,
 * 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.
551
552
553
 * 
 * Return value: a new #GtkImage
 **/
554
555
556
557
558
GtkWidget*
gtk_image_new_from_file   (const gchar *filename)
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
559
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
560
561
562
563
564
565

  gtk_image_set_from_file (image, filename);

  return GTK_WIDGET (image);
}

566
567
568
569
570
571
572
573
574
/**
 * gtk_image_new_from_pixbuf:
 * @pixbuf: a #GdkPixbuf, or %NULL
 * 
 * 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.
 * 
575
576
 * Note that this function just creates an #GtkImage from the pixbuf.  The
 * #GtkImage created will not react to state changes.  Should you want that, you
Havoc Pennington's avatar
Havoc Pennington committed
577
 * should use gtk_image_new_from_icon_set().
578
 * 
579
580
 * Return value: a new #GtkImage
 **/
581
582
583
584
585
GtkWidget*
gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
586
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
587
588
589
590
591
592

  gtk_image_set_from_pixbuf (image, pixbuf);

  return GTK_WIDGET (image);  
}

593
594
595
596
597
598
/**
 * gtk_image_new_from_stock:
 * @stock_id: a stock icon name
 * @size: a stock icon size
 * 
 * Creates a #GtkImage displaying a stock icon. Sample stock icon
Havoc Pennington's avatar
Havoc Pennington committed
599
 * names are #GTK_STOCK_OPEN, #GTK_STOCK_EXIT. Sample stock sizes
600
601
 * are #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. If the stock
 * icon name isn't known, a "broken image" icon will be displayed instead.
Havoc Pennington's avatar
Havoc Pennington committed
602
603
 * You can register your own stock icon names, see
 * gtk_icon_factory_add_default() and gtk_icon_factory_add().
604
605
606
 * 
 * Return value: a new #GtkImage displaying the stock icon
 **/
607
608
GtkWidget*
gtk_image_new_from_stock (const gchar    *stock_id,
609
                          GtkIconSize     size)
610
611
612
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
613
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
614
615
616
617
618
619

  gtk_image_set_from_stock (image, stock_id, size);

  return GTK_WIDGET (image);
}

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
/**
 * gtk_image_new_from_icon_set:
 * @icon_set: a #GtkIconSet
 * @size: a stock icon size
 *
 * Creates a #GtkImage displaying an icon set. Sample stock sizes are
 * #GTK_ICON_SIZE_MENU, #GTK_ICON_SIZE_SMALL_TOOLBAR. Instead of using
 * this function, usually it's better to create a #GtkIconFactory, put
 * 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.
 * 
 * 
 * Return value: a new #GtkImage
 **/
640
641
GtkWidget*
gtk_image_new_from_icon_set (GtkIconSet     *icon_set,
642
                             GtkIconSize     size)
643
644
645
{
  GtkImage *image;

Manish Singh's avatar
Manish Singh committed
646
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
647
648

  gtk_image_set_from_icon_set (image, icon_set, size);
Elliot Lee's avatar
Elliot Lee committed
649
650
651
652

  return GTK_WIDGET (image);
}

Havoc Pennington's avatar
Havoc Pennington committed
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
/**
 * 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.
 * 
 * Return value: a new #GtkImage widget
 **/
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
671
  image = g_object_new (GTK_TYPE_IMAGE, NULL);
Havoc Pennington's avatar
Havoc Pennington committed
672
673
674
675
676
677

  gtk_image_set_from_animation (image, animation);

  return GTK_WIDGET (image);
}

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
/**
 * gtk_image_new_from_icon_name:
 * @icon_name: an icon name
 * @size: a stock icon size
 * 
 * Creates a #GtkImage displaying an icon from the current icon theme.
 * If the icon name isn't known, a "broken image" icon will be
 * displayed instead.  If the current icon theme is changed, the icon
 * will be updated appropriately.
 * 
 * Return value: a new #GtkImage displaying the themed icon
 *
 * 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);
}

705
706
707
708
709
710
711
712
713
/**
 * gtk_image_set_from_pixmap:
 * @image: a #GtkImage
 * @pixmap: a #GdkPixmap or %NULL
 * @mask: a #GdkBitmap or %NULL
 *
 * See gtk_image_new_from_pixmap() for details.
 * 
 **/
Elliot Lee's avatar
Elliot Lee committed
714
void
715
716
717
718
719
720
721
722
723
gtk_image_set_from_pixmap (GtkImage  *image,
                           GdkPixmap *pixmap,
                           GdkBitmap *mask)
{
  g_return_if_fail (GTK_IS_IMAGE (image));
  g_return_if_fail (pixmap == NULL ||
                    GDK_IS_PIXMAP (pixmap));
  g_return_if_fail (mask == NULL ||
                    GDK_IS_PIXMAP (mask));
Havoc Pennington's avatar
Havoc Pennington committed
724
725

  g_object_freeze_notify (G_OBJECT (image));
726
727
  
  if (pixmap)
Manish Singh's avatar
Manish Singh committed
728
    g_object_ref (pixmap);
729
730

  if (mask)
Manish Singh's avatar
Manish Singh committed
731
    g_object_ref (mask);
732

733
  gtk_image_reset (image);
734

Havoc Pennington's avatar
Havoc Pennington committed
735
736
  image->mask = mask;
  
737
738
739
740
741
742
743
744
745
746
747
748
749
  if (pixmap)
    {
      int width;
      int height;
      
      image->storage_type = GTK_IMAGE_PIXMAP;

      image->data.pixmap.pixmap = pixmap;

      gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);

      gtk_image_update_size (image, width, height);
    }
Havoc Pennington's avatar
Havoc Pennington committed
750
751
752
753
754

  g_object_notify (G_OBJECT (image), "pixmap");
  g_object_notify (G_OBJECT (image), "mask");
  
  g_object_thaw_notify (G_OBJECT (image));
755
756
}

757
758
759
760
761
762
763
764
765
/**
 * gtk_image_set_from_image:
 * @image: a #GtkImage
 * @gdk_image: a #GdkImage or %NULL
 * @mask: a #GdkBitmap or %NULL
 *
 * See gtk_image_new_from_image() for details.
 * 
 **/
766
767
768
769
void
gtk_image_set_from_image  (GtkImage  *image,
                           GdkImage  *gdk_image,
                           GdkBitmap *mask)
Elliot Lee's avatar
Elliot Lee committed
770
771
{
  g_return_if_fail (GTK_IS_IMAGE (image));
772
773
774
775
776
  g_return_if_fail (gdk_image == NULL ||
                    GDK_IS_IMAGE (gdk_image));
  g_return_if_fail (mask == NULL ||
                    GDK_IS_PIXMAP (mask));

Havoc Pennington's avatar
Havoc Pennington committed
777
  g_object_freeze_notify (G_OBJECT (image));
778
779
  
  if (gdk_image)
Manish Singh's avatar
Manish Singh committed
780
    g_object_ref (gdk_image);
781
782

  if (mask)
Manish Singh's avatar
Manish Singh committed
783
    g_object_ref (mask);
Elliot Lee's avatar
Elliot Lee committed
784

785
  gtk_image_reset (image);
Elliot Lee's avatar
Elliot Lee committed
786

787
  if (gdk_image)
Elliot Lee's avatar
Elliot Lee committed
788
    {
789
790
791
      image->storage_type = GTK_IMAGE_IMAGE;

      image->data.image.image = gdk_image;
Havoc Pennington's avatar
Havoc Pennington committed
792
      image->mask = mask;
793
794

      gtk_image_update_size (image, gdk_image->width, gdk_image->height);
Elliot Lee's avatar
Elliot Lee committed
795
796
797
    }
  else
    {
798
799
      /* Clean up the mask if gdk_image was NULL */
      if (mask)
Manish Singh's avatar
Manish Singh committed
800
        g_object_unref (mask);
Elliot Lee's avatar
Elliot Lee committed
801
    }
Havoc Pennington's avatar
Havoc Pennington committed
802
803
804
805
806

  g_object_notify (G_OBJECT (image), "image");
  g_object_notify (G_OBJECT (image), "mask");
  
  g_object_thaw_notify (G_OBJECT (image));
807
}
Elliot Lee's avatar
Elliot Lee committed
808

809
810
811
812
813
814
815
816
/**
 * gtk_image_set_from_file:
 * @image: a #GtkImage
 * @filename: a filename or %NULL
 *
 * See gtk_image_new_from_file() for details.
 * 
 **/
817
818
819
820
void
gtk_image_set_from_file   (GtkImage    *image,
                           const gchar *filename)
{
Havoc Pennington's avatar
Havoc Pennington committed
821
  GdkPixbufAnimation *anim;
822
823
  
  g_return_if_fail (GTK_IS_IMAGE (image));
Havoc Pennington's avatar
Havoc Pennington committed
824
825

  g_object_freeze_notify (G_OBJECT (image));
826
  
827
  gtk_image_reset (image);
828
829

  if (filename == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
830
831
832
833
    {
      g_object_thaw_notify (G_OBJECT (image));
      return;
    }
834
  
Havoc Pennington's avatar
Havoc Pennington committed
835
  anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
836

Havoc Pennington's avatar
Havoc Pennington committed
837
  if (anim == NULL)
838
839
840
841
    {
      gtk_image_set_from_stock (image,
                                GTK_STOCK_MISSING_IMAGE,
                                GTK_ICON_SIZE_BUTTON);
Havoc Pennington's avatar
Havoc Pennington committed
842
      g_object_thaw_notify (G_OBJECT (image));
843
844
      return;
    }
845

Havoc Pennington's avatar
Havoc Pennington committed
846
847
848
849
  /* 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
   */
850

Havoc Pennington's avatar
Havoc Pennington committed
851
852
853
854
855
856
857
858
859
860
  if (gdk_pixbuf_animation_is_static_image (anim))
    {
      gtk_image_set_from_pixbuf (image,
                                 gdk_pixbuf_animation_get_static_image (anim));
    }
  else
    {
      gtk_image_set_from_animation (image, anim);
    }

Manish Singh's avatar
Manish Singh committed
861
  g_object_unref (anim);
Havoc Pennington's avatar
Havoc Pennington committed
862
863

  g_object_thaw_notify (G_OBJECT (image));
864
865
}

866
867
868
869
870
871
872
873
/**
 * gtk_image_set_from_pixbuf:
 * @image: a #GtkImage
 * @pixbuf: a #GdkPixbuf or %NULL
 *
 * See gtk_image_new_from_pixbuf() for details. 
 * 
 **/
874
875
876
877
878
879
880
void
gtk_image_set_from_pixbuf (GtkImage  *image,
                           GdkPixbuf *pixbuf)
{
  g_return_if_fail (GTK_IS_IMAGE (image));
  g_return_if_fail (pixbuf == NULL ||
                    GDK_IS_PIXBUF (pixbuf));
Havoc Pennington's avatar
Havoc Pennington committed
881
882

  g_object_freeze_notify (G_OBJECT (image));
883
884
  
  if (pixbuf)
Manish Singh's avatar
Manish Singh committed
885
    g_object_ref (pixbuf);
886

887
  gtk_image_reset (image);
888
889
890
891
892
893
894
895
896
897
898

  if (pixbuf != NULL)
    {
      image->storage_type = GTK_IMAGE_PIXBUF;

      image->data.pixbuf.pixbuf = pixbuf;

      gtk_image_update_size (image,
                             gdk_pixbuf_get_width (pixbuf),
                             gdk_pixbuf_get_height (pixbuf));
    }
Havoc Pennington's avatar
Havoc Pennington committed
899
900
901
902

  g_object_notify (G_OBJECT (image), "pixbuf");
  
  g_object_thaw_notify (G_OBJECT (image));
903
904
}

905
906
907
908
909
910
/**
 * gtk_image_set_from_stock:
 * @image: a #GtkImage
 * @stock_id: a stock icon name
 * @size: a stock icon size
 *
911
 * See gtk_image_new_from_stock() for details.
912
913
 * 
 **/
914
915
916
void
gtk_image_set_from_stock  (GtkImage       *image,
                           const gchar    *stock_id,
917
                           GtkIconSize     size)
918
{
Havoc Pennington's avatar
Havoc Pennington committed
919
920
  gchar *new_id;
  
921
  g_return_if_fail (GTK_IS_IMAGE (image));
Havoc Pennington's avatar
Havoc Pennington committed
922
923
924
925
926

  g_object_freeze_notify (G_OBJECT (image));

  /* in case stock_id == image->data.stock.stock_id */
  new_id = g_strdup (stock_id);
927
  
928
  gtk_image_reset (image);
929

Havoc Pennington's avatar
Havoc Pennington committed
930
931
  if (new_id)
    {
932
933
      image->storage_type = GTK_IMAGE_STOCK;
      
Havoc Pennington's avatar
Havoc Pennington committed
934
935
      image->data.stock.stock_id = new_id;
      image->icon_size = size;
936
937
938
939
940
941

      /* Size is demand-computed in size request method
       * if we're a stock image, since changing the
       * style impacts the size request
       */
    }
Havoc Pennington's avatar
Havoc Pennington committed
942
943
944
945
946

  g_object_notify (G_OBJECT (image), "stock");
  g_object_notify (G_OBJECT (image), "icon_size");
  
  g_object_thaw_notify (G_OBJECT (image));
947
948
}

949
950
951
952
953
954
955
956
957
/**
 * gtk_image_set_from_icon_set:
 * @image: a #GtkImage
 * @icon_set: a #GtkIconSet
 * @size: a stock icon size
 *
 * See gtk_image_new_from_icon_set() for details.
 * 
 **/
958
959
960
void
gtk_image_set_from_icon_set  (GtkImage       *image,
                              GtkIconSet     *icon_set,
961
                              GtkIconSize     size)
962
963
964
{
  g_return_if_fail (GTK_IS_IMAGE (image));

Havoc Pennington's avatar
Havoc Pennington committed
965
966
  g_object_freeze_notify (G_OBJECT (image));
  
967
968
969
  if (icon_set)
    gtk_icon_set_ref (icon_set);
  
970
  gtk_image_reset (image);
971
972
973
974
975
976

  if (icon_set)
    {      
      image->storage_type = GTK_IMAGE_ICON_SET;
      
      image->data.icon_set.icon_set = icon_set;
Havoc Pennington's avatar
Havoc Pennington committed
977
      image->icon_size = size;
978
979
980
981
982

      /* Size is demand-computed in size request method
       * if we're an icon set
       */
    }
Havoc Pennington's avatar
Havoc Pennington committed
983
984
985
986
987
  
  g_object_notify (G_OBJECT (image), "icon_set");
  g_object_notify (G_OBJECT (image), "icon_size");
  
  g_object_thaw_notify (G_OBJECT (image));
988
989
}

Havoc Pennington's avatar
Havoc Pennington committed
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
/**
 * 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)
{
  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
1005
1006

  g_object_freeze_notify (G_OBJECT (image));
Havoc Pennington's avatar
Havoc Pennington committed
1007
1008
  
  if (animation)
Manish Singh's avatar
Manish Singh committed
1009
    g_object_ref (animation);
Havoc Pennington's avatar
Havoc Pennington committed
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

  gtk_image_reset (image);

  if (animation != NULL)
    {
      image->storage_type = GTK_IMAGE_ANIMATION;

      image->data.anim.anim = animation;
      image->data.anim.frame_timeout = 0;
      image->data.anim.iter = NULL;
      
      gtk_image_update_size (image,
                             gdk_pixbuf_animation_get_width (animation),
                             gdk_pixbuf_animation_get_height (animation));
    }
Havoc Pennington's avatar
Havoc Pennington committed
1025
1026
1027
1028

  g_object_notify (G_OBJECT (image), "pixbuf_animation");
  
  g_object_thaw_notify (G_OBJECT (image));
Havoc Pennington's avatar
Havoc Pennington committed
1029
1030
}

1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
/**
 * gtk_image_set_from_icon_name:
 * @image: a #GtkImage
 * @icon_name: an icon name
 * @size: an icon size
 *
 * 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)
{
  gchar *new_name;
  
  g_return_if_fail (GTK_IS_IMAGE (image));

  g_object_freeze_notify (G_OBJECT (image));

  /* in case stock_id == image->data.stock.stock_id */
  new_name = g_strdup (icon_name);
  
  gtk_image_reset (image);

  if (new_name)
    {
      image->storage_type = GTK_IMAGE_ICON_NAME;
      
      image->data.name.icon_name = new_name;
      image->icon_size = size;

      /* Size is demand-computed in size request method
       * if we're a icon theme image, since changing the
       * style impacts the size request
       */
    }

  g_object_notify (G_OBJECT (image), "icon_name");
  g_object_notify (G_OBJECT (image), "icon_size");
  
  g_object_thaw_notify (G_OBJECT (image));
}

1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
/**
 * 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.
 * 
 * Return value: image representation being used
 **/
1086
1087
1088
1089
1090
1091
1092
1093
GtkImageType
gtk_image_get_storage_type (GtkImage *image)
{
  g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);

  return image->storage_type;
}

1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
/**
 * gtk_image_get_pixmap:
 * @image: a #GtkImage
 * @pixmap: location to store the pixmap, or %NULL
 * @mask: location to store the mask, or %NULL
 *
 * Gets the pixmap and mask being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_PIXMAP (see gtk_image_get_storage_type()).
 * The caller of this function does not own a reference to the
 * returned pixmap and mask.
 * 
 **/
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
void
gtk_image_get_pixmap (GtkImage   *image,
                      GdkPixmap **pixmap,
                      GdkBitmap **mask)
{
  g_return_if_fail (GTK_IS_IMAGE (image)); 
  g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
                    image->storage_type == GTK_IMAGE_EMPTY);
  
  if (pixmap)
    *pixmap = image->data.pixmap.pixmap;
  
  if (mask)
Havoc Pennington's avatar
Havoc Pennington committed
1120
    *mask = image->mask;
1121
1122
}

1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
/**
 * gtk_image_get_image:
 * @image: a #GtkImage
 * @gdk_image: return location for a #GtkImage
 * @mask: return location for a #GdkBitmap
 * 
 * Gets the #GdkImage and mask being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_IMAGE (see gtk_image_get_storage_type()).
 * The caller of this function does not own a reference to the
 * returned image and mask.
 **/
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
void
gtk_image_get_image  (GtkImage   *image,
                      GdkImage  **gdk_image,
                      GdkBitmap **mask)
{
  g_return_if_fail (GTK_IS_IMAGE (image));
  g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
                    image->storage_type == GTK_IMAGE_EMPTY);

  if (gdk_image)
    *gdk_image = image->data.image.image;
  
  if (mask)
Havoc Pennington's avatar
Havoc Pennington committed
1148
    *mask = image->mask;
1149
1150
}

1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
/**
 * 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.
 * 
 * Return value: the displayed pixbuf, or %NULL if the image is empty
 **/
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
GdkPixbuf*
gtk_image_get_pixbuf (GtkImage *image)
{
  g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
  g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
                        image->storage_type == GTK_IMAGE_EMPTY, NULL);

  if (image->storage_type == GTK_IMAGE_EMPTY)
    image->data.pixbuf.pixbuf = NULL;
  
  return image->data.pixbuf.pixbuf;
}

1177
1178
1179
1180
1181
1182
1183
1184
1185
/**
 * gtk_image_get_stock:
 * @image: a #GtkImage
 * @stock_id: place to store a stock icon name
 * @size: place to store a stock icon size
 *
 * 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()).
1186
 * The returned string is owned by the #GtkImage and should not
1187
1188
1189
 * be freed.
 * 
 **/
1190
1191
1192
void
gtk_image_get_stock  (GtkImage        *image,
                      gchar          **stock_id,
1193
                      GtkIconSize     *size)
1194
1195
1196
1197
1198
1199
1200
1201
1202
{
  g_return_if_fail (GTK_IS_IMAGE (image));
  g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
                    image->storage_type == GTK_IMAGE_EMPTY);

  if (image->storage_type == GTK_IMAGE_EMPTY)
    image->data.stock.stock_id = NULL;
  
  if (stock_id)
1203
    *stock_id = image->data.stock.stock_id;
1204
1205

  if (size)
Havoc Pennington's avatar
Havoc Pennington committed
1206
    *size = image->icon_size;
1207
1208
}

1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
/**
 * gtk_image_get_icon_set:
 * @image: a #GtkImage
 * @icon_set: location to store a #GtkIconSet
 * @size: location to store a stock icon size
 *
 * Gets the icon set and size being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_ICON_SET (see gtk_image_get_storage_type()).
 * 
 **/
1220
1221
1222
void
gtk_image_get_icon_set  (GtkImage        *image,
                         GtkIconSet     **icon_set,
1223
                         GtkIconSize     *size)
1224
1225
1226
1227
1228
1229
1230
1231
1232
{
  g_return_if_fail (GTK_IS_IMAGE (image));
  g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
                    image->storage_type == GTK_IMAGE_EMPTY);
      
  if (icon_set)    
    *icon_set = image->data.icon_set.icon_set;

  if (size)
Havoc Pennington's avatar
Havoc Pennington committed
1233
    *size = image->icon_size;
1234
1235
}

Havoc Pennington's avatar
Havoc Pennington committed
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
/**
 * gtk_image_get_animation:
 * @image: a #GtkImage
 *
 *
 * Gets the #GdkPixbufAnimation being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_ANIMATION (see gtk_image_get_storage_type()).
 * The caller of this function does not own a reference to the
 * returned animation.
 * 
 * Return value: the displayed animation, or %NULL if the image is empty
 **/
GdkPixbufAnimation*
gtk_image_get_animation (GtkImage *image)
{
  g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
  g_return_val_if_fail (image->storage_type == GTK_IMAGE_ANIMATION ||
                        image->storage_type == GTK_IMAGE_EMPTY,
                        NULL);

  if (image->storage_type == GTK_IMAGE_EMPTY)
    image->data.anim.anim = NULL;
  
  return image->data.anim.anim;
}

1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
/**
 * gtk_image_get_icon_name:
 * @image: a #GtkImage
 * @icon_name: place to store an icon name
 * @size: place to store an icon size
 *
 * Gets the icon name and size being displayed by the #GtkImage.
 * The storage type of the image must be %GTK_IMAGE_EMPTY or
 * %GTK_IMAGE_ICON_NAME (see gtk_image_get_storage_type()).
 * The returned string is owned by the #GtkImage and should not
 * be freed.
 * 
 * Since: 2.6
 **/
void
gtk_image_get_icon_name  (GtkImage        *image,
			  gchar          **icon_name,
			  GtkIconSize     *size)
{
  g_return_if_fail (GTK_IS_IMAGE (image));
  g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_NAME ||
                    image->storage_type == GTK_IMAGE_EMPTY);

  if (image->storage_type == GTK_IMAGE_EMPTY)
    image->data.name.icon_name = NULL;
  
  if (icon_name)
    *icon_name = image->data.name.icon_name;

  if (size)
    *size = image->icon_size;
}

1296
1297
1298
1299
1300
1301
1302
/**
 * gtk_image_new:
 * 
 * Creates a new empty #GtkImage widget.
 * 
 * Return value: a newly created #GtkImage widget. 
 **/
1303
GtkWidget*
1304
gtk_image_new (void)
1305
{
1306
  return g_object_new (GTK_TYPE_IMAGE, NULL);
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
}

void
gtk_image_set (GtkImage  *image,
	       GdkImage  *val,
	       GdkBitmap *mask)
{
  g_return_if_fail (GTK_IS_IMAGE (image));

  gtk_image_set_from_image (image, val, mask);
Elliot Lee's avatar
Elliot Lee committed
1317
1318
1319
1320
1321
1322
1323
1324
1325
}

void
gtk_image_get (GtkImage   *image,
	       GdkImage  **val,
	       GdkBitmap **mask)
{
  g_return_if_fail (GTK_IS_IMAGE (image));

1326
  gtk_image_get_image (image, val, mask);
Elliot Lee's avatar
Elliot Lee committed
1327
1328
}

Havoc Pennington's avatar
Havoc Pennington committed
1329
static void
1330
gtk_image_reset_anim_iter (GtkImage *image)
Havoc Pennington's avatar
Havoc Pennington committed
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
{
  if (image->storage_type == GTK_IMAGE_ANIMATION)
    {
      /* Reset the animation */
      
      if (image->data.anim.frame_timeout)
        {
          g_source_remove (image->data.anim.frame_timeout);
          image->data.anim.frame_timeout = 0;
        }

      if (image->data.anim.iter)
        {
Manish Singh's avatar
Manish Singh committed
1344
          g_object_unref (image->data.anim.iter);
Havoc Pennington's avatar
Havoc Pennington committed
1345
1346
1347
          image->data.anim.iter = NULL;
        }
    }
1348
1349
}

1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
static void
gtk_image_reset_icon_theme_change_cb (GtkImage *image)
{
  GdkScreen *screen;
  GtkIconTheme *icon_theme;

  if (image->storage_type == GTK_IMAGE_ICON_NAME)
    {
      if (image->data.name.theme_change_id)
	{
	  screen = gtk_widget_get_screen (GTK_WIDGET (image));
	  icon_theme = gtk_icon_theme_get_for_screen (screen);
	  g_signal_handler_disconnect (icon_theme,
				       image->data.name.theme_change_id);
	}
      image->data.name.theme_change_id = 0;
    }
}

1369
1370
1371
1372
static void
gtk_image_unmap (GtkWidget *widget)
{
  gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1373
  gtk_image_reset_icon_theme_change_cb (GTK_IMAGE (widget));
Havoc Pennington's avatar
Havoc Pennington committed
1374
1375
1376
1377
1378

  if (GTK_WIDGET_CLASS (parent_class)->unmap)
    GTK_WIDGET_CLASS (parent_class)->unmap (widget);
}

1379
1380
1381
1382
static void
gtk_image_unrealize (GtkWidget *widget)
{
  gtk_image_reset_anim_iter (GTK_IMAGE (widget));
1383
  gtk_image_reset_icon_theme_change_cb (GTK_IMAGE (widget));
1384
1385
1386
1387
1388

  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
    GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
}

Mark McLoughlin's avatar
Mark McLoughlin committed
1389
static gint
Havoc Pennington's avatar
Havoc Pennington committed
1390
1391
1392
1393
animation_timeout (gpointer data)
{
  GtkImage *image;

1394
1395
  GDK_THREADS_ENTER ();

Havoc Pennington's avatar
Havoc Pennington committed
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
  image = GTK_IMAGE (data);
  
  image->data.anim.frame_timeout = 0;

  gdk_pixbuf_animation_iter_advance (image->data.anim.iter, NULL);

  if (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter) >= 0)
    image->data.anim.frame_timeout =
      g_timeout_add (gdk_pixbuf_animation_iter_get_delay_time (image->data.anim.iter),
                     animation_timeout,
                     image);
  
  gtk_widget_queue_draw (GTK_WIDGET (image));

1410
1411
  GDK_THREADS_LEAVE ();

Havoc Pennington's avatar
Havoc Pennington committed
1412
1413
  return FALSE;
}
Elliot Lee's avatar
Elliot Lee committed
1414

1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
static void
icon_theme_changed (GtkIconTheme *icon_theme,
		    GtkImage     *image)
{
  if (image->data.name.pixbuf)
    g_object_unref (image->data.name.pixbuf);
  image->data.name.pixbuf = NULL;

  gtk_widget_queue_draw (GTK_WIDGET (image));
}

static void
ensure_pixbuf_for_icon_name (GtkImage *image)
{
  GtkImagePrivate *priv;
  GdkScreen *screen;
  GtkIconTheme *icon_theme;
  GtkSettings *settings;
  gint width, height;
  gint *sizes, *s, dist;
  GError *error = NULL;

  g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_NAME);

  priv = GTK_IMAGE_GET_PRIVATE (image);
  screen = gtk_widget_get_screen (GTK_WIDGET (image));
  icon_theme = gtk_icon_theme_get_for_screen (screen);
  settings = gtk_settings_get_for_screen (screen);
  if (image->data.name.pixbuf == NULL)
    {
      if (priv->pixel_size != -1)
	{
	  width = height = priv->pixel_size;
	}
      else if (!gtk_icon_size_lookup_for_settings (settings,
						   image->icon_size,
						   &width, &height))
	{
	  if (image->icon_size == -1)
	    {
	      /* Find an available size close to 48 */
	      sizes = gtk_icon_theme_get_icon_sizes (icon_theme, image->data.name.icon_name);
	      dist = 100;
	      width = height = 48;
	      for (s = sizes; *s; s++)
		{
		  if (*s == -1)
		    {
		      width = height = 48;
		      break;
		    }
		  if (*s < 48)
		    {
		      if (48 - *s < dist)
			{
			  width = height = *s;
			  dist = 48 - *s;
			}
		    }
		  else
		    {
		      if (*s - 48 < dist)
			{
			  width = height = *s;
			  dist = *s - 48;
			}
		    }
		}
	      g_free (sizes);
	    }
	  else
	    {
	      g_warning ("Invalid icon size %d\n", image->icon_size);
	      width = height = 24;
	    }
	}
      image->data.name.pixbuf =
	gtk_icon_theme_load_icon (icon_theme,
				  image->data.name.icon_name,
				  MIN (width, height), 0, &error);
      if (image->data.name.pixbuf == NULL)
	{
	  g_error_free (error);
	  image->data.name.pixbuf =
	    gtk_widget_render_icon (GTK_WIDGET (image),
				    GTK_STOCK_MISSING_IMAGE,
				    image->icon_size,
				    NULL);
	}
    }
}

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
/*
 * Like gdk_rectangle_intersect (dest, src, dest), but make 
 * sure that the origin of dest is moved by an "even" offset. 
 * If necessary grow the intersection by one row or column 
 * to achieve this.
 *
 * This is necessary since we can't pass alignment information
 * for the pixelation pattern down to gdk_pixbuf_saturate_and_pixelate(), 
 * thus we have to makesure that the subimages are properly aligned.
 */
static gboolean
rectangle_intersect_even (GdkRectangle *src, 
			  GdkRectangle *dest)
{
  gboolean isect;
  gint x, y;

  x = dest->x;
  y = dest->y;
  isect = gdk_rectangle_intersect (dest, src, dest);

  if ((dest->x - x + dest->y - y) % 2 != 0)
    {
      if (dest->x > x)
	{
	  dest->x--;
	  dest->width++;
	}
      else
	{
	  dest->y--;
	  dest->height++;
	}
    }
  
  return isect;
}

Elliot Lee's avatar
Elliot Lee committed
1545
1546
1547
1548
1549
1550
static gint
gtk_image_expose (GtkWidget      *widget,
		  GdkEventExpose *event)
{
  g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
  g_return_val_if_fail (event != NULL, FALSE);
1551
  
1552
  if (GTK_WIDGET_MAPPED (widget) &&
1553
      GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
Elliot Lee's avatar
Elliot Lee committed
1554
    {
1555
1556
      GtkImage *image;
      GtkMisc *misc;
1557
      GdkRectangle area, image_bound;
1558
      gfloat xalign;
1559
      gint x, y, mask_x, mask_y;
1560
1561
1562
      GdkBitmap *mask;
      GdkPixbuf *pixbuf;
      gboolean needs_state_transform;
1563
1564
      GdkScreen *screen;
      GtkIconTheme *icon_theme;
1565
      
Elliot Lee's avatar
Elliot Lee committed
1566
1567
1568
      image = GTK_IMAGE (widget);
      misc = GTK_MISC (widget);

1569
      area = event->area;
1570
1571
1572
1573
1574
1575
1576
1577

      /* For stock items and icon sets, we lazily calculate
       * the size; we might get here between a queue_resize()
       * and size_request() if something explicitely forces
       * a redraw.
       */
      if (widget->requisition.width == 0 && widget->requisition.height == 0)
	gtk_image_calc_size (image);
1578
1579
1580
1581
      
      if (!gdk_rectangle_intersect (&area, &widget->allocation, &area))
	return FALSE;

1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
	xalign = misc->xalign;
      else
	xalign = 1.0 - misc->xalign;
  
      x = floor (widget->allocation.x + misc->xpad
		 + ((widget->allocation.width - widget->requisition.width) * xalign)
		 + 0.5);
      y = floor (widget->allocation.y + misc->ypad 
		 + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
		 + 0.5);