diff options
author | Havoc Pennington <hp@redhat.com> | 2000-09-26 20:22:17 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2000-09-26 20:22:17 +0000 |
commit | e8597130f58f6808cdfa1bac7058da7f33a9f600 (patch) | |
tree | 147da1d69e7b52f2139600d9609eb58a1253965d /gtk/gtkimage.c | |
parent | 9bec105a6606f11fb1e85e5f378d39595da0c165 (diff) | |
download | gtk+-e8597130f58f6808cdfa1bac7058da7f33a9f600.tar.gz |
Move more text widget headers into the private header list
2000-09-26 Havoc Pennington <hp@redhat.com>
* gtk/Makefile.am (gtk_private_h_sources): Move more text widget
headers into the private header list
* Makefile.am (pkgconfig_DATA): install pkg-config files
* configure.in: add pkg-config files
* gdk-2.0.pc.in, gdk-pixbuf.pc.in, gtk+-2.0.pc.in: pkg-config files
* gtk/gtkwindow.c (gtk_window_read_rcfiles): Invalidate
outstanding icon caches on theme change.
* gtk/gtkiconfactory.h, gtk/gtkiconfactory.c: New icon system. Three
important types:
(GtkIconSource): Specification for creating a pixbuf
appropriate for a direction/state/size triplet from
a source pixbuf or filename
(GtkIconSet): List of GtkIconSource objects that are used to
create the "same" icon (e.g. an OK button icon), and cache for
rendered icons
(GtkIconFactory): Hash from stock ID to GtkIconSet; used to look
up the icon set for a given stock ID. GTK maintains a stack of
GtkIconFactory to search, and applications or libraries can add
additional icon factories on top of the stack
* gtk/gtkrc.h, gtk/gtkrc.c: When loading an RcStyle, parse
the set of GtkIconSource specified for a given stock ID into
a GtkIconSet, and put the GtkIconSet into a GtkIconFactory for the
RcStyle, under the specified stock ID.
* gtk/gtkstyle.h, gtk/gtkstyle.c: Add a virtual function
render_icon used to derive a GdkPixbuf from a GtkIconSource.
This allows people to theme how prelight, insensitive, etc. are
done.
(gtk_style_lookup_icon_set): Look up a stock ID in the list of
icon factories for a style, and return the resulting
icon set if any.
(gtk_style_render_icon): Render an icon using the render_icon
method in the GtkStyleClass.
* gtk/gtkwidget.h, gtk/gtkwidget.c (gtk_widget_render_icon):
Use the style for a given widget to look up a stock ID, get the
icon set, and render an icon using the render_icon method
of the style
* gtk/gtkstock.h, gtk/gtkstock.c: Header with the GtkStockItem type
(contains information about a stock item), the built-in stock item
IDs, and functions to add/lookup stock items.
* gtk/stock-icons/*: Stock icons that come with GTK
* gtk/gtkbutton.h, gtk/gtkbutton.c (gtk_button_new_stock): Returns
a button based on a GtkStockItem
(gtk_button_new_accel): Takes a uline string and accel group, and
installs the accelerator.
* gtk/gtkimage.h, gtk/gtkimage.c: Make this into a generic
image-display widget.
Diffstat (limited to 'gtk/gtkimage.c')
-rw-r--r-- | gtk/gtkimage.c | 663 |
1 files changed, 612 insertions, 51 deletions
diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 01154d9293..504b2a2e11 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -26,13 +26,20 @@ #include "gtkcontainer.h" #include "gtkimage.h" +#include "gtkiconfactory.h" +static void gtk_image_class_init (GtkImageClass *klass); +static void gtk_image_init (GtkImage *image); +static gint gtk_image_expose (GtkWidget *widget, + GdkEventExpose *event); +static void gtk_image_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_image_clear (GtkImage *image); +static void gtk_image_update_size (GtkImage *image, + gint image_width, + gint image_height); -static void gtk_image_class_init (GtkImageClass *klass); -static void gtk_image_init (GtkImage *image); -static gint gtk_image_expose (GtkWidget *widget, - GdkEventExpose *event); - +static gpointer parent_class; GtkType gtk_image_get_type (void) @@ -64,9 +71,12 @@ gtk_image_class_init (GtkImageClass *class) { GtkWidgetClass *widget_class; + parent_class = g_type_class_peek_parent (class); + widget_class = (GtkWidgetClass*) class; widget_class->expose_event = gtk_image_expose; + widget_class->size_request = gtk_image_size_request; } static void @@ -74,49 +84,371 @@ gtk_image_init (GtkImage *image) { GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW); - image->image = NULL; - image->mask = NULL; + image->storage_type = GTK_IMAGE_EMPTY; } GtkWidget* -gtk_image_new (GdkImage *val, - GdkBitmap *mask) +gtk_image_new_from_pixmap (GdkPixmap *pixmap, + GdkBitmap *mask) { GtkImage *image; - g_return_val_if_fail (val != NULL, NULL); + image = gtk_type_new (GTK_TYPE_IMAGE); + + gtk_image_set_from_pixmap (image, pixmap, mask); + + return GTK_WIDGET (image); +} + +GtkWidget* +gtk_image_new_from_image (GdkImage *gdk_image, + GdkBitmap *mask) +{ + GtkImage *image; image = gtk_type_new (GTK_TYPE_IMAGE); - gtk_image_set (image, val, mask); + gtk_image_set_from_image (image, gdk_image, mask); + + return GTK_WIDGET (image); +} + +GtkWidget* +gtk_image_new_from_file (const gchar *filename) +{ + GtkImage *image; + + image = gtk_type_new (GTK_TYPE_IMAGE); + + gtk_image_set_from_file (image, filename); + + return GTK_WIDGET (image); +} + +GtkWidget* +gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf) +{ + GtkImage *image; + + image = gtk_type_new (GTK_TYPE_IMAGE); + + gtk_image_set_from_pixbuf (image, pixbuf); + + return GTK_WIDGET (image); +} + +GtkWidget* +gtk_image_new_from_stock (const gchar *stock_id, + const gchar *size) +{ + GtkImage *image; + + image = gtk_type_new (GTK_TYPE_IMAGE); + + gtk_image_set_from_stock (image, stock_id, size); + + return GTK_WIDGET (image); +} + +GtkWidget* +gtk_image_new_from_icon_set (GtkIconSet *icon_set, + const gchar *size) +{ + GtkImage *image; + + image = gtk_type_new (GTK_TYPE_IMAGE); + + gtk_image_set_from_icon_set (image, icon_set, size); return GTK_WIDGET (image); } void -gtk_image_set (GtkImage *image, - GdkImage *val, - GdkBitmap *mask) +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)); + + if (pixmap) + g_object_ref (G_OBJECT (pixmap)); + + if (mask) + g_object_ref (G_OBJECT (mask)); + + gtk_image_clear (image); + + if (pixmap) + { + int width; + int height; + + image->storage_type = GTK_IMAGE_PIXMAP; + + image->data.pixmap.pixmap = pixmap; + image->data.pixmap.mask = mask; + + gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height); + + gtk_image_update_size (image, width, height); + } + else + { + /* Clean up the mask if pixmap was NULL */ + if (mask) + g_object_unref (G_OBJECT (mask)); + } +} + +void +gtk_image_set_from_image (GtkImage *image, + GdkImage *gdk_image, + GdkBitmap *mask) { - g_return_if_fail (image != NULL); g_return_if_fail (GTK_IS_IMAGE (image)); + g_return_if_fail (gdk_image == NULL || + GDK_IS_IMAGE (gdk_image)); + g_return_if_fail (mask == NULL || + GDK_IS_PIXMAP (mask)); + + + if (gdk_image) + g_object_ref (G_OBJECT (gdk_image)); + + if (mask) + g_object_ref (G_OBJECT (mask)); - image->image = val; - image->mask = mask; + gtk_image_clear (image); - if (image->image) + if (gdk_image) { - GTK_WIDGET (image)->requisition.width = image->image->width + GTK_MISC (image)->xpad * 2; - GTK_WIDGET (image)->requisition.height = image->image->height + GTK_MISC (image)->ypad * 2; + image->storage_type = GTK_IMAGE_IMAGE; + + image->data.image.image = gdk_image; + image->data.image.mask = mask; + + gtk_image_update_size (image, gdk_image->width, gdk_image->height); } else { - GTK_WIDGET (image)->requisition.width = 0; - GTK_WIDGET (image)->requisition.height = 0; + /* Clean up the mask if gdk_image was NULL */ + if (mask) + g_object_unref (G_OBJECT (mask)); } +} - if (GTK_WIDGET_VISIBLE (image)) - gtk_widget_queue_resize (GTK_WIDGET (image)); +void +gtk_image_set_from_file (GtkImage *image, + const gchar *filename) +{ + GdkPixbuf *pixbuf; + + g_return_if_fail (GTK_IS_IMAGE (image)); + g_return_if_fail (filename != NULL); + + gtk_image_clear (image); + + if (filename == NULL) + return; + + pixbuf = gdk_pixbuf_new_from_file (filename); + + if (pixbuf == NULL) + return; + + gtk_image_set_from_pixbuf (image, pixbuf); + + g_object_unref (G_OBJECT (pixbuf)); +} + +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)); + + if (pixbuf) + g_object_ref (G_OBJECT (pixbuf)); + + gtk_image_clear (image); + + 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)); + } +} + +void +gtk_image_set_from_stock (GtkImage *image, + const gchar *stock_id, + const gchar *size) +{ + g_return_if_fail (GTK_IS_IMAGE (image)); + + gtk_image_clear (image); + + if (stock_id) + { + image->storage_type = GTK_IMAGE_STOCK; + + image->data.stock.stock_id = g_strdup (stock_id); + image->data.stock.size = g_strdup (size); + + /* Size is demand-computed in size request method + * if we're a stock image, since changing the + * style impacts the size request + */ + } +} + +void +gtk_image_set_from_icon_set (GtkImage *image, + GtkIconSet *icon_set, + const gchar *size) +{ + g_return_if_fail (GTK_IS_IMAGE (image)); + + if (icon_set) + gtk_icon_set_ref (icon_set); + + gtk_image_clear (image); + + if (icon_set) + { + image->storage_type = GTK_IMAGE_ICON_SET; + + image->data.icon_set.icon_set = icon_set; + image->data.icon_set.size = g_strdup (size); + + /* Size is demand-computed in size request method + * if we're an icon set + */ + } +} + +GtkImageType +gtk_image_get_storage_type (GtkImage *image) +{ + g_return_val_if_fail (GTK_IS_IMAGE (image), GTK_IMAGE_EMPTY); + + return image->storage_type; +} + +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) + *mask = image->data.pixmap.mask; +} + +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) + *mask = image->data.image.mask; +} + +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; +} + +void +gtk_image_get_stock (GtkImage *image, + gchar **stock_id, + gchar **size) +{ + 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) + *stock_id = g_strdup (image->data.stock.stock_id); + + if (size) + *size = image->data.stock.size; +} + +void +gtk_image_get_icon_set (GtkImage *image, + GtkIconSet **icon_set, + gchar **size) +{ + 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) + *size = g_strdup (image->data.icon_set.size); +} + +GtkWidget* +gtk_image_new (GdkImage *val, + GdkBitmap *mask) +{ + GtkImage *image; + + g_return_val_if_fail (val != NULL, NULL); + + image = gtk_type_new (GTK_TYPE_IMAGE); + + gtk_image_set (image, val, mask); + + return GTK_WIDGET (image); +} + +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); } void @@ -124,13 +456,9 @@ gtk_image_get (GtkImage *image, GdkImage **val, GdkBitmap **mask) { - g_return_if_fail (image != NULL); g_return_if_fail (GTK_IS_IMAGE (image)); - if (val) - *val = image->image; - if (mask) - *mask = image->mask; + gtk_image_get_image (image, val, mask); } @@ -141,13 +469,16 @@ gtk_image_expose (GtkWidget *widget, g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); - - if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget)) + + if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) && + GTK_IMAGE (widget)->storage_type != GTK_IMAGE_EMPTY) { GtkImage *image; GtkMisc *misc; GdkRectangle area, image_bound, intersection; gint x, y; + GdkBitmap *mask = NULL; + GdkPixbuf *stock_pixbuf = NULL; image = GTK_IMAGE (widget); misc = GTK_MISC (widget); @@ -161,35 +492,265 @@ gtk_image_expose (GtkWidget *widget, - (widget->requisition.height - misc->ypad * 2)) * misc->yalign) + 0.5; - if (image->mask) + image_bound.x = x; + image_bound.y = y; + + switch (image->storage_type) + { + case GTK_IMAGE_PIXMAP: + mask = image->data.pixmap.mask; + gdk_drawable_get_size (image->data.pixmap.pixmap, + &image_bound.width, + &image_bound.height); + break; + + case GTK_IMAGE_IMAGE: + mask = image->data.image.mask; + image_bound.width = image->data.image.image->width; + image_bound.height = image->data.image.image->height; + break; + + case GTK_IMAGE_PIXBUF: + image_bound.width = gdk_pixbuf_get_width (image->data.pixbuf.pixbuf); + image_bound.height = gdk_pixbuf_get_height (image->data.pixbuf.pixbuf); + break; + + case GTK_IMAGE_STOCK: + stock_pixbuf = gtk_widget_render_stock_icon (widget, + image->data.stock.stock_id, + image->data.stock.size, + NULL); + + if (stock_pixbuf) + { + image_bound.width = gdk_pixbuf_get_width (stock_pixbuf); + image_bound.height = gdk_pixbuf_get_height (stock_pixbuf); + } + break; + + case GTK_IMAGE_ICON_SET: + stock_pixbuf = + gtk_icon_set_render_icon (image->data.icon_set.icon_set, + widget->style, + gtk_widget_get_direction (widget), + GTK_WIDGET_STATE (widget), + image->data.icon_set.size, + widget, + NULL); + + if (stock_pixbuf) + { + image_bound.width = gdk_pixbuf_get_width (stock_pixbuf); + image_bound.height = gdk_pixbuf_get_height (stock_pixbuf); + } + break; + + default: + break; + } + + if (mask) { - gdk_gc_set_clip_mask (widget->style->black_gc, image->mask); + gdk_gc_set_clip_mask (widget->style->black_gc, mask); gdk_gc_set_clip_origin (widget->style->black_gc, x, y); } - image_bound.x = x; - image_bound.y = y; - image_bound.width = image->image->width; - image_bound.height = image->image->height; - area = event->area; - if(gdk_rectangle_intersect(&image_bound, &area, &intersection)) + if (gdk_rectangle_intersect (&image_bound, &area, &intersection)) { - gdk_draw_image (widget->window, - widget->style->black_gc, - image->image, - image_bound.x - x, image_bound.y - y, - image_bound.x, image_bound.y, - image_bound.width, image_bound.height); + + switch (image->storage_type) + { + case GTK_IMAGE_PIXMAP: + gdk_draw_drawable (widget->window, + widget->style->black_gc, + image->data.pixmap.pixmap, + image_bound.x - x, image_bound.y - y, + image_bound.x, image_bound.y, + image_bound.width, image_bound.height); + break; + + case GTK_IMAGE_IMAGE: + gdk_draw_image (widget->window, + widget->style->black_gc, + image->data.image.image, + image_bound.x - x, image_bound.y - y, + image_bound.x, image_bound.y, + image_bound.width, image_bound.height); + break; + + case GTK_IMAGE_PIXBUF: + gdk_pixbuf_render_to_drawable_alpha (image->data.pixbuf.pixbuf, + widget->window, + image_bound.x - x, image_bound.y - y, + image_bound.x, image_bound.y, + image_bound.width, image_bound.height, + GDK_PIXBUF_ALPHA_FULL, + 128, + GDK_RGB_DITHER_NORMAL, + 0, 0); + break; + + case GTK_IMAGE_STOCK: /* fall thru */ + case GTK_IMAGE_ICON_SET: + if (stock_pixbuf) + { + gdk_pixbuf_render_to_drawable_alpha (stock_pixbuf, + widget->window, + image_bound.x - x, image_bound.y - y, + image_bound.x, image_bound.y, + image_bound.width, image_bound.height, + GDK_PIXBUF_ALPHA_FULL, + 128, + GDK_RGB_DITHER_NORMAL, + 0, 0); + + g_object_unref (G_OBJECT (stock_pixbuf)); + } + break; + + default: + break; + } + } /* if rectangle intersects */ + if (mask) + { + gdk_gc_set_clip_mask (widget->style->black_gc, NULL); + gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0); } + } /* if widget is drawable */ + + return FALSE; +} + +static void +gtk_image_clear (GtkImage *image) +{ + switch (image->storage_type) + { + case GTK_IMAGE_PIXMAP: + + if (image->data.pixmap.pixmap) + g_object_unref (G_OBJECT (image->data.pixmap.pixmap)); + + if (image->data.pixmap.mask) + g_object_unref (G_OBJECT (image->data.pixmap.mask)); + + image->data.pixmap.pixmap = NULL; + image->data.pixmap.mask = NULL; + + break; + + case GTK_IMAGE_IMAGE: + + if (image->data.image.image) + g_object_unref (G_OBJECT (image->data.image.image)); + + if (image->data.image.mask) + g_object_unref (G_OBJECT (image->data.image.mask)); + + image->data.image.image = NULL; + image->data.image.mask = NULL; + + break; + + case GTK_IMAGE_PIXBUF: + + if (image->data.pixbuf.pixbuf) + g_object_unref (G_OBJECT (image->data.pixbuf.pixbuf)); + + image->data.pixbuf.pixbuf = NULL; + + break; + + case GTK_IMAGE_STOCK: + + g_free (image->data.stock.size); + g_free (image->data.stock.stock_id); + + image->data.stock.stock_id = NULL; + image->data.stock.size = NULL; + + break; + + case GTK_IMAGE_ICON_SET: + if (image->data.icon_set.icon_set) + gtk_icon_set_unref (image->data.icon_set.icon_set); + + g_free (image->data.icon_set.size); + + image->data.icon_set.size = NULL; + image->data.icon_set.icon_set = NULL; + + break; + + case GTK_IMAGE_EMPTY: + default: + break; - if (image->mask) - { - gdk_gc_set_clip_mask (widget->style->black_gc, NULL); - gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0); - } } - return FALSE; + image->storage_type = GTK_IMAGE_EMPTY; + + GTK_WIDGET (image)->requisition.width = 0; + GTK_WIDGET (image)->requisition.height = 0; + + if (GTK_WIDGET_VISIBLE (image)) + gtk_widget_queue_resize (GTK_WIDGET (image)); +} + +static void +gtk_image_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkImage *image; + GdkPixbuf *pixbuf = NULL; + + image = GTK_IMAGE (widget); + + switch (image->storage_type) + { + case GTK_IMAGE_STOCK: + pixbuf = gtk_widget_render_stock_icon (GTK_WIDGET (image), + image->data.stock.stock_id, + image->data.stock.size, + NULL); + break; + + case GTK_IMAGE_ICON_SET: + pixbuf = gtk_icon_set_render_icon (image->data.icon_set.icon_set, + widget->style, + gtk_widget_get_direction (widget), + GTK_WIDGET_STATE (widget), + image->data.icon_set.size, + widget, + NULL); + break; + + default: + break; + } + + if (pixbuf) + { + gtk_image_update_size (image, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + g_object_unref (G_OBJECT (pixbuf)); + } + + /* Chain up to default that simply reads current requisition */ + GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition); } + +static void +gtk_image_update_size (GtkImage *image, + gint image_width, + gint image_height) +{ + GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2; + GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2; +} + + |