1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gtkcontainer.h"
29 #include "gtkiconfactory.h"
31 static void gtk_image_class_init (GtkImageClass *klass);
32 static void gtk_image_init (GtkImage *image);
33 static gint gtk_image_expose (GtkWidget *widget,
34 GdkEventExpose *event);
35 static void gtk_image_size_request (GtkWidget *widget,
36 GtkRequisition *requisition);
37 static void gtk_image_clear (GtkImage *image);
38 static void gtk_image_update_size (GtkImage *image,
42 static gpointer parent_class;
45 gtk_image_get_type (void)
47 static GtkType image_type = 0;
51 static const GtkTypeInfo image_info =
55 sizeof (GtkImageClass),
56 (GtkClassInitFunc) gtk_image_class_init,
57 (GtkObjectInitFunc) gtk_image_init,
58 /* reserved_1 */ NULL,
59 /* reserved_2 */ NULL,
60 (GtkClassInitFunc) NULL,
63 image_type = gtk_type_unique (GTK_TYPE_MISC, &image_info);
70 gtk_image_class_init (GtkImageClass *class)
72 GtkWidgetClass *widget_class;
74 parent_class = g_type_class_peek_parent (class);
76 widget_class = (GtkWidgetClass*) class;
78 widget_class->expose_event = gtk_image_expose;
79 widget_class->size_request = gtk_image_size_request;
83 gtk_image_init (GtkImage *image)
85 GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
87 image->storage_type = GTK_IMAGE_EMPTY;
91 gtk_image_new_from_pixmap (GdkPixmap *pixmap,
96 image = gtk_type_new (GTK_TYPE_IMAGE);
98 gtk_image_set_from_pixmap (image, pixmap, mask);
100 return GTK_WIDGET (image);
104 gtk_image_new_from_image (GdkImage *gdk_image,
109 image = gtk_type_new (GTK_TYPE_IMAGE);
111 gtk_image_set_from_image (image, gdk_image, mask);
113 return GTK_WIDGET (image);
117 gtk_image_new_from_file (const gchar *filename)
121 image = gtk_type_new (GTK_TYPE_IMAGE);
123 gtk_image_set_from_file (image, filename);
125 return GTK_WIDGET (image);
129 gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf)
133 image = gtk_type_new (GTK_TYPE_IMAGE);
135 gtk_image_set_from_pixbuf (image, pixbuf);
137 return GTK_WIDGET (image);
141 gtk_image_new_from_stock (const gchar *stock_id,
146 image = gtk_type_new (GTK_TYPE_IMAGE);
148 gtk_image_set_from_stock (image, stock_id, size);
150 return GTK_WIDGET (image);
154 gtk_image_new_from_icon_set (GtkIconSet *icon_set,
159 image = gtk_type_new (GTK_TYPE_IMAGE);
161 gtk_image_set_from_icon_set (image, icon_set, size);
163 return GTK_WIDGET (image);
167 gtk_image_set_from_pixmap (GtkImage *image,
171 g_return_if_fail (GTK_IS_IMAGE (image));
172 g_return_if_fail (pixmap == NULL ||
173 GDK_IS_PIXMAP (pixmap));
174 g_return_if_fail (mask == NULL ||
175 GDK_IS_PIXMAP (mask));
178 g_object_ref (G_OBJECT (pixmap));
181 g_object_ref (G_OBJECT (mask));
183 gtk_image_clear (image);
190 image->storage_type = GTK_IMAGE_PIXMAP;
192 image->data.pixmap.pixmap = pixmap;
193 image->data.pixmap.mask = mask;
195 gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
197 gtk_image_update_size (image, width, height);
201 /* Clean up the mask if pixmap was NULL */
203 g_object_unref (G_OBJECT (mask));
208 gtk_image_set_from_image (GtkImage *image,
212 g_return_if_fail (GTK_IS_IMAGE (image));
213 g_return_if_fail (gdk_image == NULL ||
214 GDK_IS_IMAGE (gdk_image));
215 g_return_if_fail (mask == NULL ||
216 GDK_IS_PIXMAP (mask));
220 g_object_ref (G_OBJECT (gdk_image));
223 g_object_ref (G_OBJECT (mask));
225 gtk_image_clear (image);
229 image->storage_type = GTK_IMAGE_IMAGE;
231 image->data.image.image = gdk_image;
232 image->data.image.mask = mask;
234 gtk_image_update_size (image, gdk_image->width, gdk_image->height);
238 /* Clean up the mask if gdk_image was NULL */
240 g_object_unref (G_OBJECT (mask));
245 gtk_image_set_from_file (GtkImage *image,
246 const gchar *filename)
250 g_return_if_fail (GTK_IS_IMAGE (image));
251 g_return_if_fail (filename != NULL);
253 gtk_image_clear (image);
255 if (filename == NULL)
258 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
263 gtk_image_set_from_pixbuf (image, pixbuf);
265 g_object_unref (G_OBJECT (pixbuf));
269 gtk_image_set_from_pixbuf (GtkImage *image,
272 g_return_if_fail (GTK_IS_IMAGE (image));
273 g_return_if_fail (pixbuf == NULL ||
274 GDK_IS_PIXBUF (pixbuf));
277 g_object_ref (G_OBJECT (pixbuf));
279 gtk_image_clear (image);
283 image->storage_type = GTK_IMAGE_PIXBUF;
285 image->data.pixbuf.pixbuf = pixbuf;
287 gtk_image_update_size (image,
288 gdk_pixbuf_get_width (pixbuf),
289 gdk_pixbuf_get_height (pixbuf));
294 gtk_image_set_from_stock (GtkImage *image,
295 const gchar *stock_id,
298 g_return_if_fail (GTK_IS_IMAGE (image));
300 gtk_image_clear (image);
304 image->storage_type = GTK_IMAGE_STOCK;
306 image->data.stock.stock_id = g_strdup (stock_id);
307 image->data.stock.size = g_strdup (size);
309 /* Size is demand-computed in size request method
310 * if we're a stock image, since changing the
311 * style impacts the size request
317 gtk_image_set_from_icon_set (GtkImage *image,
318 GtkIconSet *icon_set,
321 g_return_if_fail (GTK_IS_IMAGE (image));
324 gtk_icon_set_ref (icon_set);
326 gtk_image_clear (image);
330 image->storage_type = GTK_IMAGE_ICON_SET;
332 image->data.icon_set.icon_set = icon_set;
333 image->data.icon_set.size = g_strdup (size);
335 /* Size is demand-computed in size request method
336 * if we're an icon set
342 gtk_image_get_storage_type (GtkImage *image)
344 g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY);
346 return image->storage_type;
350 gtk_image_get_pixmap (GtkImage *image,
354 g_return_if_fail (GTK_IS_IMAGE (image));
355 g_return_if_fail (image->storage_type == GTK_IMAGE_PIXMAP ||
356 image->storage_type == GTK_IMAGE_EMPTY);
359 *pixmap = image->data.pixmap.pixmap;
362 *mask = image->data.pixmap.mask;
366 gtk_image_get_image (GtkImage *image,
367 GdkImage **gdk_image,
370 g_return_if_fail (GTK_IS_IMAGE (image));
371 g_return_if_fail (image->storage_type == GTK_IMAGE_IMAGE ||
372 image->storage_type == GTK_IMAGE_EMPTY);
375 *gdk_image = image->data.image.image;
378 *mask = image->data.image.mask;
382 gtk_image_get_pixbuf (GtkImage *image)
384 g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
385 g_return_val_if_fail (image->storage_type == GTK_IMAGE_PIXBUF ||
386 image->storage_type == GTK_IMAGE_EMPTY, NULL);
388 if (image->storage_type == GTK_IMAGE_EMPTY)
389 image->data.pixbuf.pixbuf = NULL;
391 return image->data.pixbuf.pixbuf;
395 gtk_image_get_stock (GtkImage *image,
399 g_return_if_fail (GTK_IS_IMAGE (image));
400 g_return_if_fail (image->storage_type == GTK_IMAGE_STOCK ||
401 image->storage_type == GTK_IMAGE_EMPTY);
403 if (image->storage_type == GTK_IMAGE_EMPTY)
404 image->data.stock.stock_id = NULL;
407 *stock_id = g_strdup (image->data.stock.stock_id);
410 *size = image->data.stock.size;
414 gtk_image_get_icon_set (GtkImage *image,
415 GtkIconSet **icon_set,
418 g_return_if_fail (GTK_IS_IMAGE (image));
419 g_return_if_fail (image->storage_type == GTK_IMAGE_ICON_SET ||
420 image->storage_type == GTK_IMAGE_EMPTY);
423 *icon_set = image->data.icon_set.icon_set;
426 *size = g_strdup (image->data.icon_set.size);
430 gtk_image_new (GdkImage *val,
435 g_return_val_if_fail (val != NULL, NULL);
437 image = gtk_type_new (GTK_TYPE_IMAGE);
439 gtk_image_set (image, val, mask);
441 return GTK_WIDGET (image);
445 gtk_image_set (GtkImage *image,
449 g_return_if_fail (GTK_IS_IMAGE (image));
451 gtk_image_set_from_image (image, val, mask);
455 gtk_image_get (GtkImage *image,
459 g_return_if_fail (GTK_IS_IMAGE (image));
461 gtk_image_get_image (image, val, mask);
466 gtk_image_expose (GtkWidget *widget,
467 GdkEventExpose *event)
469 g_return_val_if_fail (widget != NULL, FALSE);
470 g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
471 g_return_val_if_fail (event != NULL, FALSE);
473 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
474 GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY)
478 GdkRectangle area, image_bound, intersection;
480 GdkBitmap *mask = NULL;
481 GdkPixbuf *stock_pixbuf = NULL;
483 image = GTK_IMAGE (widget);
484 misc = GTK_MISC (widget);
486 x = (widget->allocation.x * (1.0 - misc->xalign) +
487 (widget->allocation.x + widget->allocation.width
488 - (widget->requisition.width - misc->xpad * 2)) *
490 y = (widget->allocation.y * (1.0 - misc->yalign) +
491 (widget->allocation.y + widget->allocation.height
492 - (widget->requisition.height - misc->ypad * 2)) *
498 switch (image->storage_type)
500 case GTK_IMAGE_PIXMAP:
501 mask = image->data.pixmap.mask;
502 gdk_drawable_get_size (image->data.pixmap.pixmap,
504 &image_bound.height);
507 case GTK_IMAGE_IMAGE:
508 mask = image->data.image.mask;
509 image_bound.width = image->data.image.image->width;
510 image_bound.height = image->data.image.image->height;
513 case GTK_IMAGE_PIXBUF:
514 image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf);
515 image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf);
518 case GTK_IMAGE_STOCK:
519 stock_pixbuf = gtk_widget_render_stock_icon (widget,
520 image->data.stock.stock_id,
521 image->data.stock.size,
525 image_bound.width = gdk_pixbuf_get_width (stock_pixbuf);
526 image_bound.height = gdk_pixbuf_get_height (stock_pixbuf);
530 case GTK_IMAGE_ICON_SET:
532 gtk_icon_set_render_icon (image->data.icon_set.icon_set,
534 gtk_widget_get_direction (widget),
535 GTK_WIDGET_STATE (widget),
536 image->data.icon_set.size,
542 image_bound.width = gdk_pixbuf_get_width (stock_pixbuf);
543 image_bound.height = gdk_pixbuf_get_height (stock_pixbuf);
553 gdk_gc_set_clip_mask (widget->style->black_gc, mask);
554 gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
559 if (gdk_rectangle_intersect (&image_bound, &area, &intersection))
562 switch (image->storage_type)
564 case GTK_IMAGE_PIXMAP:
565 gdk_draw_drawable (widget->window,
566 widget->style->black_gc,
567 image->data.pixmap.pixmap,
568 image_bound.x - x, image_bound.y - y,
569 image_bound.x, image_bound.y,
570 image_bound.width, image_bound.height);
573 case GTK_IMAGE_IMAGE:
574 gdk_draw_image (widget->window,
575 widget->style->black_gc,
576 image->data.image.image,
577 image_bound.x - x, image_bound.y - y,
578 image_bound.x, image_bound.y,
579 image_bound.width, image_bound.height);
582 case GTK_IMAGE_PIXBUF:
583 gdk_pixbuf_render_to_drawable_alpha (image->data.pixbuf.pixbuf,
591 GDK_PIXBUF_ALPHA_FULL,
593 GDK_RGB_DITHER_NORMAL,
597 case GTK_IMAGE_STOCK: /* fall thru */
598 case GTK_IMAGE_ICON_SET:
601 gdk_pixbuf_render_to_drawable_alpha (stock_pixbuf,
609 GDK_PIXBUF_ALPHA_FULL,
611 GDK_RGB_DITHER_NORMAL,
614 g_object_unref (G_OBJECT (stock_pixbuf));
621 } /* if rectangle intersects */
624 gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
625 gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
627 } /* if widget is drawable */
633 gtk_image_clear (GtkImage *image)
635 switch (image->storage_type)
637 case GTK_IMAGE_PIXMAP:
639 if (image->data.pixmap.pixmap)
640 g_object_unref (G_OBJECT (image->data.pixmap.pixmap));
642 if (image->data.pixmap.mask)
643 g_object_unref (G_OBJECT (image->data.pixmap.mask));
645 image->data.pixmap.pixmap = NULL;
646 image->data.pixmap.mask = NULL;
650 case GTK_IMAGE_IMAGE:
652 if (image->data.image.image)
653 g_object_unref (G_OBJECT (image->data.image.image));
655 if (image->data.image.mask)
656 g_object_unref (G_OBJECT (image->data.image.mask));
658 image->data.image.image = NULL;
659 image->data.image.mask = NULL;
663 case GTK_IMAGE_PIXBUF:
665 if (image->data.pixbuf.pixbuf)
666 g_object_unref (G_OBJECT (image->data.pixbuf.pixbuf));
668 image->data.pixbuf.pixbuf = NULL;
672 case GTK_IMAGE_STOCK:
674 g_free (image->data.stock.size);
675 g_free (image->data.stock.stock_id);
677 image->data.stock.stock_id = NULL;
678 image->data.stock.size = NULL;
682 case GTK_IMAGE_ICON_SET:
683 if (image->data.icon_set.icon_set)
684 gtk_icon_set_unref (image->data.icon_set.icon_set);
686 g_free (image->data.icon_set.size);
688 image->data.icon_set.size = NULL;
689 image->data.icon_set.icon_set = NULL;
693 case GTK_IMAGE_EMPTY:
699 image->storage_type = GTK_IMAGE_EMPTY;
701 GTK_WIDGET (image)->requisition.width = 0;
702 GTK_WIDGET (image)->requisition.height = 0;
704 if (GTK_WIDGET_VISIBLE (image))
705 gtk_widget_queue_resize (GTK_WIDGET (image));
709 gtk_image_size_request (GtkWidget *widget,
710 GtkRequisition *requisition)
713 GdkPixbuf *pixbuf = NULL;
715 image = GTK_IMAGE (widget);
717 switch (image->storage_type)
719 case GTK_IMAGE_STOCK:
720 pixbuf = gtk_widget_render_stock_icon (GTK_WIDGET (image),
721 image->data.stock.stock_id,
722 image->data.stock.size,
726 case GTK_IMAGE_ICON_SET:
727 pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set,
729 gtk_widget_get_direction (widget),
730 GTK_WIDGET_STATE (widget),
731 image->data.icon_set.size,
742 gtk_image_update_size (image,
743 gdk_pixbuf_get_width (pixbuf),
744 gdk_pixbuf_get_height (pixbuf));
745 g_object_unref (G_OBJECT (pixbuf));
748 /* Chain up to default that simply reads current requisition */
749 GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
753 gtk_image_update_size (GtkImage *image,
757 GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2;
758 GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2;