From e8597130f58f6808cdfa1bac7058da7f33a9f600 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 26 Sep 2000 20:22:17 +0000 Subject: [PATCH] Move more text widget headers into the private header list 2000-09-26 Havoc Pennington * 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. --- Makefile.am | 3 + configure.in | 4 + gdk-2.0.pc.in | 12 + gdk-pixbuf.pc.in | 11 + gdk-pixbuf/ChangeLog | 23 +- gdk-pixbuf/Makefile.am | 6 + gdk-pixbuf/gdk-pixbuf-data.c | 174 +++ gdk-pixbuf/gdk-pixbuf-private.h | 10 + gdk-pixbuf/gdk-pixbuf-util.c | 99 ++ gdk-pixbuf/gdk-pixbuf.h | 16 +- gdk-pixbuf/make-inline-pixbuf.c | 213 ++++ gtk+-2.0.pc.in | 12 + gtk/Makefile.am | 16 +- gtk/gtk.h | 2 + gtk/gtkbutton.c | 93 +- gtk/gtkbutton.h | 6 +- gtk/gtkiconfactory.c | 1127 ++++++++++++++++++ gtk/gtkiconfactory.h | 159 +++ gtk/gtkimage.c | 665 ++++++++++- gtk/gtkimage.h | 108 +- gtk/gtkrc.c | 368 +++++- gtk/gtkrc.h | 10 +- gtk/gtkstock.c | 198 +++ gtk/gtkstock.h | 89 ++ gtk/gtkstyle.c | 298 +++-- gtk/gtkstyle.h | 25 +- gtk/gtkwidget.c | 32 + gtk/gtkwidget.h | 5 + gtk/stock-icons/Makefile.am | 23 + gtk/stock-icons/dialog_error.png | Bin 0 -> 2684 bytes gtk/stock-icons/dialog_error_48.png | Bin 0 -> 2684 bytes gtk/stock-icons/dialog_info.png | Bin 0 -> 3504 bytes gtk/stock-icons/dialog_info_48.png | Bin 0 -> 3504 bytes gtk/stock-icons/dialog_question.png | Bin 0 -> 1302 bytes gtk/stock-icons/dialog_question_48.png | Bin 0 -> 1302 bytes gtk/stock-icons/dialog_warning.png | Bin 0 -> 1968 bytes gtk/stock-icons/dialog_warning_48.png | Bin 0 -> 1968 bytes gtk/stock-icons/stock_apply_20.png | Bin 0 -> 452 bytes gtk/stock-icons/stock_button_apply.png | Bin 0 -> 452 bytes gtk/stock-icons/stock_button_apply_24.png | Bin 0 -> 452 bytes gtk/stock-icons/stock_button_cancel.png | Bin 0 -> 454 bytes gtk/stock-icons/stock_button_cancel_24.png | Bin 0 -> 454 bytes gtk/stock-icons/stock_button_close.png | Bin 0 -> 286 bytes gtk/stock-icons/stock_button_close_24.png | Bin 0 -> 286 bytes gtk/stock-icons/stock_button_no.png | Bin 0 -> 847 bytes gtk/stock-icons/stock_button_no_24.png | Bin 0 -> 847 bytes gtk/stock-icons/stock_button_ok.png | Bin 0 -> 661 bytes gtk/stock-icons/stock_button_ok_24.png | Bin 0 -> 661 bytes gtk/stock-icons/stock_button_yes.png | Bin 0 -> 806 bytes gtk/stock-icons/stock_button_yes_24.png | Bin 0 -> 806 bytes gtk/stock-icons/stock_cancel_20.png | Bin 0 -> 454 bytes gtk/stock-icons/stock_close.png | Bin 0 -> 290 bytes gtk/stock-icons/stock_close_20.png | Bin 0 -> 286 bytes gtk/stock-icons/stock_close_24.png | Bin 0 -> 290 bytes gtk/stock-icons/stock_dialog_error_48.png | Bin 0 -> 2684 bytes gtk/stock-icons/stock_dialog_info_48.png | Bin 0 -> 3504 bytes gtk/stock-icons/stock_dialog_question_48.png | Bin 0 -> 1302 bytes gtk/stock-icons/stock_dialog_warning_48.png | Bin 0 -> 1968 bytes gtk/stock-icons/stock_exit.png | Bin 0 -> 413 bytes gtk/stock-icons/stock_exit_24.png | Bin 0 -> 413 bytes gtk/stock-icons/stock_help.png | Bin 0 -> 480 bytes gtk/stock-icons/stock_help_24.png | Bin 0 -> 480 bytes gtk/stock-icons/stock_new.png | Bin 0 -> 771 bytes gtk/stock-icons/stock_new_24.png | Bin 0 -> 771 bytes gtk/stock-icons/stock_no_20.png | Bin 0 -> 847 bytes gtk/stock-icons/stock_ok_20.png | Bin 0 -> 661 bytes gtk/stock-icons/stock_open.png | Bin 0 -> 393 bytes gtk/stock-icons/stock_open_24.png | Bin 0 -> 393 bytes gtk/stock-icons/stock_save.png | Bin 0 -> 849 bytes gtk/stock-icons/stock_save_24.png | Bin 0 -> 849 bytes gtk/stock-icons/stock_yes_20.png | Bin 0 -> 806 bytes 71 files changed, 3662 insertions(+), 145 deletions(-) create mode 100644 gdk-2.0.pc.in create mode 100644 gdk-pixbuf.pc.in create mode 100644 gdk-pixbuf/make-inline-pixbuf.c create mode 100644 gtk+-2.0.pc.in create mode 100644 gtk/gtkiconfactory.c create mode 100644 gtk/gtkiconfactory.h create mode 100644 gtk/gtkstock.c create mode 100644 gtk/gtkstock.h create mode 100644 gtk/stock-icons/Makefile.am create mode 100644 gtk/stock-icons/dialog_error.png create mode 100644 gtk/stock-icons/dialog_error_48.png create mode 100644 gtk/stock-icons/dialog_info.png create mode 100644 gtk/stock-icons/dialog_info_48.png create mode 100644 gtk/stock-icons/dialog_question.png create mode 100644 gtk/stock-icons/dialog_question_48.png create mode 100644 gtk/stock-icons/dialog_warning.png create mode 100644 gtk/stock-icons/dialog_warning_48.png create mode 100644 gtk/stock-icons/stock_apply_20.png create mode 100644 gtk/stock-icons/stock_button_apply.png create mode 100644 gtk/stock-icons/stock_button_apply_24.png create mode 100644 gtk/stock-icons/stock_button_cancel.png create mode 100644 gtk/stock-icons/stock_button_cancel_24.png create mode 100644 gtk/stock-icons/stock_button_close.png create mode 100644 gtk/stock-icons/stock_button_close_24.png create mode 100644 gtk/stock-icons/stock_button_no.png create mode 100644 gtk/stock-icons/stock_button_no_24.png create mode 100644 gtk/stock-icons/stock_button_ok.png create mode 100644 gtk/stock-icons/stock_button_ok_24.png create mode 100644 gtk/stock-icons/stock_button_yes.png create mode 100644 gtk/stock-icons/stock_button_yes_24.png create mode 100644 gtk/stock-icons/stock_cancel_20.png create mode 100644 gtk/stock-icons/stock_close.png create mode 100644 gtk/stock-icons/stock_close_20.png create mode 100644 gtk/stock-icons/stock_close_24.png create mode 100644 gtk/stock-icons/stock_dialog_error_48.png create mode 100644 gtk/stock-icons/stock_dialog_info_48.png create mode 100644 gtk/stock-icons/stock_dialog_question_48.png create mode 100644 gtk/stock-icons/stock_dialog_warning_48.png create mode 100644 gtk/stock-icons/stock_exit.png create mode 100644 gtk/stock-icons/stock_exit_24.png create mode 100644 gtk/stock-icons/stock_help.png create mode 100644 gtk/stock-icons/stock_help_24.png create mode 100644 gtk/stock-icons/stock_new.png create mode 100644 gtk/stock-icons/stock_new_24.png create mode 100644 gtk/stock-icons/stock_no_20.png create mode 100644 gtk/stock-icons/stock_ok_20.png create mode 100644 gtk/stock-icons/stock_open.png create mode 100644 gtk/stock-icons/stock_open_24.png create mode 100644 gtk/stock-icons/stock_save.png create mode 100644 gtk/stock-icons/stock_save_24.png create mode 100644 gtk/stock-icons/stock_yes_20.png diff --git a/Makefile.am b/Makefile.am index fbab5ecd6..0b42c1c0e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -112,6 +112,9 @@ EXTRA_DIST = \ examples/spinbutton/Makefile \ examples/find-examples.sh +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA= gdk-pixbuf.pc gdk-2.0.pc gtk+-2.0.pc + dist-hook: gtk+.spec if test -e $(srcdir)/INSTALL.in && test -e $(srcdir)/README.in ; then \ CONFIG_FILES="INSTALL:$(srcdir)/INSTALL.in README:$(srcdir)/README.in" \ diff --git a/configure.in b/configure.in index d33a4fe30..5b1dca127 100644 --- a/configure.in +++ b/configure.in @@ -1005,6 +1005,9 @@ gtk+.spec docs/gtk-config.1 Makefile gtk-config-2.0 +gdk-pixbuf.pc +gdk-2.0.pc +gtk+-2.0.pc po/Makefile.in build/Makefile build/win32/Makefile @@ -1031,6 +1034,7 @@ gdk/linux-fb/Makefile gtk/Makefile gtk/makefile.mingw gtk/gtkcompat.h +gtk/stock-icons/Makefile modules/Makefile modules/linux-fb/Makefile ], [chmod +x gtk-config-2.0]) diff --git a/gdk-2.0.pc.in b/gdk-2.0.pc.in new file mode 100644 index 000000000..0dc03329c --- /dev/null +++ b/gdk-2.0.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +target=@gdktarget@ + +Name: GDK +Description: GIMP Drawing Kit +Version: @VERSION@ +Requires: gdk-pixbuf,pangox +Libs: -L${libdir} @more_ldflags@ -lgdk-${target}-1.3 @more_libs@ @GDK_WLIBS@ +Cflags: -I${includedir}/gtk-2.0 -I${libdir}/gtk-2.0/include @more_cflags@ diff --git a/gdk-pixbuf.pc.in b/gdk-pixbuf.pc.in new file mode 100644 index 000000000..96afc3d31 --- /dev/null +++ b/gdk-pixbuf.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: GdkPixbuf +Description: Image loading and scaling +Version: @VERSION@ +Requires: gobject-2.0,gmodule-2.0 +Libs: -L${libdir} -lgdk_pixbuf-1.3 @INTLLIBS@ @MATH_LIB@ +Cflags: -I${includedir} diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index e8bb33219..8a85fb836 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,23 @@ +2000-09-26 Havoc Pennington + + * gdk-pixbuf-util.c (gdk_pixbuf_saturate_and_pixelate): Add this + function here, instead of putting it in a private GTK+ file. + + * gdk-pixbuf-private.h (GdkPixbufInlineFormat): include an + enum here for the known formats of inlined pixbufs. + Also, #define our file magic here. + +2000-06-23 Havoc Pennington + + * make-inline-pixbuf.c: Small program that creates C variable + declarations of inline pixbuf data. This can be read + by gdk_pixbuf_new_from_inline. + + * gdk-pixbuf.h (gdk_pixbuf_new_from_inline): New function to read + inline pixbuf data and create a pixbuf from it. + + * gdk-pixbuf-data.c (gdk_pixbuf_new_from_inline): implement here + 2000-09-07 Tor Lillqvist * makefile.mingw.in: Use own version number for gdk-pixbuf DLLs, @@ -27,6 +47,7 @@ * io-wbmp.c: Some bug fixes - now tested to work. 2000-07-27 Elliot Lee + * gdk-pixbuf-io.h, gdk-pixbuf-io.c: Add gdk_pixbuf_get_named_module() function to facilitate above change * io-wbmp.c, pixbufloader_wbmp.defs, gdk-pixbuf-io.c, Makefile: Implement loader for WBMP format. * io-bmp.c: Don't malloc a temporary buffer - use stack instead. @@ -91,7 +112,7 @@ Thu Jul 6 11:49:47 2000 Owen Taylor * Makefile.am (libgdk_pixbuf_la_LDFLAGS): Use GTK+ version soname scheme for gdk-pixbuf. - + 2000-06-21 Havoc Pennington * gdk-pixbuf.c: Convert GdkPixbuf to GObject, leaving it opaque diff --git a/gdk-pixbuf/Makefile.am b/gdk-pixbuf/Makefile.am index 4628de1cc..2247e657e 100644 --- a/gdk-pixbuf/Makefile.am +++ b/gdk-pixbuf/Makefile.am @@ -148,6 +148,12 @@ LDADDS = libgdk_pixbuf-1.3.la $(GLIB_LIBS) $(STATIC_LIB_DEPS) test_gdk_pixbuf_LDADD = $(LDADDS) +bin_PROGRAMS=make-inline-pixbuf + +make_inline_pixbuf_SOURCES=make-inline-pixbuf.c + +make_inline_pixbuf_LDADD = $(LDADDS) + GDK_PIXBUF_LIBS = $(GLIB_LIBS) # diff --git a/gdk-pixbuf/gdk-pixbuf-data.c b/gdk-pixbuf/gdk-pixbuf-data.c index 62634d214..94db20f37 100644 --- a/gdk-pixbuf/gdk-pixbuf-data.c +++ b/gdk-pixbuf/gdk-pixbuf-data.c @@ -23,6 +23,8 @@ #include #include "gdk-pixbuf.h" #include "gdk-pixbuf-private.h" +#include +#include @@ -75,3 +77,175 @@ gdk_pixbuf_new_from_data (const guchar *data, GdkColorspace colorspace, gboolean return pixbuf; } + +static guint32 +read_int (const guchar **p) +{ + guint32 num; + + /* Note most significant bytes are first in the byte stream */ + num = + (*p)[3] | + ((*p)[2] << 8) | + ((*p)[1] << 16) | + ((*p)[0] << 24); + + *p += 4; + + return num; +} + +static gboolean +read_bool (const guchar **p) +{ + gboolean val = **p != 0; + + ++(*p); + + return val; +} + +static GdkPixbuf* +read_raw_inline (const guchar *data, gboolean copy_pixels, int length) +{ + GdkPixbuf *pixbuf; + const guchar *p = data; + guint32 rowstride, width, height, colorspace, + n_channels, bits_per_sample; + gboolean has_alpha; + + if (length >= 0 && length < 12) { + /* Not enough buffer to hold the width/height/rowstride */ + return NULL; + } + + rowstride = read_int (&p); + width = read_int (&p); + height = read_int (&p); + + if (rowstride < width) + return NULL; /* bad data from untrusted source. */ + + /* rowstride >= width, so we can trust width */ + + length -= 12; + + /* There's some better way like G_MAXINT/height > rowstride + * but I'm not sure it works, so stick to this for now. + */ + if (((double)height) * ((double)rowstride) > (double)G_MAXINT) + return NULL; /* overflow */ + + if (length >= 0 && + length < (height * rowstride + 13)) { + /* Not enough buffer to hold the remaining header + * information plus the data. + */ + + return NULL; + } + + /* Read the remaining 13 bytes of header information */ + + has_alpha = read_bool (&p) != FALSE; + colorspace = read_int (&p); + n_channels = read_int (&p); + bits_per_sample = read_int (&p); + + if (colorspace != GDK_COLORSPACE_RGB) + return NULL; + + if (bits_per_sample != 8) + return NULL; + + if (has_alpha && n_channels != 4) + return NULL; + + if (!has_alpha && n_channels != 3) + return NULL; + + if (copy_pixels) { + guchar *pixels; + gint dest_rowstride; + gint row; + + pixbuf = gdk_pixbuf_new (colorspace, + has_alpha, bits_per_sample, + width, height); + + pixels = gdk_pixbuf_get_pixels (pixbuf); + dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + for (row = 0; row < height; row++) { + memcpy (pixels, p, rowstride); + pixels += dest_rowstride; + p += rowstride; + } + } else { + pixbuf = gdk_pixbuf_new_from_data (p, + colorspace, + has_alpha, + bits_per_sample, + width, height, + rowstride, + NULL, NULL); + } + + return pixbuf; +} + +/** + * gdk_pixbuf_new_from_inline: + * @data: An inlined GdkPixbuf + * @copy_pixels: whether to copy the pixels out of the inline data, or to use them in-place + * + * Create a #GdkPixbuf from a custom format invented to store pixbuf + * data in C program code. This library comes with a program called "make-inline-pixbuf" + * that can write out a variable definition containing an inlined pixbuf. + * This is useful if you want to ship a program with images, but + * don't want to depend on any external files. + * + * The inline data format contains the pixels in #GdkPixbuf's native + * format. Since the inline pixbuf is read-only static data, you + * don't need to copy it unless you intend to write to it. + * + * Return value: A newly-created #GdkPixbuf structure with a reference count of + * 1. + **/ +GdkPixbuf* +gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf, + gboolean copy_pixels, + int length) +{ + const guchar *p; + GdkPixbuf *pixbuf; + GdkPixbufInlineFormat format; + + if (length >= 0 && length < 8) { + /* not enough bytes to contain even the magic number + * and format code. + */ + return NULL; + } + + p = inline_pixbuf; + + if (read_int (&p) != GDK_PIXBUF_INLINE_MAGIC_NUMBER) { + return NULL; + } + + format = read_int (&p); + + switch (format) + { + case GDK_PIXBUF_INLINE_RAW: + pixbuf = read_raw_inline (p, copy_pixels, length - 8); + break; + + default: + return NULL; + } + + return pixbuf; +} + diff --git a/gdk-pixbuf/gdk-pixbuf-private.h b/gdk-pixbuf/gdk-pixbuf-private.h index 1b14e3ccc..e8eb7248a 100644 --- a/gdk-pixbuf/gdk-pixbuf-private.h +++ b/gdk-pixbuf/gdk-pixbuf-private.h @@ -117,4 +117,14 @@ struct _GdkPixbufAnimationClass { +#define GDK_PIXBUF_INLINE_MAGIC_NUMBER 0x47646B50 /* 'GdkP' */ + +typedef enum +{ + GDK_PIXBUF_INLINE_RAW = 0, + GDK_PIXBUF_INLINE_RLE = 1 +} GdkPixbufInlineFormat; + + + #endif diff --git a/gdk-pixbuf/gdk-pixbuf-util.c b/gdk-pixbuf/gdk-pixbuf-util.c index 848aadd14..db8ca758e 100644 --- a/gdk-pixbuf/gdk-pixbuf-util.c +++ b/gdk-pixbuf/gdk-pixbuf-util.c @@ -131,3 +131,102 @@ gdk_pixbuf_copy_area (const GdkPixbuf *src_pixbuf, 1.0, 1.0, GDK_INTERP_NEAREST); } + + + +#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) + +/** + * gdk_pixbuf_saturate_and_pixelate: + * @src: source image + * @dest: place to write modified version of @src + * @saturation: saturation factor + * @pixelate: whether to pixelate + * + * Modifies saturation and optionally pixelates @src, placing the + * result in @dest. @src and @dest may be the same pixbuf with no ill + * effects. If @saturation is 1.0 then saturation is not changed. If + * it's less than 1.0, saturation is reduced (the image is darkened); + * if greater than 1.0, saturation is increased (the image is + * brightened). If @pixelate is TRUE, then pixels are faded in a + * checkerboard pattern to create a pixelated image. @src and @dest + * must have the same image format, size, and rowstride. + * + **/ +void +gdk_pixbuf_saturate_and_pixelate(const GdkPixbuf *src, + GdkPixbuf *dest, + gfloat saturation, + gboolean pixelate) +{ + /* NOTE that src and dest MAY be the same pixbuf! */ + + g_return_if_fail (GDK_IS_PIXBUF (src)); + g_return_if_fail (GDK_IS_PIXBUF (dest)); + g_return_if_fail (gdk_pixbuf_get_height (src) == gdk_pixbuf_get_height (dest)); + g_return_if_fail (gdk_pixbuf_get_width (src) == gdk_pixbuf_get_width (dest)); + g_return_if_fail (gdk_pixbuf_get_rowstride (src) == gdk_pixbuf_get_rowstride (dest)); + g_return_if_fail (gdk_pixbuf_get_colorspace (src) == gdk_pixbuf_get_colorspace (dest)); + + if (saturation == 1.0 && !pixelate) { + if (dest != src) + memcpy (gdk_pixbuf_get_pixels (dest), + gdk_pixbuf_get_pixels (src), + gdk_pixbuf_get_height (src) * gdk_pixbuf_get_rowstride (src)); + + return; + } else { + gint i, j; + gint width, height, has_alpha, rowstride; + guchar *target_pixels; + guchar *original_pixels; + guchar *current_pixel; + guchar intensity; + + has_alpha = gdk_pixbuf_get_has_alpha (src); + width = gdk_pixbuf_get_width (src); + height = gdk_pixbuf_get_height (src); + rowstride = gdk_pixbuf_get_rowstride (src); + + target_pixels = gdk_pixbuf_get_pixels (dest); + original_pixels = gdk_pixbuf_get_pixels (src); + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + current_pixel = original_pixels + i*rowstride + j*(has_alpha?4:3); + intensity = INTENSITY (*(current_pixel), *(current_pixel + 1), *(current_pixel + 2)); + if (pixelate && (i+j)%2 == 0) { + *(target_pixels + i*rowstride + j*(has_alpha?4:3)) = intensity/2 + 127; + *(target_pixels + i*rowstride + j*(has_alpha?4:3) + 1) = intensity/2 + 127; + *(target_pixels + i*rowstride + j*(has_alpha?4:3) + 2) = intensity/2 + 127; + } else if (pixelate) { +#define DARK_FACTOR 0.7 + *(target_pixels + i*rowstride + j*(has_alpha?4:3)) = + (guchar) (((1.0 - saturation) * intensity + + saturation * (*(current_pixel)))) * DARK_FACTOR; + *(target_pixels + i*rowstride + j*(has_alpha?4:3) + 1) = + (guchar) (((1.0 - saturation) * intensity + + saturation * (*(current_pixel + 1)))) * DARK_FACTOR; + *(target_pixels + i*rowstride + j*(has_alpha?4:3) + 2) = + (guchar) (((1.0 - saturation) * intensity + + saturation * (*(current_pixel + 2)))) * DARK_FACTOR; + } else { + *(target_pixels + i*rowstride + j*(has_alpha?4:3)) = + (guchar) ((1.0 - saturation) * intensity + + saturation * (*(current_pixel))); + *(target_pixels + i*rowstride + j*(has_alpha?4:3) + 1) = + (guchar) ((1.0 - saturation) * intensity + + saturation * (*(current_pixel + 1))); + *(target_pixels + i*rowstride + j*(has_alpha?4:3) + 2) = + (guchar) ((1.0 - saturation) * intensity + + saturation * (*(current_pixel + 2))); + } + + if (has_alpha) + *(target_pixels + i*rowstride + j*(has_alpha?4:3) + 3) = *(current_pixel + 3); + } + } + + return; + } +} diff --git a/gdk-pixbuf/gdk-pixbuf.h b/gdk-pixbuf/gdk-pixbuf.h index a7074fd50..aaaad7fda 100644 --- a/gdk-pixbuf/gdk-pixbuf.h +++ b/gdk-pixbuf/gdk-pixbuf.h @@ -36,7 +36,10 @@ extern "C" { -/* Color spaces; right now only RGB is supported */ +/* Color spaces; right now only RGB is supported. + * Note that these values are encoded in inline pixbufs + * as ints, so don't reorder them + */ typedef enum { GDK_COLORSPACE_RGB } GdkColorspace; @@ -103,6 +106,11 @@ GdkPixbuf *gdk_pixbuf_new_from_data (const guchar *data, GdkPixbuf *gdk_pixbuf_new_from_xpm_data (const char **data); +/* Read an inline pixbuf */ +GdkPixbuf *gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf, + gboolean copy_pixels, + int length); + /* Adding an alpha channel */ GdkPixbuf *gdk_pixbuf_add_alpha (const GdkPixbuf *pixbuf, gboolean substitute_color, guchar r, guchar g, guchar b); @@ -114,6 +122,12 @@ void gdk_pixbuf_copy_area (const GdkPixbuf *src_pixbuf, GdkPixbuf *dest_pixbuf, int dest_x, int dest_y); +/* Brighten/darken and optionally make it pixelated-looking */ +void gdk_pixbuf_saturate_and_pixelate (const GdkPixbuf *src, + GdkPixbuf *dest, + gfloat saturation, + gboolean pixelate); + /* Rendering to a drawable */ diff --git a/gdk-pixbuf/make-inline-pixbuf.c b/gdk-pixbuf/make-inline-pixbuf.c new file mode 100644 index 000000000..daf0a7e20 --- /dev/null +++ b/gdk-pixbuf/make-inline-pixbuf.c @@ -0,0 +1,213 @@ +/* Program to convert an image file to inline C data + * + * Copyright (C) 2000 Red Hat, Inc. + * + * Developed by Havoc Pennington + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include "gdk-pixbuf-private.h" +#include +#include +#include +#include + +void +output_int (FILE *outfile, guint32 num, const char *comment) +{ + guchar bytes[4]; + + /* Note, most significant bytes first */ + bytes[0] = num >> 24; + bytes[1] = num >> 16; + bytes[2] = num >> 8; + bytes[3] = num; + + fprintf(outfile, " /* %s (%u) */\n 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,\n", + comment, num, + bytes[0], bytes[1], bytes[2], bytes[3]); +} + +void +output_bool (FILE *outfile, gboolean val, const char *comment) +{ + fprintf(outfile, " /* %s (%s) */\n 0x%.2x,\n", + comment, + val ? "TRUE" : "FALSE", + val ? 1 : 0); +} + +void +output_pixbuf (FILE *outfile, gboolean ext_symbols, + const char *varname, + GdkPixbuf *pixbuf) +{ + const char *modifier; + const guchar *p; + const guchar *end; + gboolean has_alpha; + int column; + + modifier = "static "; + if (ext_symbols) + modifier = ""; + + fprintf (outfile, "%sconst guchar ", modifier); + fputs (varname, outfile); + fputs ("[] =\n", outfile); + fputs ("{\n", outfile); + + p = gdk_pixbuf_get_pixels (pixbuf); + end = p + gdk_pixbuf_get_rowstride (pixbuf) * gdk_pixbuf_get_height (pixbuf); + has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); + + /* Sync the order of writing with the order of reading in + * gdk-pixbuf-data.c + */ + output_int (outfile, GDK_PIXBUF_INLINE_MAGIC_NUMBER, "File magic"); + output_int (outfile, GDK_PIXBUF_INLINE_RAW, "Format of following stuff"); + output_int (outfile, gdk_pixbuf_get_rowstride (pixbuf), "Rowstride"); + output_int (outfile, gdk_pixbuf_get_width (pixbuf), "Width"); + output_int (outfile, gdk_pixbuf_get_height (pixbuf), "Height"); + + output_bool (outfile, has_alpha, "Has an alpha channel"); + + output_int (outfile, gdk_pixbuf_get_colorspace (pixbuf), "Colorspace (0 == RGB, no other options implemented)"); + + output_int (outfile, gdk_pixbuf_get_n_channels (pixbuf), "Number of channels"); + + output_int (outfile, gdk_pixbuf_get_bits_per_sample (pixbuf), "Bits per sample"); + + fputs (" /* Image data */\n", outfile); + + /* Copy the data in the pixbuf */ + column = 0; + while (p != end) + { + guchar r, g, b, a; + + r = *p; + ++p; + g = *p; + ++p; + b = *p; + ++p; + if (has_alpha) + { + a = *p; + ++p; + } + else + a = 0; + + + if (has_alpha) + fprintf(outfile, " 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x", r, g, b, a); + else + fprintf(outfile, " 0x%.2x, 0x%.2x, 0x%.2x", r, g, b); + + if (p != end) + fputs (",", outfile); + else + fputs ("\n", outfile); + + ++column; + + if (column > 2) + { + fputs ("\n", outfile); + column = 0; + } + } + + fputs ("};\n\n", outfile); +} + +void +usage (void) +{ + fprintf (stderr, "Usage: make-inline-pixbuf [--extern-symbols] OUTFILE varname1 imagefile1 varname2 imagefile2 ...\n"); + exit (1); +} + +int +main (int argc, char **argv) +{ + gboolean ext_symbols = FALSE; + FILE *outfile; + int i; + + gdk_pixbuf_init (); + + if (argc < 4) + usage (); + + i = 1; + if (strcmp (argv[i], "--extern-symbols") == 0) + { + ext_symbols = TRUE; + ++i; + if (argc < 5) + usage (); + } + + outfile = fopen (argv[i], "w"); + if (outfile == NULL) + { + fprintf (stderr, "Failed to open output file `%s': %s\n", + argv[i], strerror (errno)); + exit (1); + } + + ++i; + + fputs ("/* This file was automatically generated by the make-inline-pixbuf program.\n" + " * It contains inline RGB image data.\n" + " */\n\n", outfile); + + /* Check for matched pairs of images/names */ + if (((argc - i) % 2) != 0) + usage (); + + while (i < argc) + { + GdkPixbuf *pixbuf; + + g_assert ((i + 1) < argc); + + pixbuf = gdk_pixbuf_new_from_file (argv[i+1]); + + if (pixbuf == NULL) + { + fprintf (stderr, "Failed to open image file `%s': %s\n", + argv[i+1], strerror (errno)); + + exit (1); + } + + output_pixbuf (outfile, ext_symbols, argv[i], pixbuf); + + gdk_pixbuf_unref (pixbuf); + + i += 2; + } + + fclose (outfile); + + return 0; +} diff --git a/gtk+-2.0.pc.in b/gtk+-2.0.pc.in new file mode 100644 index 000000000..ddf6c4b62 --- /dev/null +++ b/gtk+-2.0.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +target=@gdktarget@ + +Name: GTK+ +Description: GIMP Tool Kit +Version: @VERSION@ +Requires: gdk-2.0 +Libs: -L${libdir} -lgtk-${target}-1.3 +Cflags: -I${includedir} diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 274ecc36a..173ef56a9 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -1,5 +1,7 @@ ## Makefile.am for gtk+/gtk +SUBDIRS=stock-icons + INCLUDES = @STRIP_BEGIN@ \ -DG_LOG_DOMAIN=\"Gtk\" \ -DGTK_DISABLE_COMPAT_H \ @@ -96,6 +98,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \ gtkhscrollbar.h \ gtkhseparator.h \ gtkhsv.h \ + gtkiconfactory.h \ gtkimage.h \ gtkimcontext.h \ gtkimmulticontext.h \ @@ -141,6 +144,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \ gtkspinbutton.h \ gtkstyle.h \ gtkstatusbar.h \ + gtkstock.h \ gtktable.h \ gtktearoffmenuitem.h \ gtktextbuffer.h \ @@ -178,16 +182,18 @@ gtk_public_h_sources = @STRIP_BEGIN@ \ # interface) gtk_semipublic_h_sources = @STRIP_BEGIN@ \ - gtktextbtree.h \ - gtktextchild.h \ gtktextdisplay.h \ gtktextlayout.h \ - gtktextsegment.h \ - gtktexttypes.h \ @STRIP_END@ # GTK+ header files that don't get installed gtk_private_h_sources = @STRIP_BEGIN@ \ + gtktextbtree.h \ + gtktextchild.h \ + gtktextsegment.h \ + gtktexttypes.h \ + gtktextiterprivate.h \ + gtktextmarkprivate.h \ gtktexttagprivate.h \ @STRIP_END@ @@ -238,6 +244,7 @@ gtk_c_sources = @STRIP_BEGIN@ \ gtkhscrollbar.c \ gtkhseparator.c \ gtkhsv.c \ + gtkiconfactory.c \ gtkimage.c \ gtkimcontext.c \ gtkimcontextsimple.c \ @@ -283,6 +290,7 @@ gtk_c_sources = @STRIP_BEGIN@ \ gtksignal.c \ gtksocket.c \ gtkspinbutton.c \ + gtkstock.c \ gtkstyle.c \ gtkstatusbar.c \ gtktable.c \ diff --git a/gtk/gtk.h b/gtk/gtk.h index 25765fdd3..2e2bd5138 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -75,6 +75,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c index 802873e00..394688496 100644 --- a/gtk/gtkbutton.c +++ b/gtk/gtkbutton.c @@ -29,7 +29,10 @@ #include "gtklabel.h" #include "gtkmain.h" #include "gtksignal.h" - +#include "gtkimage.h" +#include "gtkhbox.h" +#include "gtkstock.h" +#include "gtkiconfactory.h" #define CHILD_SPACING 1 #define DEFAULT_LEFT_POS 4 @@ -45,6 +48,7 @@ enum { LEAVE, LAST_SIGNAL }; + enum { ARG_0, ARG_LABEL, @@ -311,6 +315,93 @@ gtk_button_new_with_label (const gchar *label) return button; } +GtkWidget* +gtk_button_new_stock (const gchar *stock_id, + GtkAccelGroup *accel_group) +{ + GtkWidget *button; + GtkStockItem item; + + if (gtk_stock_lookup (stock_id, &item)) + { + GtkWidget *label; + GtkWidget *image; + GtkWidget *hbox; + guint keyval; + + button = gtk_button_new (); + + label = gtk_label_new (NULL); + keyval = gtk_label_parse_uline (GTK_LABEL (label), + item.label); + + if (keyval && accel_group) + { + gtk_widget_add_accelerator (button, + "clicked", + accel_group, + keyval, + GDK_MOD1_MASK, + GTK_ACCEL_LOCKED); + } + + /* Also add the stock accelerator if one was specified. */ + if (item.keyval && accel_group) + { + gtk_widget_add_accelerator (button, + "clicked", + accel_group, + item.keyval, + item.modifier, + GTK_ACCEL_LOCKED); + } + + image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON); + hbox = gtk_hbox_new (FALSE, 0); + + gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 2); + gtk_box_pack_end (GTK_BOX (hbox), label, TRUE, TRUE, 2); + + gtk_container_add (GTK_CONTAINER (button), hbox); + gtk_widget_show_all (hbox); + } + else + { + button = gtk_button_new_accel (stock_id, accel_group); + } + + return button; +} + +GtkWidget* +gtk_button_new_accel (const gchar *uline_label, + GtkAccelGroup *accel_group) +{ + GtkWidget *button; + GtkWidget *label; + guint keyval; + + button = gtk_button_new (); + + label = gtk_label_new (NULL); + keyval = gtk_label_parse_uline (GTK_LABEL (label), uline_label); + + if (keyval && accel_group) + { + gtk_widget_add_accelerator (button, + "clicked", + accel_group, + keyval, + GDK_MOD1_MASK, + GTK_ACCEL_LOCKED); + } + + gtk_container_add (GTK_CONTAINER (button), label); + gtk_widget_show (label); + + return button; +} + void gtk_button_pressed (GtkButton *button) { diff --git a/gtk/gtkbutton.h b/gtk/gtkbutton.h index a55460e03..0d8c676d0 100644 --- a/gtk/gtkbutton.h +++ b/gtk/gtkbutton.h @@ -75,7 +75,11 @@ struct _GtkButtonClass GtkType gtk_button_get_type (void) G_GNUC_CONST; GtkWidget* gtk_button_new (void); -GtkWidget* gtk_button_new_with_label (const gchar *label); +GtkWidget* gtk_button_new_with_label (const gchar *label); +GtkWidget* gtk_button_new_stock (const gchar *stock_id, + GtkAccelGroup *accel_group); +GtkWidget* gtk_button_new_accel (const gchar *uline_label, + GtkAccelGroup *accel_group); void gtk_button_pressed (GtkButton *button); void gtk_button_released (GtkButton *button); void gtk_button_clicked (GtkButton *button); diff --git a/gtk/gtkiconfactory.c b/gtk/gtkiconfactory.c new file mode 100644 index 000000000..8924df75c --- /dev/null +++ b/gtk/gtkiconfactory.c @@ -0,0 +1,1127 @@ +/* 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 + * modify it under the terms of the GNU Lesser General Public + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * 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/. + */ + +#include "gtkiconfactory.h" +#include "stock-icons/gtkstockpixbufs.h" +#include "gtkstock.h" +#include +#include +#include +#include + +static gpointer parent_class = NULL; + +static void gtk_icon_factory_init (GtkIconFactory *icon_factory); +static void gtk_icon_factory_class_init (GtkIconFactoryClass *klass); +static void gtk_icon_factory_finalize (GObject *object); +static void get_default_icons (GtkIconFactory *icon_factory); + +GType +gtk_icon_factory_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GtkIconFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gtk_icon_factory_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkIconFactory), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_icon_factory_init, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GtkIconFactory", + &object_info); + } + + return object_type; +} + +static void +gtk_icon_factory_init (GtkIconFactory *factory) +{ + factory->icons = g_hash_table_new (g_str_hash, g_str_equal); +} + +static void +gtk_icon_factory_class_init (GtkIconFactoryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gtk_icon_factory_finalize; +} + +static void +free_icon_set (gpointer key, gpointer value, gpointer data) +{ + g_free (key); + gtk_icon_set_unref (value); +} + +static void +gtk_icon_factory_finalize (GObject *object) +{ + GtkIconFactory *factory = GTK_ICON_FACTORY (object); + + g_hash_table_foreach (factory->icons, free_icon_set, NULL); + + g_hash_table_destroy (factory->icons); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +GtkIconFactory* +gtk_icon_factory_new (void) +{ + return GTK_ICON_FACTORY (g_object_new (GTK_TYPE_ICON_FACTORY, NULL)); +} + +void +gtk_icon_factory_add (GtkIconFactory *factory, + const gchar *stock_id, + GtkIconSet *icon_set) +{ + gpointer old_key = NULL; + gpointer old_value = NULL; + + g_return_if_fail (GTK_IS_ICON_FACTORY (factory)); + g_return_if_fail (stock_id != NULL); + g_return_if_fail (icon_set != NULL); + + g_hash_table_lookup_extended (factory->icons, stock_id, + &old_key, &old_value); + + if (old_value == icon_set) + return; + + gtk_icon_set_ref (icon_set); + + /* GHashTable key memory management is so fantastically broken. */ + if (old_key) + g_hash_table_insert (factory->icons, old_key, icon_set); + else + g_hash_table_insert (factory->icons, g_strdup (stock_id), icon_set); + + if (old_value) + gtk_icon_set_unref (old_value); +} + +GtkIconSet * +gtk_icon_factory_lookup (GtkIconFactory *factory, + const gchar *stock_id) +{ + g_return_val_if_fail (GTK_IS_ICON_FACTORY (factory), NULL); + g_return_val_if_fail (stock_id != NULL, NULL); + + return g_hash_table_lookup (factory->icons, stock_id); +} + +static GtkIconFactory *gtk_default_icons = NULL; +static GSList *default_factories = NULL; + +void +gtk_icon_factory_add_default (GtkIconFactory *factory) +{ + g_return_if_fail (GTK_IS_ICON_FACTORY (factory)); + + g_object_ref (G_OBJECT (factory)); + + default_factories = g_slist_prepend (default_factories, factory); +} + +void +gtk_icon_factory_remove_default (GtkIconFactory *factory) +{ + g_return_if_fail (GTK_IS_ICON_FACTORY (factory)); + + default_factories = g_slist_remove (default_factories, factory); + + g_object_unref (G_OBJECT (factory)); +} + +GtkIconSet * +gtk_icon_factory_lookup_default (const gchar *stock_id) +{ + GSList *tmp_list; + + g_return_val_if_fail (stock_id != NULL, NULL); + + tmp_list = default_factories; + while (tmp_list != NULL) + { + GtkIconSet *icon_set = + gtk_icon_factory_lookup (GTK_ICON_FACTORY (tmp_list->data), + stock_id); + + if (icon_set) + return icon_set; + + tmp_list = g_slist_next (tmp_list); + } + + if (gtk_default_icons == NULL) + { + gtk_default_icons = gtk_icon_factory_new (); + + get_default_icons (gtk_default_icons); + } + + return gtk_icon_factory_lookup (gtk_default_icons, stock_id); +} + +static GtkIconSet * +sized_icon_set_from_inline (const guchar *inline_data, + const gchar *size) +{ + GtkIconSet *set; + + GtkIconSource source = { NULL, NULL, 0, 0, NULL, + TRUE, TRUE, FALSE }; + + source.size = size; + + set = gtk_icon_set_new (); + + source.pixbuf = gdk_pixbuf_new_from_inline (inline_data, FALSE, -1); + + g_assert (source.pixbuf); + + gtk_icon_set_add_source (set, &source); + + g_object_unref (G_OBJECT (source.pixbuf)); + + return set; +} + +static GtkIconSet * +unsized_icon_set_from_inline (const guchar *inline_data) +{ + GtkIconSet *set; + + /* This icon can be used for any direction/state/size */ + GtkIconSource source = { NULL, NULL, 0, 0, 0, + TRUE, TRUE, TRUE }; + + set = gtk_icon_set_new (); + + source.pixbuf = gdk_pixbuf_new_from_inline (inline_data, FALSE, -1); + + g_assert (source.pixbuf); + + gtk_icon_set_add_source (set, &source); + + g_object_unref (G_OBJECT (source.pixbuf)); + + return set; +} + +static void +add_sized (GtkIconFactory *factory, + const guchar *inline_data, + const gchar *size, + const gchar *stock_id) +{ + GtkIconSet *set; + + set = sized_icon_set_from_inline (inline_data, size); + + gtk_icon_factory_add (factory, stock_id, set); + + gtk_icon_set_unref (set); +} + +static void +add_unsized (GtkIconFactory *factory, + const guchar *inline_data, + const gchar *stock_id) +{ + GtkIconSet *set; + + set = unsized_icon_set_from_inline (inline_data); + + gtk_icon_factory_add (factory, stock_id, set); + + gtk_icon_set_unref (set); +} + +static void +get_default_icons (GtkIconFactory *factory) +{ + /* KEEP IN SYNC with gtkstock.c */ + + add_sized (factory, dialog_error, GTK_ICON_SIZE_DIALOG, GTK_STOCK_DIALOG_ERROR); + add_sized (factory, dialog_info, GTK_ICON_SIZE_DIALOG, GTK_STOCK_DIALOG_INFO); + add_sized (factory, dialog_question, GTK_ICON_SIZE_DIALOG, GTK_STOCK_DIALOG_QUESTION); + add_sized (factory, dialog_warning, GTK_ICON_SIZE_DIALOG, GTK_STOCK_DIALOG_WARNING); + + add_sized (factory, stock_button_apply, GTK_ICON_SIZE_BUTTON, GTK_STOCK_BUTTON_APPLY); + add_sized (factory, stock_button_ok, GTK_ICON_SIZE_BUTTON, GTK_STOCK_BUTTON_OK); + add_sized (factory, stock_button_cancel, GTK_ICON_SIZE_BUTTON, GTK_STOCK_BUTTON_CANCEL); + add_sized (factory, stock_button_close, GTK_ICON_SIZE_BUTTON, GTK_STOCK_BUTTON_CLOSE); + add_sized (factory, stock_button_yes, GTK_ICON_SIZE_BUTTON, GTK_STOCK_BUTTON_YES); + add_sized (factory, stock_button_no, GTK_ICON_SIZE_BUTTON, GTK_STOCK_BUTTON_NO); + + add_unsized (factory, stock_close, GTK_STOCK_CLOSE); + add_unsized (factory, stock_exit, GTK_STOCK_QUIT); + add_unsized (factory, stock_help, GTK_STOCK_HELP); + add_unsized (factory, stock_new, GTK_STOCK_NEW); + add_unsized (factory, stock_open, GTK_STOCK_OPEN); + add_unsized (factory, stock_save, GTK_STOCK_SAVE); +} + +/* Sizes */ + +static GHashTable *icon_sizes = NULL; + +typedef struct _IconSize IconSize; + +struct _IconSize +{ + gchar *name; + + gboolean is_alias; + + union + { + gchar *target; + struct + { + gint width; + gint height; + } size; + } d; +}; + +static IconSize* +icon_size_new (const gchar *name) +{ + IconSize *is; + + is = g_new0 (IconSize, 1); + + is->name = g_strdup (name); + + return is; +} + +static void +icon_size_free (IconSize *is) +{ + g_free (is->name); + + if (is->is_alias) + g_free (is->d.target); + + g_free (is); +} + +static void +icon_size_insert (IconSize *is) +{ + gpointer old_key, old_value; + + /* Remove old ones */ + if (g_hash_table_lookup_extended (icon_sizes, + is->name, + &old_key, &old_value)) + { + g_hash_table_remove (icon_sizes, is->name); + icon_size_free (old_value); + } + + g_hash_table_insert (icon_sizes, + is->name, is); + +} + +static IconSize* +icon_size_lookup (const gchar *name) +{ + IconSize *is; + + is = g_hash_table_lookup (icon_sizes, + name); + + while (is && is->is_alias) + { + is = g_hash_table_lookup (icon_sizes, + is->d.target); + + } + + return is; +} + +static void +icon_size_add (const gchar *name, + gint width, + gint height) +{ + IconSize *is; + + is = icon_size_new (name); + is->d.size.width = width; + is->d.size.height = height; + + icon_size_insert (is); +} + +static void +icon_alias_add (const gchar *name, + const gchar *target) +{ + IconSize *is; + + is = icon_size_new (name); + is->is_alias = TRUE; + + is->d.target = g_strdup (target); + + icon_size_insert (is); +} + +static void +init_icon_sizes (void) +{ + if (icon_sizes == NULL) + { + IconSize *is; + + icon_sizes = g_hash_table_new (g_str_hash, g_str_equal); + + icon_size_add (GTK_ICON_SIZE_MENU, 16, 16); + icon_size_add (GTK_ICON_SIZE_BUTTON, 24, 24); + icon_size_add (GTK_ICON_SIZE_SMALL_TOOLBAR, 18, 18); + icon_size_add (GTK_ICON_SIZE_LARGE_TOOLBAR, 24, 24); + icon_size_add (GTK_ICON_SIZE_DIALOG, 48, 48); + } +} + +gboolean +gtk_icon_size_lookup (const gchar *alias, + gint *widthp, + gint *heightp) +{ + IconSize *is; + + g_return_val_if_fail (alias != NULL, FALSE); + + init_icon_sizes (); + + is = icon_size_lookup (alias); + + if (is == NULL) + return FALSE; + + if (widthp) + *widthp = is->d.size.width; + + if (heightp) + *heightp = is->d.size.height; + + return TRUE; +} + +void +gtk_icon_size_register (const gchar *alias, + gint width, + gint height) +{ + gpointer old_key, old_value; + + g_return_if_fail (alias != NULL); + g_return_if_fail (width > 0); + g_return_if_fail (height > 0); + + init_icon_sizes (); + + icon_size_add (alias, width, height); +} + +void +gtk_icon_size_register_alias (const gchar *alias, + const gchar *target) +{ + g_return_if_fail (alias != NULL); + g_return_if_fail (target != NULL); + + init_icon_sizes (); + + icon_alias_add (alias, target); +} + +/* Icon Set */ + + +/* Clear icon set contents, drop references to all contained + * GdkPixbuf objects and forget all GtkIconSources. Used to + * recycle an icon set. + */ +static void gtk_icon_set_clear (GtkIconSet *icon_set); + +static GdkPixbuf *find_in_cache (GtkIconSet *icon_set, + GtkStyle *style, + GtkTextDirection direction, + GtkStateType state, + const gchar *size); +static void add_to_cache (GtkIconSet *icon_set, + GtkStyle *style, + GtkTextDirection direction, + GtkStateType state, + const gchar *size, + GdkPixbuf *pixbuf); +static void clear_cache (GtkIconSet *icon_set, + gboolean style_detach); +static GSList* copy_cache (GtkIconSet *icon_set, + GtkIconSet *copy_recipient); +static void attach_to_style (GtkIconSet *icon_set, + GtkStyle *style); +static void detach_from_style (GtkIconSet *icon_set, + GtkStyle *style); +static void style_dnotify (gpointer data); + +struct _GtkIconSet +{ + guint ref_count; + + GSList *sources; + + /* Cache of the last few rendered versions of the icon. */ + GSList *cache; + + guint cache_size; + + guint cache_serial; +}; + +static guint cache_serial = 0; + +GtkIconSet* +gtk_icon_set_new (void) +{ + GtkIconSet *icon_set; + + icon_set = g_new (GtkIconSet, 1); + + icon_set->ref_count = 1; + icon_set->sources = NULL; + icon_set->cache = NULL; + icon_set->cache_size = 0; + icon_set->cache_serial = cache_serial; + + return icon_set; +} + +GtkIconSet* +gtk_icon_set_ref (GtkIconSet *icon_set) +{ + g_return_val_if_fail (icon_set != NULL, NULL); + g_return_val_if_fail (icon_set->ref_count > 0, NULL); + + icon_set->ref_count += 1; + + return icon_set; +} + +void +gtk_icon_set_unref (GtkIconSet *icon_set) +{ + g_return_if_fail (icon_set != NULL); + g_return_if_fail (icon_set->ref_count > 0); + + icon_set->ref_count -= 1; + + if (icon_set->ref_count == 0) + { + GSList *tmp_list = icon_set->sources; + while (tmp_list != NULL) + { + gtk_icon_source_free (tmp_list->data); + + tmp_list = g_slist_next (tmp_list); + } + + clear_cache (icon_set, TRUE); + + g_free (icon_set); + } +} + +GtkIconSet* +gtk_icon_set_copy (GtkIconSet *icon_set) +{ + GtkIconSet *copy; + GSList *tmp_list; + + copy = gtk_icon_set_new (); + + tmp_list = icon_set->sources; + while (tmp_list != NULL) + { + copy->sources = g_slist_prepend (copy->sources, + gtk_icon_source_copy (tmp_list->data)); + + tmp_list = g_slist_next (tmp_list); + } + + copy->sources = g_slist_reverse (copy->sources); + + copy->cache = copy_cache (icon_set, copy); + copy->cache_size = icon_set->cache_size; + copy->cache_serial = icon_set->cache_serial; + + return copy; +} + + +static gboolean +sizes_equivalent (const gchar *rhs, const gchar *lhs) +{ + gint r_w, r_h, l_w, l_h; + + gtk_icon_size_lookup (rhs, &r_w, &r_h); + gtk_icon_size_lookup (lhs, &l_w, &l_h); + + return r_w == l_w && r_h == l_h; +} + +static GtkIconSource* +find_and_prep_icon_source (GtkIconSet *icon_set, + GtkTextDirection direction, + GtkStateType state, + const gchar *size) +{ + GtkIconSource *source; + GSList *tmp_list; + + + /* We need to find the best icon source. Direction matters more + * than state, state matters more than size. icon_set->sources + * is sorted according to wildness, so if we take the first + * match we find it will be the least-wild match (if there are + * multiple matches for a given "wildness" then the RC file contained + * dumb stuff, and we end up with an arbitrary matching source) + */ + + source = NULL; + tmp_list = icon_set->sources; + while (tmp_list != NULL) + { + GtkIconSource *s = tmp_list->data; + + if ((s->any_direction || (s->direction == direction)) && + (s->any_state || (s->state == state)) && + (s->any_size || (sizes_equivalent (size, s->size)))) + { + source = s; + break; + } + + tmp_list = g_slist_next (tmp_list); + } + + if (source == NULL) + return NULL; + + if (source->pixbuf == NULL) + { + gchar *full; + + g_assert (source->filename); + + if (*source->filename != G_DIR_SEPARATOR) + full = gtk_rc_find_pixmap_in_path (NULL, source->filename); + else + full = g_strdup (source->filename); + + source->pixbuf = gdk_pixbuf_new_from_file (full); + + g_free (full); + + if (source->pixbuf == NULL) + { + /* Remove this icon source so we don't keep trying to + * load it. + */ + g_warning ("Failed to load icon '%s'", source->filename); + + icon_set->sources = g_slist_remove (icon_set->sources, source); + + gtk_icon_source_free (source); + + /* Try to fall back to other sources */ + if (icon_set->sources != NULL) + return find_and_prep_icon_source (icon_set, + direction, + state, + size); + else + return NULL; + } + } + + return source; +} + +GdkPixbuf* +gtk_icon_set_render_icon (GtkIconSet *icon_set, + GtkStyle *style, + GtkTextDirection direction, + GtkStateType state, + const gchar *size, + GtkWidget *widget, + const char *detail) +{ + GdkPixbuf *icon; + GtkIconSource *source; + + /* FIXME conceivably, everywhere this function + * returns NULL, we should return some default + * dummy icon like a question mark or the image icon + * from netscape + */ + + g_return_val_if_fail (icon_set != NULL, NULL); + g_return_val_if_fail (GTK_IS_STYLE (style), NULL); + + if (icon_set->sources == NULL) + return NULL; + + icon = find_in_cache (icon_set, style, direction, + state, size); + + if (icon) + { + g_object_ref (G_OBJECT (icon)); + return icon; + } + + + source = find_and_prep_icon_source (icon_set, direction, state, size); + + if (source == NULL) + return NULL; + + g_assert (source->pixbuf != NULL); + + icon = gtk_style_render_icon (style, + source, + direction, + state, + size, + widget, + detail); + + if (icon == NULL) + { + g_warning ("Theme engine failed to render icon"); + return NULL; + } + + add_to_cache (icon_set, style, direction, state, size, icon); + + return icon; +} + +/* Order sources by their "wildness", so that "wilder" sources are + * greater than "specific" sources; for determining ordering, + * direction beats state beats size. + */ + +static int +icon_source_compare (gconstpointer ap, gconstpointer bp) +{ + const GtkIconSource *a = ap; + const GtkIconSource *b = bp; + + if (!a->any_direction && b->any_direction) + return -1; + else if (a->any_direction && !b->any_direction) + return 1; + else if (!a->any_state && b->any_state) + return -1; + else if (a->any_state && !b->any_state) + return 1; + else if (!a->any_size && b->any_size) + return -1; + else if (a->any_size && !b->any_size) + return 1; + else + return 0; +} + +void +gtk_icon_set_add_source (GtkIconSet *icon_set, + const GtkIconSource *source) +{ + g_return_if_fail (icon_set != NULL); + g_return_if_fail (source != NULL); + + if (source->pixbuf == NULL && + source->filename == NULL) + { + g_warning ("Useless GtkIconSource contains NULL filename and pixbuf"); + return; + } + + icon_set->sources = g_slist_insert_sorted (icon_set->sources, + gtk_icon_source_copy (source), + icon_source_compare); +} + +GtkIconSource * +gtk_icon_source_copy (const GtkIconSource *source) +{ + GtkIconSource *copy; + + g_return_val_if_fail (source != NULL, NULL); + + copy = g_new (GtkIconSource, 1); + + *copy = *source; + + copy->filename = g_strdup (source->filename); + copy->size = g_strdup (source->size); + if (copy->pixbuf) + g_object_ref (G_OBJECT (copy->pixbuf)); + + return copy; +} + +void +gtk_icon_source_free (GtkIconSource *source) +{ + g_return_if_fail (source != NULL); + + g_free ((char*) source->filename); + g_free ((char*) source->size); + if (source->pixbuf) + g_object_unref (G_OBJECT (source->pixbuf)); + + g_free (source); +} + +void +gtk_icon_set_clear (GtkIconSet *icon_set) +{ + GSList *tmp_list; + + g_return_if_fail (icon_set != NULL); + + tmp_list = icon_set->sources; + while (tmp_list != NULL) + { + gtk_icon_source_free (tmp_list->data); + + tmp_list = g_slist_next (tmp_list); + } + + clear_cache (icon_set, TRUE); +} + +/* Note that the logical maximum is 20 per GtkTextDirection, so we could + * eventually set this to >20 to never throw anything out. + */ +#define NUM_CACHED_ICONS 8 + +typedef struct _CachedIcon CachedIcon; + +struct _CachedIcon +{ + /* These must all match to use the cached pixbuf. + * If any don't match, we must re-render the pixbuf. + */ + GtkStyle *style; + GtkTextDirection direction; + GtkStateType state; + gchar *size; + + GdkPixbuf *pixbuf; +}; + +static void +ensure_cache_up_to_date (GtkIconSet *icon_set) +{ + if (icon_set->cache_serial != cache_serial) + clear_cache (icon_set, TRUE); +} + +static void +cached_icon_free (CachedIcon *icon) +{ + g_free (icon->size); + g_object_unref (G_OBJECT (icon->pixbuf)); + + g_free (icon); +} + +static GdkPixbuf * +find_in_cache (GtkIconSet *icon_set, + GtkStyle *style, + GtkTextDirection direction, + GtkStateType state, + const gchar *size) +{ + GSList *tmp_list; + GSList *prev; + + ensure_cache_up_to_date (icon_set); + + prev = NULL; + tmp_list = icon_set->cache; + while (tmp_list != NULL) + { + CachedIcon *icon = tmp_list->data; + + if (icon->style == style && + icon->direction == direction && + icon->state == state && + strcmp (icon->size, size) == 0) + { + if (prev) + { + /* Move this icon to the front of the list. */ + prev->next = tmp_list->next; + tmp_list->next = icon_set->cache; + icon_set->cache = tmp_list; + } + + return icon->pixbuf; + } + + prev = tmp_list; + tmp_list = g_slist_next (tmp_list); + } + + return NULL; +} + +static void +add_to_cache (GtkIconSet *icon_set, + GtkStyle *style, + GtkTextDirection direction, + GtkStateType state, + const gchar *size, + GdkPixbuf *pixbuf) +{ + CachedIcon *icon; + + ensure_cache_up_to_date (icon_set); + + g_object_ref (G_OBJECT (pixbuf)); + + /* We have to ref the style, since if the style was finalized + * its address could be reused by another style, creating a + * really weird bug + */ + + if (style) + g_object_ref (G_OBJECT (style)); + + + icon = g_new (CachedIcon, 1); + icon_set->cache = g_slist_prepend (icon_set->cache, icon); + + icon->style = style; + icon->direction = direction; + icon->state = state; + icon->size = g_strdup (size); + icon->pixbuf = pixbuf; + + if (icon->style) + attach_to_style (icon_set, icon->style); + + if (icon_set->cache_size >= NUM_CACHED_ICONS) + { + /* Remove oldest item in the cache */ + + GSList *tmp_list; + + tmp_list = icon_set->cache; + + /* Find next-to-last link */ + g_assert (NUM_CACHED_ICONS > 2); + while (tmp_list->next->next) + tmp_list = tmp_list->next; + + g_assert (tmp_list != NULL); + g_assert (tmp_list->next != NULL); + g_assert (tmp_list->next->next == NULL); + + /* Free the last icon */ + icon = tmp_list->next->data; + + g_slist_free (tmp_list->next); + tmp_list->next = NULL; + + cached_icon_free (icon); + } +} + +static void +clear_cache (GtkIconSet *icon_set, + gboolean style_detach) +{ + GSList *tmp_list; + GtkStyle *last_style = NULL; + + tmp_list = icon_set->cache; + while (tmp_list != NULL) + { + CachedIcon *icon = tmp_list->data; + + if (style_detach) + { + /* simple optimization for the case where the cache + * contains contiguous icons from the same style. + * it's safe to call detach_from_style more than + * once on the same style though. + */ + if (last_style != icon->style) + { + detach_from_style (icon_set, icon->style); + last_style = icon->style; + } + } + + cached_icon_free (icon); + + tmp_list = g_slist_next (tmp_list); + } + + g_slist_free (icon_set->cache); + icon_set->cache = NULL; + icon_set->cache_size = 0; +} + +static GSList* +copy_cache (GtkIconSet *icon_set, + GtkIconSet *copy_recipient) +{ + GSList *tmp_list; + GSList *copy = NULL; + + ensure_cache_up_to_date (icon_set); + + tmp_list = icon_set->cache; + while (tmp_list != NULL) + { + CachedIcon *icon = tmp_list->data; + CachedIcon *icon_copy = g_new (CachedIcon, 1); + + *icon_copy = *icon; + + if (icon_copy->style) + attach_to_style (copy_recipient, icon_copy->style); + + g_object_ref (G_OBJECT (icon_copy->pixbuf)); + + icon_copy->size = g_strdup (icon->size); + + copy = g_slist_prepend (copy, icon_copy); + + tmp_list = g_slist_next (tmp_list); + } + + return g_slist_reverse (copy); +} + +static void +attach_to_style (GtkIconSet *icon_set, + GtkStyle *style) +{ + GHashTable *table; + + table = g_object_get_qdata (G_OBJECT (style), + g_quark_try_string ("gtk-style-icon-sets")); + + if (table == NULL) + { + table = g_hash_table_new (NULL, NULL); + g_object_set_qdata_full (G_OBJECT (style), + g_quark_from_static_string ("gtk-style-icon-sets"), + table, + style_dnotify); + } + + g_hash_table_insert (table, icon_set, icon_set); +} + +static void +detach_from_style (GtkIconSet *icon_set, + GtkStyle *style) +{ + GHashTable *table; + + table = g_object_get_qdata (G_OBJECT (style), + g_quark_try_string ("gtk-style-icon-sets")); + + if (table != NULL) + g_hash_table_remove (table, icon_set); +} + +static void +iconsets_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + GtkIconSet *icon_set = key; + + /* We only need to remove cache entries for the given style; + * but that complicates things because in destroy notify + * we don't know which style got destroyed, and 95% of the + * time all cache entries will have the same style, + * so this is faster anyway. + */ + + clear_cache (icon_set, FALSE); +} + +static void +style_dnotify (gpointer data) +{ + GHashTable *table = data; + + g_hash_table_foreach (table, iconsets_foreach, NULL); + + g_hash_table_destroy (table); +} + +/* This allows the icon set to detect that its cache is out of date. */ +void +_gtk_icon_set_invalidate_caches (void) +{ + ++cache_serial; +} diff --git a/gtk/gtkiconfactory.h b/gtk/gtkiconfactory.h new file mode 100644 index 000000000..357e37eb7 --- /dev/null +++ b/gtk/gtkiconfactory.h @@ -0,0 +1,159 @@ +/* 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 + * modify it under the terms of the GNU Lesser General Public + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * 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/. + */ + +#ifndef __GTK_ICON_FACTORY_H__ +#define __GTK_ICON_FACTORY_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _GtkIconFactoryClass GtkIconFactoryClass; + +#define GTK_TYPE_ICON_FACTORY (gtk_icon_factory_get_type ()) +#define GTK_ICON_FACTORY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_ICON_FACTORY, GtkIconFactory)) +#define GTK_ICON_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ICON_FACTORY, GtkIconFactoryClass)) +#define GTK_IS_ICON_FACTORY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_ICON_FACTORY)) +#define GTK_IS_ICON_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ICON_FACTORY)) +#define GTK_ICON_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ICON_FACTORY, GtkIconFactoryClass)) + +struct _GtkIconFactory +{ + GObject parent_instance; + + GHashTable *icons; +}; + +struct _GtkIconFactoryClass +{ + GObjectClass parent_class; + + +}; + +GType gtk_icon_factory_get_type (void); +GtkIconFactory* gtk_icon_factory_new (void); +void gtk_icon_factory_add (GtkIconFactory *factory, + const gchar *stock_id, + GtkIconSet *icon_set); +GtkIconSet* gtk_icon_factory_lookup (GtkIconFactory *factory, + const gchar *stock_id); + +/* Manage the default icon factory stack */ + +void gtk_icon_factory_add_default (GtkIconFactory *factory); +void gtk_icon_factory_remove_default (GtkIconFactory *factory); +GtkIconSet* gtk_icon_factory_lookup_default (const gchar *stock_id); + +/* Get preferred real size from registered semantic size. Note that + * themes SHOULD use this size, but they aren't required to; for size + * requests and such, you should get the actual pixbuf from the icon + * set and see what size was rendered. + * + * This function is intended for people who are scaling icons, + * rather than for people who are displaying already-scaled icons. + * That is, if you are displaying an icon, you should get the + * size from the rendered pixbuf, not from here. + */ + +gboolean gtk_icon_size_lookup (const gchar *alias, + gint *width, + gint *height); +void gtk_icon_size_register (const gchar *alias, + gint width, + gint height); +void gtk_icon_size_register_alias (const gchar *alias, + const gchar *target); + + +/* Standard sizes */ + +#define GTK_ICON_SIZE_MENU "gtk-menu" +#define GTK_ICON_SIZE_SMALL_TOOLBAR "gtk-small-toolbar" +#define GTK_ICON_SIZE_LARGE_TOOLBAR "gtk-large-toolbar" +#define GTK_ICON_SIZE_BUTTON "gtk-button" +#define GTK_ICON_SIZE_DIALOG "gtk-dialog" + +/* Icon sets */ + +GtkIconSet* gtk_icon_set_new (void); + +GtkIconSet* gtk_icon_set_ref (GtkIconSet *icon_set); +void gtk_icon_set_unref (GtkIconSet *icon_set); +GtkIconSet* gtk_icon_set_copy (GtkIconSet *icon_set); + +/* Get one of the icon variants in the set, creating the variant if + * necessary. + */ +GdkPixbuf* gtk_icon_set_render_icon (GtkIconSet *icon_set, + GtkStyle *style, + GtkTextDirection direction, + GtkStateType state, + const gchar *size, + GtkWidget *widget, + const char *detail); + + +void gtk_icon_set_add_source (GtkIconSet *icon_set, + const GtkIconSource *source); + +/* INTERNAL */ +void _gtk_icon_set_invalidate_caches (void); + +struct _GtkIconSource +{ + /* Either filename or pixbuf can be NULL. If both are non-NULL, + * the pixbuf is assumed to be the already-loaded contents of the + * file. + */ + gchar *filename; + GdkPixbuf *pixbuf; + + GtkTextDirection direction; + GtkStateType state; + gchar *size; + + /* If TRUE, then the parameter is wildcarded, and the above + * fields should be ignored. If FALSE, the parameter is + * specified, and the above fields should be valid. + */ + guint any_direction : 1; + guint any_state : 1; + guint any_size : 1; +}; + + +GtkIconSource* gtk_icon_source_copy (const GtkIconSource *source); +void gtk_icon_source_free (GtkIconSource *source); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GTK_ICON_FACTORY_H__ */ diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 01154d929..504b2a2e1 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,8 +84,346 @@ 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_from_pixmap (GdkPixmap *pixmap, + GdkBitmap *mask) +{ + GtkImage *image; + + 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_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_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 (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)); + + gtk_image_clear (image); + + if (gdk_image) + { + 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 + { + /* Clean up the mask if gdk_image was NULL */ + if (mask) + g_object_unref (G_OBJECT (mask)); + } +} + +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* @@ -98,25 +446,9 @@ gtk_image_set (GtkImage *image, GdkImage *val, GdkBitmap *mask) { - g_return_if_fail (image != NULL); g_return_if_fail (GTK_IS_IMAGE (image)); - image->image = val; - image->mask = mask; - - if (image->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; - } - else - { - GTK_WIDGET (image)->requisition.width = 0; - GTK_WIDGET (image)->requisition.height = 0; - } - - if (GTK_WIDGET_VISIBLE (image)) - gtk_widget_queue_resize (GTK_WIDGET (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 (image->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; + + } + + 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; +} + + diff --git a/gtk/gtkimage.h b/gtk/gtkimage.h index 147a60646..266d032e6 100644 --- a/gtk/gtkimage.h +++ b/gtk/gtkimage.h @@ -36,7 +36,6 @@ extern "C" { #endif /* __cplusplus */ - #define GTK_TYPE_IMAGE (gtk_image_get_type ()) #define GTK_IMAGE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_IMAGE, GtkImage)) #define GTK_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_IMAGE, GtkImageClass)) @@ -48,12 +47,65 @@ extern "C" { typedef struct _GtkImage GtkImage; typedef struct _GtkImageClass GtkImageClass; +typedef struct _GtkImagePixmapData GtkImagePixmapData; +typedef struct _GtkImageImageData GtkImageImageData; +typedef struct _GtkImagePixbufData GtkImagePixbufData; +typedef struct _GtkImageStockData GtkImageStockData; +typedef struct _GtkImageIconSetData GtkImageIconSetData; + +struct _GtkImagePixmapData +{ + GdkPixmap *pixmap; + GdkBitmap *mask; +}; + +struct _GtkImageImageData +{ + GdkImage *image; + GdkBitmap *mask; +}; + +struct _GtkImagePixbufData +{ + GdkPixbuf *pixbuf; +}; + +struct _GtkImageStockData +{ + gchar *stock_id; + gchar *size; +}; + +struct _GtkImageIconSetData +{ + GtkIconSet *icon_set; + gchar *size; +}; + +typedef enum +{ + GTK_IMAGE_EMPTY, + GTK_IMAGE_PIXMAP, + GTK_IMAGE_IMAGE, + GTK_IMAGE_PIXBUF, + GTK_IMAGE_STOCK, + GTK_IMAGE_ICON_SET +} GtkImageType; + struct _GtkImage { GtkMisc misc; - GdkImage *image; - GdkBitmap *mask; + GtkImageType storage_type; + + union + { + GtkImagePixmapData pixmap; + GtkImageImageData image; + GtkImagePixbufData pixbuf; + GtkImageStockData stock; + GtkImageIconSetData icon_set; + } data; }; struct _GtkImageClass @@ -61,8 +113,56 @@ struct _GtkImageClass GtkMiscClass parent_class; }; - GtkType gtk_image_get_type (void) G_GNUC_CONST; + +GtkWidget* gtk_image_new_from_pixmap (GdkPixmap *pixmap, + GdkBitmap *mask); +GtkWidget* gtk_image_new_from_image (GdkImage *image, + GdkBitmap *mask); +GtkWidget* gtk_image_new_from_file (const gchar *filename); +GtkWidget* gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf); +GtkWidget* gtk_image_new_from_stock (const gchar *stock_id, + const gchar *size); +GtkWidget* gtk_image_new_from_icon_set (GtkIconSet *icon_set, + const gchar *size); + +void gtk_image_set_from_pixmap (GtkImage *image, + GdkPixmap *pixmap, + GdkBitmap *mask); +void gtk_image_set_from_image (GtkImage *image, + GdkImage *gdk_image, + GdkBitmap *mask); +void gtk_image_set_from_file (GtkImage *image, + const gchar *filename); +void gtk_image_set_from_pixbuf (GtkImage *image, + GdkPixbuf *pixbuf); +void gtk_image_set_from_stock (GtkImage *image, + const gchar *stock_id, + const gchar *size); +void gtk_image_set_from_icon_set (GtkImage *image, + GtkIconSet *icon_set, + const gchar *size); + +GtkImageType gtk_image_get_storage_type (GtkImage *image); + +void gtk_image_get_pixmap (GtkImage *image, + GdkPixmap **pixmap, + GdkBitmap **mask); +void gtk_image_get_image (GtkImage *image, + GdkImage **gdk_image, + GdkBitmap **mask); +GdkPixbuf* gtk_image_get_pixbuf (GtkImage *image); +void gtk_image_get_stock (GtkImage *image, + gchar **stock_id, + gchar **size); +void gtk_image_get_icon_set (GtkImage *image, + GtkIconSet **icon_set, + gchar **size); + + + +/* These three are deprecated */ + GtkWidget* gtk_image_new (GdkImage *val, GdkBitmap *mask); void gtk_image_set (GtkImage *image, diff --git a/gtk/gtkrc.c b/gtk/gtkrc.c index 495fbbd41..324e8d3a5 100644 --- a/gtk/gtkrc.c +++ b/gtk/gtkrc.c @@ -60,6 +60,7 @@ #include "gtkbindings.h" #include "gtkthemes.h" #include "gtkintl.h" +#include "gtkiconfactory.h" typedef struct _GtkRcSet GtkRcSet; typedef struct _GtkRcNode GtkRcNode; @@ -127,6 +128,9 @@ static void gtk_rc_parse_pixmap_path_string (gchar *pix_path) static guint gtk_rc_parse_module_path (GScanner *scanner); static void gtk_rc_parse_module_path_string (gchar *mod_path); static guint gtk_rc_parse_path_pattern (GScanner *scanner); +static guint gtk_rc_parse_stock (GScanner *scanner, + GtkRcStyle *rc_style, + GtkIconFactory *factory); static void gtk_rc_clear_hash_node (gpointer key, gpointer data, gpointer user_data); @@ -220,6 +224,9 @@ static const struct { "highest", GTK_RC_TOKEN_HIGHEST }, { "engine", GTK_RC_TOKEN_ENGINE }, { "module_path", GTK_RC_TOKEN_MODULE_PATH }, + { "stock", GTK_RC_TOKEN_STOCK }, + { "LTR", GTK_RC_TOKEN_LTR }, + { "RTL", GTK_RC_TOKEN_RTL } }; static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]); @@ -857,8 +864,19 @@ gtk_rc_style_finalize (GObject *object) tmp_list1 = tmp_list1->next; } + g_slist_free (rc_style->rc_style_lists); + tmp_list1 = rc_style->icon_factories; + while (tmp_list1) + { + g_object_unref (G_OBJECT (tmp_list1->data)); + + tmp_list1 = tmp_list1->next; + } + + g_slist_free (rc_style->icon_factories); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -887,7 +905,7 @@ gtk_rc_style_copy (GtkRcStyle *orig) { GtkRcStyle *style; - g_return_if_fail (GTK_IS_RC_STYLE (orig)); + g_return_val_if_fail (GTK_IS_RC_STYLE (orig), NULL); style = GTK_RC_STYLE_GET_CLASS (orig)->clone (orig); GTK_RC_STYLE_GET_CLASS (style)->merge (style, orig); @@ -1363,10 +1381,11 @@ gtk_rc_style_to_style (GtkRcStyle *rc_style) style = GTK_RC_STYLE_GET_CLASS (rc_style)->create_style (rc_style); style->rc_style = rc_style; + gtk_rc_style_ref (rc_style); - GTK_STYLE_GET_CLASS (style)->init_from_rc (style, rc_style); - + GTK_STYLE_GET_CLASS (style)->init_from_rc (style, rc_style); + return style; } @@ -1402,13 +1421,13 @@ gtk_rc_init_style (GSList *rc_styles) while (tmp_styles) { GtkRcStyle *rc_style = tmp_styles->data; - + if (G_OBJECT_TYPE (rc_style) != rc_style_type) { base_style = rc_style; break; } - + tmp_styles = tmp_styles->next; } @@ -1419,13 +1438,31 @@ gtk_rc_init_style (GSList *rc_styles) while (tmp_styles) { GtkRcStyle *rc_style = tmp_styles->data; - - proto_style_class->merge (proto_style, rc_style); - + GSList *factories; + + proto_style_class->merge (proto_style, rc_style); + /* Point from each rc_style to the list of styles */ if (!g_slist_find (rc_style->rc_style_lists, rc_styles)) rc_style->rc_style_lists = g_slist_prepend (rc_style->rc_style_lists, rc_styles); - + + factories = g_slist_copy (rc_style->icon_factories); + if (factories) + { + GSList *iter; + + iter = factories; + while (iter != NULL) + { + g_object_ref (G_OBJECT (iter->data)); + iter = g_slist_next (iter); + } + + proto_style->icon_factories = g_slist_concat (proto_style->icon_factories, + factories); + + } + tmp_styles = tmp_styles->next; } @@ -1508,6 +1545,7 @@ gtk_rc_parse_style (GScanner *scanner) guint token; gint insert; gint i; + GtkIconFactory *our_factory = NULL; token = g_scanner_get_next_token (scanner); if (token != GTK_RC_TOKEN_STYLE) @@ -1519,6 +1557,12 @@ gtk_rc_parse_style (GScanner *scanner) insert = FALSE; rc_style = gtk_rc_style_find (scanner->value.v_string); + + /* If there's a list, its first member is always the factory belonging + * to this RcStyle + */ + if (rc_style && rc_style->icon_factories) + our_factory = rc_style->icon_factories->data; if (!rc_style) { @@ -1532,7 +1576,7 @@ gtk_rc_parse_style (GScanner *scanner) for (i = 0; i < 5; i++) rc_style->color_flags[i] = 0; } - + token = g_scanner_peek_next_token (scanner); if (token == G_TOKEN_EQUAL_SIGN) { @@ -1550,6 +1594,8 @@ gtk_rc_parse_style (GScanner *scanner) parent_style = gtk_rc_style_find (scanner->value.v_string); if (parent_style) { + GSList *factories; + for (i = 0; i < 5; i++) { rc_style->color_flags[i] = parent_style->color_flags[i]; @@ -1575,6 +1621,35 @@ gtk_rc_parse_style (GScanner *scanner) g_free (rc_style->bg_pixmap_name[i]); rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]); } + + /* Append parent's factories, adding a ref to them */ + if (parent_style->icon_factories != NULL) + { + /* Add a factory for ourselves if we have none, + * in case we end up defining more stock icons. + * I see no real way around this; we need to maintain + * the invariant that the first factory in the list + * is always our_factory, the one belonging to us, + * and if we put parent factories in the list we can't + * do that if the style is reopened. + */ + if (our_factory == NULL) + { + our_factory = gtk_icon_factory_new (); + rc_style->icon_factories = g_slist_prepend (rc_style->icon_factories, + our_factory); + } + + rc_style->icon_factories = g_slist_concat (rc_style->icon_factories, + g_slist_copy (parent_style->icon_factories)); + + factories = parent_style->icon_factories; + while (factories != NULL) + { + g_object_ref (G_OBJECT (factories->data)); + factories = factories->next; + } + } } } @@ -1625,6 +1700,15 @@ gtk_rc_parse_style (GScanner *scanner) case GTK_RC_TOKEN_ENGINE: token = gtk_rc_parse_engine (scanner, &rc_style); break; + case GTK_RC_TOKEN_STOCK: + if (our_factory == NULL) + { + our_factory = gtk_icon_factory_new (); + rc_style->icon_factories = g_slist_prepend (rc_style->icon_factories, + our_factory); + } + token = gtk_rc_parse_stock (scanner, rc_style, our_factory); + break; default: g_scanner_get_next_token (scanner); token = G_TOKEN_RIGHT_CURLY; @@ -2502,6 +2586,270 @@ gtk_rc_parse_path_pattern (GScanner *scanner) return G_TOKEN_NONE; } +static guint +gtk_rc_parse_stock_id (GScanner *scanner, + gchar **stock_id) +{ + guint token; + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_LEFT_BRACE) + return G_TOKEN_LEFT_BRACE; + + token = g_scanner_get_next_token (scanner); + + if (token != G_TOKEN_STRING) + return G_TOKEN_STRING; + + *stock_id = g_strdup (scanner->value.v_string); + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_RIGHT_BRACE) + { + g_free (*stock_id); + return G_TOKEN_RIGHT_BRACE; + } + + return G_TOKEN_NONE; +} + +static void +cleanup_source (GtkIconSource *source) +{ + g_free (source->filename); + g_free (source->size); +} + +static guint +gtk_rc_parse_icon_source (GScanner *scanner, + GtkIconSet *icon_set) +{ + guint token; + GtkIconSource source = { NULL, NULL, + 0, 0, 0, + TRUE, TRUE, TRUE }; + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_LEFT_CURLY) + return G_TOKEN_LEFT_CURLY; + + token = g_scanner_get_next_token (scanner); + + if (token != G_TOKEN_STRING) + return G_TOKEN_STRING; + + source.filename = g_strdup (scanner->value.v_string); + + token = g_scanner_get_next_token (scanner); + + if (token == G_TOKEN_RIGHT_CURLY) + { + gtk_icon_set_add_source (icon_set, &source); + cleanup_source (&source); + return G_TOKEN_NONE; + } + else if (token != G_TOKEN_COMMA) + { + cleanup_source (&source); + return G_TOKEN_COMMA; + } + + /* Get the direction */ + + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case GTK_RC_TOKEN_RTL: + source.any_direction = FALSE; + source.direction = GTK_TEXT_DIR_RTL; + break; + + case GTK_RC_TOKEN_LTR: + source.any_direction = FALSE; + source.direction = GTK_TEXT_DIR_LTR; + break; + + case '*': + break; + + default: + cleanup_source (&source); + return GTK_RC_TOKEN_RTL; + break; + } + + token = g_scanner_get_next_token (scanner); + + if (token == G_TOKEN_RIGHT_CURLY) + { + gtk_icon_set_add_source (icon_set, &source); + cleanup_source (&source); + return G_TOKEN_NONE; + } + else if (token != G_TOKEN_COMMA) + { + cleanup_source (&source); + return G_TOKEN_COMMA; + } + + /* Get the state */ + + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case GTK_RC_TOKEN_NORMAL: + source.any_state = FALSE; + source.state = GTK_STATE_NORMAL; + break; + + case GTK_RC_TOKEN_PRELIGHT: + source.any_state = FALSE; + source.state = GTK_STATE_PRELIGHT; + break; + + + case GTK_RC_TOKEN_INSENSITIVE: + source.any_state = FALSE; + source.state = GTK_STATE_INSENSITIVE; + break; + + case GTK_RC_TOKEN_ACTIVE: + source.any_state = FALSE; + source.state = GTK_STATE_ACTIVE; + break; + + case GTK_RC_TOKEN_SELECTED: + source.any_state = FALSE; + source.state = GTK_STATE_SELECTED; + break; + + case '*': + break; + + default: + cleanup_source (&source); + return GTK_RC_TOKEN_PRELIGHT; + break; + } + + token = g_scanner_get_next_token (scanner); + + if (token == G_TOKEN_RIGHT_CURLY) + { + gtk_icon_set_add_source (icon_set, &source); + cleanup_source (&source); + return G_TOKEN_NONE; + } + else if (token != G_TOKEN_COMMA) + { + cleanup_source (&source); + return G_TOKEN_COMMA; + } + + /* Get the size */ + + token = g_scanner_get_next_token (scanner); + + if (token != '*') + { + if (token != G_TOKEN_STRING) + { + cleanup_source (&source); + return G_TOKEN_STRING; + } + + source.size = g_strdup (scanner->value.v_string); + source.any_size = FALSE; + } + + /* Check the close brace */ + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_RIGHT_CURLY) + { + cleanup_source (&source); + return G_TOKEN_RIGHT_CURLY; + } + + gtk_icon_set_add_source (icon_set, &source); + + cleanup_source (&source); + + return G_TOKEN_NONE; +} + +static guint +gtk_rc_parse_stock (GScanner *scanner, + GtkRcStyle *rc_style, + GtkIconFactory *factory) +{ + GtkIconSet *icon_set = NULL; + gchar *stock_id = NULL; + guint token; + + token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_STOCK) + return GTK_RC_TOKEN_STOCK; + + token = gtk_rc_parse_stock_id (scanner, &stock_id); + if (token != G_TOKEN_NONE) + return token; + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_EQUAL_SIGN) + { + g_free (stock_id); + return G_TOKEN_EQUAL_SIGN; + } + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_LEFT_CURLY) + { + g_free (stock_id); + return G_TOKEN_LEFT_CURLY; + } + + token = g_scanner_peek_next_token (scanner); + while (token != G_TOKEN_RIGHT_CURLY) + { + if (icon_set == NULL) + icon_set = gtk_icon_set_new (); + + token = gtk_rc_parse_icon_source (scanner, icon_set); + if (token != G_TOKEN_NONE) + { + g_free (stock_id); + gtk_icon_set_unref (icon_set); + return token; + } + + token = g_scanner_get_next_token (scanner); + + if (token != G_TOKEN_COMMA && + token != G_TOKEN_RIGHT_CURLY) + { + g_free (stock_id); + gtk_icon_set_unref (icon_set); + return G_TOKEN_RIGHT_CURLY; + } + } + + if (icon_set) + { + gtk_icon_factory_add (factory, + stock_id, + icon_set); + + gtk_icon_set_unref (icon_set); + } + + g_free (stock_id); + + return G_TOKEN_NONE; +} + /* typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window, GdkColormap *colormap, diff --git a/gtk/gtkrc.h b/gtk/gtkrc.h index a1a98f227..0b3703931 100644 --- a/gtk/gtkrc.h +++ b/gtk/gtkrc.h @@ -35,6 +35,9 @@ extern "C" { #endif /* __cplusplus */ +/* Forward declaration */ +typedef struct _GtkIconFactory GtkIconFactory; + #define GTK_TYPE_RC_STYLE (gtk_rc_style_get_type ()) #define GTK_RC_STYLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_RC_STYLE, GtkRcStyle)) #define GTK_RC_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_RC_STYLE, GtkRcStyleClass)) @@ -70,11 +73,13 @@ struct _GtkRcStyle gint xthickness; gint ythickness; - + /*< private >*/ /* list of RC style lists including this RC style */ GSList *rc_style_lists; + + GSList *icon_factories; }; struct _GtkRcStyleClass @@ -177,6 +182,9 @@ typedef enum { GTK_RC_TOKEN_HIGHEST, GTK_RC_TOKEN_ENGINE, GTK_RC_TOKEN_MODULE_PATH, + GTK_RC_TOKEN_STOCK, + GTK_RC_TOKEN_LTR, + GTK_RC_TOKEN_RTL, GTK_RC_TOKEN_LAST } GtkRcTokenType; diff --git a/gtk/gtkstock.c b/gtk/gtkstock.c new file mode 100644 index 000000000..ecb307973 --- /dev/null +++ b/gtk/gtkstock.c @@ -0,0 +1,198 @@ +/* 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 + * modify it under the terms of the GNU Lesser General Public + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * 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/. + */ + +#include "gtkstock.h" +#include "gtkintl.h" +#include + +static GHashTable *stock_hash = NULL; +static void init_stock_hash (void); + +static void +real_add (const GtkStockItem *items, + guint n_items, + gboolean copy) +{ + int i; + + init_stock_hash (); + + if (n_items == 0) + return; + + i = 0; + while (i < n_items) + { + gpointer old_key, old_value; + const GtkStockItem *item = &items[i]; + if (copy) + item = gtk_stock_item_copy (item); + + if (g_hash_table_lookup_extended (stock_hash, item->stock_id, + &old_key, &old_value)) + { + g_hash_table_remove (stock_hash, old_key); + gtk_stock_item_free (old_value); + } + + g_hash_table_insert (stock_hash, + (gchar*)item->stock_id, (GtkStockItem*)item); + + ++i; + } +} + +void +gtk_stock_add (const GtkStockItem *items, + guint n_items) +{ + g_return_if_fail (items != NULL); + + real_add (items, n_items, TRUE); +} + +void +gtk_stock_add_static (const GtkStockItem *items, + guint n_items) +{ + g_return_if_fail (items != NULL); + + real_add (items, n_items, FALSE); +} + +gboolean +gtk_stock_lookup (const gchar *stock_id, + GtkStockItem *item) +{ + const GtkStockItem *found; + + g_return_val_if_fail (stock_id != NULL, FALSE); + g_return_val_if_fail (item != NULL, FALSE); + + init_stock_hash (); + + found = g_hash_table_lookup (stock_hash, stock_id); + + if (found) + { + *item = *found; + if (item->label) + item->label = dgettext (item->translation_domain, item->label); + } + + return found != NULL; +} + +static void +listify_foreach (gpointer key, gpointer value, gpointer data) +{ + GSList **list = data; + + *list = g_slist_prepend (*list, value); +} + +static GSList * +g_hash_table_get_values (GHashTable *table) +{ + GSList *list = NULL; + + g_hash_table_foreach (table, listify_foreach, &list); + + return list; +} + +GSList * +gtk_stock_list_items (void) +{ + init_stock_hash (); + + return g_hash_table_get_values (stock_hash); +} + +GtkStockItem * +gtk_stock_item_copy (const GtkStockItem *item) +{ + GtkStockItem *copy; + + g_return_val_if_fail (item != NULL, NULL); + + copy = g_new (GtkStockItem, 1); + + *copy = *item; + + copy->stock_id = g_strdup (item->stock_id); + copy->label = g_strdup (item->label); + copy->translation_domain = g_strdup (item->translation_domain); + + return copy; +} + +void +gtk_stock_item_free (GtkStockItem *item) +{ + g_return_if_fail (item != NULL); + + g_free ((gchar*)item->stock_id); + g_free ((gchar*)item->label); + g_free ((gchar*)item->translation_domain); + + g_free (item); +} + +static GtkStockItem builtin_items [] = +{ + /* KEEP IN SYNC with gtkiconfactory.c stock icons */ + + { GTK_STOCK_DIALOG_INFO, N_("Information"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_DIALOG_WARNING, N_("Warning"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_DIALOG_ERROR, N_("Error"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_DIALOG_QUESTION, N_("Question"), 0, 0, GETTEXT_PACKAGE }, + + { GTK_STOCK_BUTTON_APPLY, N_("_Apply"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_BUTTON_OK, N_("OK"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_BUTTON_CANCEL, N_("Cancel"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_BUTTON_CLOSE, N_("_Close"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_BUTTON_YES, N_("_Yes"), 0, 0, GETTEXT_PACKAGE }, + { GTK_STOCK_BUTTON_NO, N_("_No"), 0, 0, GETTEXT_PACKAGE }, + + { GTK_STOCK_CLOSE, N_("Close"), GDK_CONTROL_MASK, 'w', GETTEXT_PACKAGE }, + { GTK_STOCK_QUIT, N_("Quit"), GDK_CONTROL_MASK, 'q', GETTEXT_PACKAGE }, + { GTK_STOCK_HELP, N_("Help"), GDK_CONTROL_MASK, 'h', GETTEXT_PACKAGE }, + { GTK_STOCK_NEW, N_("New"), GDK_CONTROL_MASK, 'n', GETTEXT_PACKAGE }, + { GTK_STOCK_OPEN, N_("Open"), GDK_CONTROL_MASK, 'o', GETTEXT_PACKAGE }, + { GTK_STOCK_SAVE, N_("Save"), GDK_CONTROL_MASK, 's', GETTEXT_PACKAGE } +}; + +static void +init_stock_hash (void) +{ + if (stock_hash == NULL) + { + stock_hash = g_hash_table_new (g_str_hash, g_str_equal); + + gtk_stock_add_static (builtin_items, G_N_ELEMENTS (builtin_items)); + } +} diff --git a/gtk/gtkstock.h b/gtk/gtkstock.h new file mode 100644 index 000000000..02b51ff97 --- /dev/null +++ b/gtk/gtkstock.h @@ -0,0 +1,89 @@ +/* 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 + * modify it under the terms of the GNU Lesser General Public + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * 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/. + */ + +#ifndef __GTK_STOCK_H__ +#define __GTK_STOCK_H__ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _GtkStockItem GtkStockItem; + +struct _GtkStockItem +{ + gchar *stock_id; + gchar *label; + GdkModifierType modifier; + guint keyval; + gchar *translation_domain; +}; + +void gtk_stock_add (const GtkStockItem *item, + guint n_items); +void gtk_stock_add_static (const GtkStockItem *item, + guint n_items); +gboolean gtk_stock_lookup (const gchar *stock_id, + GtkStockItem *item); + +/* Should free the list, but DO NOT modify the items in the list. + * This function is only useful for GUI builders and such. + */ +GSList* gtk_stock_list_items (void); + +GtkStockItem *gtk_stock_item_copy (const GtkStockItem *item); +void gtk_stock_item_free (GtkStockItem *item); + + +/* Stock IDs */ +#define GTK_STOCK_DIALOG_INFO "gtk-dialog-info" +#define GTK_STOCK_DIALOG_WARNING "gtk-dialog-warning" +#define GTK_STOCK_DIALOG_ERROR "gtk-dialog-error" +#define GTK_STOCK_DIALOG_QUESTION "gtk-dialog-question" + +#define GTK_STOCK_BUTTON_APPLY "gtk-button-apply" +#define GTK_STOCK_BUTTON_OK "gtk-button-ok" +#define GTK_STOCK_BUTTON_CANCEL "gtk-button-cancel" +#define GTK_STOCK_BUTTON_CLOSE "gtk-button-close" +#define GTK_STOCK_BUTTON_YES "gtk-button-yes" +#define GTK_STOCK_BUTTON_NO "gtk-button-no" + +#define GTK_STOCK_CLOSE "gtk-close" +#define GTK_STOCK_QUIT "gtk-quit" +#define GTK_STOCK_HELP "gtk-help" +#define GTK_STOCK_NEW "gtk-new" +#define GTK_STOCK_OPEN "gtk-open" +#define GTK_STOCK_SAVE "gtk-save" + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GTK_STOCK_H__ */ diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index a7c1b6880..087bcb12e 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -31,7 +31,7 @@ #include "gtkstyle.h" #include "gtkwidget.h" #include "gtkthemes.h" - +#include "gtkiconfactory.h" #define LIGHTNESS_MULT 1.3 #define DARKNESS_MULT 0.7 @@ -56,7 +56,16 @@ static void gtk_style_real_set_background (GtkStyle *style, GtkStateType state_type); static GtkStyle *gtk_style_real_clone (GtkStyle *style); static void gtk_style_real_init_from_rc (GtkStyle *style, - GtkRcStyle *rc_style); + GtkRcStyle *rc_style); + + +static GdkPixbuf *gtk_default_render_icon (GtkStyle *style, + const GtkIconSource *source, + GtkTextDirection direction, + GtkStateType state, + const gchar *size, + GtkWidget *widget, + const gchar *detail); static void gtk_default_draw_hline (GtkStyle *style, GdkWindow *window, @@ -445,7 +454,8 @@ gtk_style_class_init (GtkStyleClass *klass) klass->realize = gtk_style_real_realize; klass->unrealize = gtk_style_real_unrealize; klass->set_background = gtk_style_real_set_background; - + klass->render_icon = gtk_default_render_icon; + klass->draw_hline = gtk_default_draw_hline; klass->draw_vline = gtk_default_draw_vline; klass->draw_shadow = gtk_default_draw_shadow; @@ -521,7 +531,7 @@ gtk_style_duplicate (GtkStyle *style) { GtkStyle *new_style; - g_return_val_if_fail (style != NULL, NULL); + g_return_val_if_fail (GTK_IS_STYLE (style), NULL); new_style = gtk_style_copy (style); @@ -582,7 +592,7 @@ gtk_style_attach (GtkStyle *style, GtkStyle *new_style = NULL; GdkColormap *colormap; - g_return_val_if_fail (style != NULL, NULL); + g_return_val_if_fail (GTK_IS_STYLE (style), NULL); g_return_val_if_fail (window != NULL, NULL); colormap = gdk_window_get_colormap (window); @@ -632,7 +642,7 @@ gtk_style_attach (GtkStyle *style, void gtk_style_detach (GtkStyle *style) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); style->attach_count -= 1; if (style->attach_count == 0) @@ -659,7 +669,7 @@ static void gtk_style_realize (GtkStyle *style, GdkColormap *colormap) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); style->colormap = colormap; style->depth = gdk_colormap_get_visual (colormap)->depth; @@ -667,6 +677,31 @@ gtk_style_realize (GtkStyle *style, GTK_STYLE_GET_CLASS (style)->realize (style); } +GtkIconSet* +gtk_style_lookup_icon_set (GtkStyle *style, + const char *stock_id) +{ + GSList *iter; + + g_return_val_if_fail (GTK_IS_STYLE (style), NULL); + g_return_val_if_fail (stock_id != NULL, NULL); + + iter = style->icon_factories; + while (iter != NULL) + { + GtkIconSet *icon_set = + gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data), + stock_id); + + if (icon_set) + return icon_set; + + iter = g_slist_next (iter); + } + + return gtk_icon_factory_lookup_default (stock_id); +} + void gtk_draw_hline (GtkStyle *style, GdkWindow *window, @@ -675,7 +710,7 @@ gtk_draw_hline (GtkStyle *style, gint x2, gint y) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL); GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, NULL, NULL, NULL, x1, x2, y); @@ -690,7 +725,7 @@ gtk_draw_vline (GtkStyle *style, gint y2, gint x) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL); GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, NULL, NULL, NULL, y1, y2, x); @@ -707,7 +742,7 @@ gtk_draw_shadow (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL); GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -722,7 +757,7 @@ gtk_draw_polygon (GtkStyle *style, gint npoints, gboolean fill) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_polygon != NULL); GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, NULL, NULL, NULL, points, npoints, fill); @@ -740,7 +775,7 @@ gtk_draw_arrow (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL); GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, NULL, NULL, NULL, arrow_type, fill, x, y, width, height); @@ -757,7 +792,7 @@ gtk_draw_diamond (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL); GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -774,7 +809,7 @@ gtk_draw_oval (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_oval != NULL); GTK_STYLE_GET_CLASS (style)->draw_oval (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -788,7 +823,7 @@ gtk_draw_string (GtkStyle *style, gint y, const gchar *string) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL); GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, NULL, NULL, NULL, x, y, string); @@ -804,7 +839,7 @@ gtk_draw_box (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL); GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -820,7 +855,7 @@ gtk_draw_flat_box (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL); GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -836,7 +871,7 @@ gtk_draw_check (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL); GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -852,7 +887,7 @@ gtk_draw_option (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL); GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -868,7 +903,7 @@ gtk_draw_cross (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_cross != NULL); GTK_STYLE_GET_CLASS (style)->draw_cross (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -885,7 +920,7 @@ gtk_draw_ramp (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_ramp != NULL); GTK_STYLE_GET_CLASS (style)->draw_ramp (style, window, state_type, shadow_type, NULL, NULL, NULL, arrow_type, x, y, width, height); @@ -901,7 +936,7 @@ gtk_draw_tab (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL); GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); @@ -920,7 +955,7 @@ gtk_draw_shadow_gap (GtkStyle *style, gint gap_x, gint gap_width) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL); GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side, gap_x, gap_width); @@ -939,7 +974,7 @@ gtk_draw_box_gap (GtkStyle *style, gint gap_x, gint gap_width) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL); GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side, gap_x, gap_width); @@ -956,7 +991,7 @@ gtk_draw_extension (GtkStyle *style, gint height, GtkPositionType gap_side) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL); GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side); @@ -970,7 +1005,7 @@ gtk_draw_focus (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL); GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, NULL, NULL, NULL, x, y, width, height); @@ -987,7 +1022,7 @@ gtk_draw_slider (GtkStyle *style, gint height, GtkOrientation orientation) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL); GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation); @@ -1004,7 +1039,7 @@ gtk_draw_handle (GtkStyle *style, gint height, GtkOrientation orientation) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL); GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation); @@ -1015,7 +1050,7 @@ gtk_style_set_background (GtkStyle *style, GdkWindow *window, GtkStateType state_type) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type); @@ -1103,6 +1138,22 @@ gtk_style_real_init_from_rc (GtkStyle *style, style->xthickness = rc_style->xthickness; if (rc_style->ythickness >= 0) style->ythickness = rc_style->ythickness; + + + if (rc_style->icon_factories) + { + GSList *iter; + + style->icon_factories = g_slist_copy (rc_style->icon_factories); + + iter = style->icon_factories; + while (iter != NULL) + { + g_object_ref (G_OBJECT (iter->data)); + + iter = g_slist_next (iter); + } + } } static void @@ -1241,6 +1292,29 @@ gtk_style_real_set_background (GtkStyle *style, gdk_window_set_background (window, &style->bg[state_type]); } +GdkPixbuf * +gtk_style_render_icon (GtkStyle *style, + const GtkIconSource *source, + GtkTextDirection direction, + GtkStateType state, + const gchar *size, + GtkWidget *widget, + const gchar *detail) +{ + GdkPixbuf *pixbuf; + + g_return_val_if_fail (GTK_IS_STYLE (style), NULL); + g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL); + + pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state, + size, widget, detail); + + g_return_val_if_fail (pixbuf != NULL, NULL); + + return pixbuf; +} + +/* Default functions */ void gtk_style_apply_default_background (GtkStyle *style, GdkWindow *window, @@ -1305,6 +1379,92 @@ gtk_style_apply_default_background (GtkStyle *style, } } +static GdkPixbuf* +scale_or_ref (GdkPixbuf *src, + gint width, + gint height) +{ + if (width == gdk_pixbuf_get_width (src) && + height == gdk_pixbuf_get_height (src)) + { + gdk_pixbuf_ref (src); + return src; + } + else + { + return gdk_pixbuf_scale_simple (src, + width, height, + GDK_INTERP_BILINEAR); + } +} + +static GdkPixbuf * +gtk_default_render_icon (GtkStyle *style, + const GtkIconSource *source, + GtkTextDirection direction, + GtkStateType state, + const gchar *size, + GtkWidget *widget, + const gchar *detail) +{ + gint width = 1; + gint height = 1; + GdkPixbuf *scaled; + GdkPixbuf *stated; + + /* Oddly, style can be NULL in this function, because + * GtkIconSet can be used without a style and if so + * it uses this function. + */ + + g_return_val_if_fail (source->pixbuf != NULL, NULL); + + if (!gtk_icon_size_lookup (size, &width, &height)) + { + g_warning ("Bad icon size '%s' passed to render_icon", size); + return NULL; + } + + /* If the size was wildcarded, then scale; otherwise, leave it + * alone. + */ + if (source->any_size) + scaled = scale_or_ref (source->pixbuf, width, height); + else + scaled = GDK_PIXBUF (g_object_ref (G_OBJECT (source->pixbuf))); + + /* If the state was wildcarded, then generate a state. */ + if (source->any_state) + { + if (state == GTK_STATE_INSENSITIVE) + { + stated = gdk_pixbuf_copy (scaled); + + gdk_pixbuf_saturate_and_pixelate (scaled, stated, + 0.8, TRUE); + + gdk_pixbuf_unref (scaled); + } + else if (state == GTK_STATE_PRELIGHT) + { + stated = gdk_pixbuf_copy (scaled); + + gdk_pixbuf_saturate_and_pixelate (scaled, stated, + 1.2, FALSE); + + gdk_pixbuf_unref (scaled); + } + else + { + stated = scaled; + } + } + else + stated = scaled; + + return stated; +} + static void gtk_default_draw_hline (GtkStyle *style, GdkWindow *window, @@ -1320,7 +1480,7 @@ gtk_default_draw_hline (GtkStyle *style, gint thickness_dark; gint i; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); thickness_light = style->ythickness / 2; @@ -1377,7 +1537,7 @@ gtk_default_draw_vline (GtkStyle *style, gint thickness_dark; gint i; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); thickness_light = style->xthickness / 2; @@ -1427,7 +1587,7 @@ gtk_default_draw_shadow (GtkStyle *style, gint thickness_dark; gint i; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if ((width == -1) && (height == -1)) @@ -1606,7 +1766,7 @@ gtk_default_draw_polygon (GtkStyle *style, gint yadjust; gint i; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); g_return_if_fail (points != NULL); @@ -1740,7 +1900,7 @@ gtk_default_draw_arrow (GtkStyle *style, gint half_height; GdkPoint points[3]; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); switch (shadow_type) @@ -2086,7 +2246,7 @@ gtk_default_draw_diamond (GtkStyle *style, gint half_width; gint half_height; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if ((width == -1) && (height == -1)) @@ -2211,7 +2371,7 @@ gtk_default_draw_oval (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); g_warning ("gtk_default_draw_oval(): FIXME, this function is currently unimplemented"); @@ -2228,7 +2388,7 @@ gtk_default_draw_string (GtkStyle *style, gint y, const gchar *string) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if (area) @@ -2262,7 +2422,7 @@ gtk_default_draw_box (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if (width == -1 && height == -1) @@ -2307,7 +2467,7 @@ gtk_default_draw_flat_box (GtkStyle *style, { GdkGC *gc1; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if (width == -1 && height == -1) @@ -2400,7 +2560,7 @@ gtk_default_draw_cross (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); g_warning ("gtk_default_draw_cross(): FIXME, this function is currently unimplemented"); @@ -2420,7 +2580,7 @@ gtk_default_draw_ramp (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); g_warning ("gtk_default_draw_ramp(): FIXME, this function is currently unimplemented"); @@ -2439,7 +2599,7 @@ gtk_default_draw_tab (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); gtk_paint_box (style, window, state_type, shadow_type, area, widget, detail, @@ -2467,7 +2627,7 @@ gtk_default_draw_shadow_gap (GtkStyle *style, GdkGC *gc3 = NULL; GdkGC *gc4 = NULL; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if (width == -1 && height == -1) @@ -2688,7 +2848,7 @@ gtk_default_draw_box_gap (GtkStyle *style, GdkGC *gc3 = NULL; GdkGC *gc4 = NULL; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); gtk_style_apply_default_background (style, window, @@ -2912,7 +3072,7 @@ gtk_default_draw_extension (GtkStyle *style, GdkGC *gc3 = NULL; GdkGC *gc4 = NULL; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); gtk_style_apply_default_background (style, window, @@ -3084,7 +3244,7 @@ gtk_default_draw_focus (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if (width == -1 && height == -1) @@ -3143,7 +3303,7 @@ gtk_default_draw_slider (GtkStyle *style, gint height, GtkOrientation orientation) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if (width == -1 && height == -1) @@ -3214,7 +3374,7 @@ gtk_default_draw_handle (GtkStyle *style, GdkRectangle dest; gint intersect; - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); if (width == -1 && height == -1) @@ -3488,7 +3648,7 @@ gtk_paint_hline (GtkStyle *style, gint x2, gint y) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL); GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, area, widget, detail, x1, x2, y); @@ -3505,7 +3665,7 @@ gtk_paint_vline (GtkStyle *style, gint y2, gint x) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL); GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, area, widget, detail, y1, y2, x); @@ -3524,7 +3684,7 @@ gtk_paint_shadow (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL); GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3542,7 +3702,7 @@ gtk_paint_polygon (GtkStyle *style, gint npoints, gboolean fill) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL); GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, area, widget, detail, points, npoints, fill); @@ -3563,7 +3723,7 @@ gtk_paint_arrow (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL); GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height); @@ -3582,7 +3742,7 @@ gtk_paint_diamond (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL); GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3601,7 +3761,7 @@ gtk_paint_oval (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_oval != NULL); GTK_STYLE_GET_CLASS (style)->draw_oval (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3618,7 +3778,7 @@ gtk_paint_string (GtkStyle *style, gint y, const gchar *string) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL); GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, area, widget, detail, x, y, string); @@ -3637,7 +3797,7 @@ gtk_paint_box (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL); GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3656,7 +3816,7 @@ gtk_paint_flat_box (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL); GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3675,7 +3835,7 @@ gtk_paint_check (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL); GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3694,7 +3854,7 @@ gtk_paint_option (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL); GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3713,7 +3873,7 @@ gtk_paint_cross (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_cross != NULL); GTK_STYLE_GET_CLASS (style)->draw_cross (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3733,7 +3893,7 @@ gtk_paint_ramp (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_ramp != NULL); GTK_STYLE_GET_CLASS (style)->draw_ramp (style, window, state_type, shadow_type, area, widget, detail, arrow_type, x, y, width, height); @@ -3752,7 +3912,7 @@ gtk_paint_tab (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL); GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); @@ -3774,7 +3934,7 @@ gtk_paint_shadow_gap (GtkStyle *style, gint gap_x, gint gap_width) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL); GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side, gap_x, gap_width); @@ -3797,7 +3957,7 @@ gtk_paint_box_gap (GtkStyle *style, gint gap_x, gint gap_width) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL); GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side, gap_x, gap_width); @@ -3817,7 +3977,7 @@ gtk_paint_extension (GtkStyle *style, gint height, GtkPositionType gap_side) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL); GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side); @@ -3834,7 +3994,7 @@ gtk_paint_focus (GtkStyle *style, gint width, gint height) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL); GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, area, widget, detail, x, y, width, height); @@ -3854,7 +4014,7 @@ gtk_paint_slider (GtkStyle *style, gint height, GtkOrientation orientation) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL); GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation); @@ -3874,7 +4034,7 @@ gtk_paint_handle (GtkStyle *style, gint height, GtkOrientation orientation) { - g_return_if_fail (style != NULL); + g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL); GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation); diff --git a/gtk/gtkstyle.h b/gtk/gtkstyle.h index e23203a1c..842712730 100644 --- a/gtk/gtkstyle.h +++ b/gtk/gtkstyle.h @@ -51,7 +51,8 @@ typedef struct _GtkStyleClass GtkStyleClass; */ typedef struct _GtkThemeEngine GtkThemeEngine; typedef struct _GtkRcStyle GtkRcStyle; - +typedef struct _GtkIconSet GtkIconSet; +typedef struct _GtkIconSource GtkIconSource; /* We make this forward declaration here, since we pass * GtkWidgt's to the draw functions. @@ -110,6 +111,8 @@ struct _GtkStyle * was created */ GSList *styles; + + GSList *icon_factories; }; struct _GtkStyleClass @@ -149,8 +152,18 @@ struct _GtkStyleClass GdkWindow *window, GtkStateType state_type); + + GdkPixbuf * (* render_icon) (GtkStyle *style, + const GtkIconSource *source, + GtkTextDirection direction, + GtkStateType state, + const gchar *size, + GtkWidget *widget, + const gchar *detail); + /* Drawing functions */ + void (*draw_hline) (GtkStyle *style, GdkWindow *window, GtkStateType state_type, @@ -408,6 +421,15 @@ void gtk_style_apply_default_background (GtkStyle *style, gint width, gint height); +GtkIconSet* gtk_style_lookup_icon_set (GtkStyle *style, + const gchar *stock_id); +GdkPixbuf * gtk_style_render_icon (GtkStyle *style, + const GtkIconSource *source, + GtkTextDirection direction, + GtkStateType state, + const gchar * size, + GtkWidget *widget, + const gchar *detail); void gtk_draw_hline (GtkStyle *style, GdkWindow *window, GtkStateType state_type, @@ -815,6 +837,7 @@ void gtk_paint_handle (GtkStyle *style, gint height, GtkOrientation orientation); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index bd084de24..ed19d79e4 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -28,6 +28,7 @@ #include #include #include "gtkcontainer.h" +#include "gtkiconfactory.h" #include "gtkmain.h" #include "gtkrc.h" #include "gtkselection.h" @@ -3541,6 +3542,37 @@ gtk_widget_create_pango_layout (GtkWidget *widget, return layout; } +GdkPixbuf* +gtk_widget_render_stock_icon (GtkWidget *widget, + const gchar *stock_id, + const gchar *size, + const gchar *detail) +{ + GtkIconSet *icon_set; + GdkPixbuf *retval; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + g_return_val_if_fail (stock_id != NULL, NULL); + g_return_val_if_fail (size != NULL, NULL); + + gtk_widget_ensure_style (widget); + + icon_set = gtk_style_lookup_icon_set (widget->style, stock_id); + + if (icon_set == NULL) + return NULL; + + retval = gtk_icon_set_render_icon (icon_set, + widget->style, + gtk_widget_get_direction (widget), + GTK_WIDGET_STATE (widget), + size, + widget, + detail); + + return retval; +} + /************************************************************* * gtk_widget_set_parent_window: * Set a non default parent window for widget diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index 4e2a87e7f..b55a2a1b9 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -606,6 +606,11 @@ PangoContext *gtk_widget_get_pango_context (GtkWidget *widget); PangoLayout *gtk_widget_create_pango_layout (GtkWidget *widget, const gchar *text); +GdkPixbuf* gtk_widget_render_stock_icon (GtkWidget *widget, + const gchar *stock_id, + const gchar *size, + const gchar *detail); + /* handle composite names for GTK_COMPOSITE_CHILD widgets, * the returned name is newly allocated. */ diff --git a/gtk/stock-icons/Makefile.am b/gtk/stock-icons/Makefile.am new file mode 100644 index 000000000..3bf0d5074 --- /dev/null +++ b/gtk/stock-icons/Makefile.am @@ -0,0 +1,23 @@ +BUILT_SOURCES=gtkstockpixbufs.h + +IMAGES= dialog_error.png dialog_info.png dialog_question.png dialog_warning.png stock_button_apply.png stock_button_cancel.png stock_button_close.png stock_button_no.png stock_button_ok.png stock_button_yes.png stock_close.png stock_exit.png stock_help.png stock_new.png stock_open.png stock_save.png + +VARIABLES= dialog_error dialog_error.png \ + dialog_info dialog_info.png \ + dialog_question dialog_question.png \ + dialog_warning dialog_warning.png \ + stock_button_apply stock_button_apply.png \ + stock_button_cancel stock_button_cancel.png \ + stock_button_close stock_button_close.png \ + stock_button_no stock_button_no.png \ + stock_button_ok stock_button_ok.png \ + stock_button_yes stock_button_yes.png \ + stock_close stock_close.png \ + stock_exit stock_exit.png \ + stock_help stock_help.png \ + stock_new stock_new.png \ + stock_open stock_open.png \ + stock_save stock_save.png + +gtkstockpixbufs.h: $(top_builddir)/gdk-pixbuf/make-inline-pixbuf $(IMAGES) + GDK_PIXBUF_MODULEDIR=$(top_builddir)/gdk-pixbuf/.libs $(top_builddir)/gdk-pixbuf/make-inline-pixbuf gtkstockpixbufs.h $(VARIABLES) diff --git a/gtk/stock-icons/dialog_error.png b/gtk/stock-icons/dialog_error.png new file mode 100644 index 0000000000000000000000000000000000000000..cc7830e26ef2b67b23587061997543e4eeadeb21 GIT binary patch literal 2684 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 M07*qoM6N<$f=zj6oB#j- literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/dialog_question_48.png b/gtk/stock-icons/dialog_question_48.png new file mode 100644 index 0000000000000000000000000000000000000000..2afbc7a873daec85ffaa08bab8817f8b8b9d08e4 GIT binary patch literal 1302 zcmV+x1?l>UP)Qnz#zQTj~I0m z(~uZZUo04+B*f6N+r&4iCM3oOfHhW&dr2A;8 z#=hW6X8R=O7w2>G>=1blkw2~|eE4}sy8kP{*Jey?h5!xVeE3C5mpqrWxJqGEM!tGg zcj}YR(|_$cbvu4YjrkPVobBY<3eW(?PSk-v0L}tXFF;&{X#13xyBv9N62^LI|Lr2D zItJJk?lOgg-RMA%$6c$cu_^MCqi`wAq1GM-Z`=Z4PGKG|tnx#wo6=e3$k)6qU$y{1 z7ht#BSH|P`N(=?}D?^pBoOBKlrrw_URCIDX@ zZYQ)Sxi7q4Z<(SfmyM7RjSTX5+=~EeDqY}N2$8l7^5U~qtKM)3qHW!~&8PXfd-9He z0vL}1P+98L?-z^3mK)(=Sb(a=I`@AZfc#Pzk0N*fI*okw`i;k5UHb$(8XH;xUX~P049{1eSo+1xuf*|Pc2gW1Fktu#X*GKfWAP9p-c^J+@ ze<^vyhh_SD2QpVPMM?vz0ZNPA;G6+=4=5e9cMh}rP`B>e(9m$uC=bH|%Aeo!Aa1L7 zZhjK4+lf3<3}Y7nINcf19Rxvq$0!Fd9zqN5Wpqleg=v@7z|JL=J}S!RCoSVq`UXb% z%FP2oMMaria`E!srvY1lWSX;5`>WlB6|2%Qwx>uzJN}+1)rs;W}O-b2IiCI%8sO-+eRV<;3#+`fIg1z_EZl4PnK>j%L_>zPQJrw}eI zEchLauRfSpji%%E`oO}yuhlN4xMB^7*d?MdfzgpM>bCCZ+Mo*XZBbFtTdCC#1Of@8 z0t|2Bf52YNkX_cvge6a)e`tjMprhLQq*Ydgjuo+}T|By#5}ykkGx@Rg zyYvFiv;(aaEXhJ8J{RQ8OSWgbbh{{uixP>u>c6aD$$J3DOo*$<7ux6>7)|dH%+5mA z2!Q0VV#eu%6|h9WpJ$K3ghJoID2H2n(z}N5GsG~g*aO1Sx+9M)RazB7Wtj#+5H~e8 zHtsfiB1^Ima2c>klJs=Sux;D6HY+Bwx+W3RKm5)5h{+*`9R5f68%_|?=3mMMKL7v# M07*qoM6N<$f=zj6oB#j- literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/dialog_warning.png b/gtk/stock-icons/dialog_warning.png new file mode 100644 index 0000000000000000000000000000000000000000..d6f2306dba4ece5c3880ef9e0f4ad3eb0c438bff GIT binary patch literal 1968 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 literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_button_cancel_24.png b/gtk/stock-icons/stock_button_cancel_24.png new file mode 100644 index 0000000000000000000000000000000000000000..2d7c194c8cf58b8f0cda70f2a5a3fb6d8731b97c GIT binary patch literal 454 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VTavfC3&UOz%yhcC0x0s@)5S5Q z;?~>qAzb+ z>%@!OI6atVF&((D^vofSrtlqh?%xJUi4_+UG-77USXr{U4ZTm7OcNRoU=&Q?|p&M=l2^%~>h5Gh;*S+U3@3 zx`Ub-72YP^h~sBSuzNANVcFdj-5Ncq%ddY%t>b?z{*{gGMp{Gejn*qbZ@X57M3e;Q zrsR+eb2 zJEQBNbJFMB_0#%Z>&ArUbJWPx{7#TWLI08kcoVNyQXYh3Ob6Mw<&;$S@j<@^( literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_button_close.png b/gtk/stock-icons/stock_button_close.png new file mode 100644 index 0000000000000000000000000000000000000000..b900bdf3bd5be9bcb1001726e8a1678883dcc49c GIT binary patch literal 286 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc0wmQNuC@UwrX+877lys^v2U1xJaF! zcl!?VG8k|$9sOIrY`t0666O=DANu7UxwT=>jlig>MrJN1Jg)zC2#Bt?`o$xk)!2Vw z#%&H`73rT+QF;8u|B8M2P9G9vx%=<>I-rrRRUr{2!TD(=<%vb93=9>wiZ29Q`*OzD z$N#IZ&v~D7VFnkCFBk`I*mA+#;G(%fh=<-O9lez$8tcyJdgz?=Id}cEz85<~O&0&p zifODrjcm}qQZ=Cj$r)62-u%oj+S8Txpd8Jc;R7 literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_button_close_24.png b/gtk/stock-icons/stock_button_close_24.png new file mode 100644 index 0000000000000000000000000000000000000000..b900bdf3bd5be9bcb1001726e8a1678883dcc49c GIT binary patch literal 286 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc0wmQNuC@UwrX+877lys^v2U1xJaF! zcl!?VG8k|$9sOIrY`t0666O=DANu7UxwT=>jlig>MrJN1Jg)zC2#Bt?`o$xk)!2Vw z#%&H`73rT+QF;8u|B8M2P9G9vx%=<>I-rrRRUr{2!TD(=<%vb93=9>wiZ29Q`*OzD z$N#IZ&v~D7VFnkCFBk`I*mA+#;G(%fh=<-O9lez$8tcyJdgz?=Id}cEz85<~O&0&p zifODrjcm}qQZ=Cj$r)62-u%oj+S8Txpd8Jc;R7 literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_button_no.png b/gtk/stock-icons/stock_button_no.png new file mode 100644 index 0000000000000000000000000000000000000000..6478554f620d324d4fe829189b0a0d761aaef745 GIT binary patch literal 847 zcmV-V1F-ywP)PRHmIs7LTRc%R9aFycI=Po}ze9YI6_K45OJ@sge5xHDW zzrXf0A6$8rT-GItBK%I9QGcJXe?Tt^X>ILrt9vjOYCjp|^Z6e>S$~~t>u=&#W-vM> z?DkM;N*V?LIGGF^iw%mF;H&n)oP-_$ZQC~QK6{aCZ?98YS;Z+#k_G`Pig9utD2YH} zD~W~TrI|9lFyco)J_gMkUM5|akKedLq23@jJwvh4BwH?HdmdE60Ibp2_i`$kz|y_Rfd;~SpahgJ}UWz z#RY_Ik&Z@$oi@p!PuSffc=V8XFhq?;7^TogB7_31F%uR~RVKMLj7U!cYlR%q!2y}h zE}3oy9Vf)Y0pad0VXsXR`ba6!S|d|U#`P#oSIOHB?6gleW&3fPLUkG`H7H3s3P}AS z(SDDh(Ua^2zuHa3TaSKKKexK{#e9MjdJACxqGvd?RzZ^>* zyDPRHmIs7LTRc%R9aFycI=Po}ze9YI6_K45OJ@sge5xHDW zzrXf0A6$8rT-GItBK%I9QGcJXe?Tt^X>ILrt9vjOYCjp|^Z6e>S$~~t>u=&#W-vM> z?DkM;N*V?LIGGF^iw%mF;H&n)oP-_$ZQC~QK6{aCZ?98YS;Z+#k_G`Pig9utD2YH} zD~W~TrI|9lFyco)J_gMkUM5|akKedLq23@jJwvh4BwH?HdmdE60Ibp2_i`$kz|y_Rfd;~SpahgJ}UWz z#RY_Ik&Z@$oi@p!PuSffc=V8XFhq?;7^TogB7_31F%uR~RVKMLj7U!cYlR%q!2y}h zE}3oy9Vf)Y0pad0VXsXR`ba6!S|d|U#`P#oSIOHB?6gleW&3fPLUkG`H7H3s3P}AS z(SDDh(Ua^2zuHa3TaSKKKexK{#e9MjdJACxqGvd?RzZ^>* zyDw% z3phItqf{ze-$*m8Tq@)0Jc>k2{!AnU{tiDlLf~ujp;Hvl7wAEEZx>cq*0H^@i=u82 z(ugJR6;Mj;WpG@>o}gBH#a&!R_$-QxlPmj=UB{G%6l%3sd>57H3Z&~8l5z@{rx6PS z0B;@3C|OX-zQyu69dRjvw4x$>er>~SHyoZA!uZrMd~ME;M@?&pNeO5f4UtRf3uYTi z9Su#7z~lAUk{D&ksyRrJTc~LbH_>=gtm%}4qk{;|jDj(Wr+fj7QWSIpX+=dY``8lu z0@l&7$sj0W*xNY(=dn+?73LU%$g{!V0BiO9eue%U_Lq1A;R4_$te|I)0000*dQ@0+ zQ*UN;cVTj6004N}bI?%M^vq36PxVbq&rHr%Fwry6Gf}X#&^IvAH!xI4F3Kz}sdOl= z%q>VP$xP1I%P&d?0DNi>`FQpe!T?(ZeetFa%BJjc-k{hO-nX3GB-*y vF)*?;F}F0gG&D|1Niw!fPDx5hGd2MLjF$+_I&sfb00000NkvXXu0mjf#^f6W literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_button_ok_24.png b/gtk/stock-icons/stock_button_ok_24.png new file mode 100644 index 0000000000000000000000000000000000000000..f1c33753f369e410d8e7fd3a03f5d1612a101efa GIT binary patch literal 661 zcmV;G0&4ww% z3phItqf{ze-$*m8Tq@)0Jc>k2{!AnU{tiDlLf~ujp;Hvl7wAEEZx>cq*0H^@i=u82 z(ugJR6;Mj;WpG@>o}gBH#a&!R_$-QxlPmj=UB{G%6l%3sd>57H3Z&~8l5z@{rx6PS z0B;@3C|OX-zQyu69dRjvw4x$>er>~SHyoZA!uZrMd~ME;M@?&pNeO5f4UtRf3uYTi z9Su#7z~lAUk{D&ksyRrJTc~LbH_>=gtm%}4qk{;|jDj(Wr+fj7QWSIpX+=dY``8lu z0@l&7$sj0W*xNY(=dn+?73LU%$g{!V0BiO9eue%U_Lq1A;R4_$te|I)0000*dQ@0+ zQ*UN;cVTj6004N}bI?%M^vq36PxVbq&rHr%Fwry6Gf}X#&^IvAH!xI4F3Kz}sdOl= z%q>VP$xP1I%P&d?0DNi>`FQpe!T?(ZeetFa%BJjc-k{hO-nX3GB-*y vF)*?;F}F0gG&D|1Niw!fPDx5hGd2MLjF$+_I&sfb00000NkvXXu0mjf#^f6W literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_button_yes.png b/gtk/stock-icons/stock_button_yes.png new file mode 100644 index 0000000000000000000000000000000000000000..e061e7f17cc9d1d12ee7aaf40c24c14a1b29e289 GIT binary patch literal 806 zcmV+>1KIqEP)1uc)!u_0+o|I?PTI6lQA&jp1Ojf5K+s0&1@wX& z{sI4w-n0!+6(po0N>iv%icABfN~n`KKJD)8&Vh^2l9Gi>BwlHxnUUT{?>FD*ga1m# z7z;23>tAIRfn3+sr+k-J-hYWRmpW8t0-ikHVe7#*-LJM$nJM(1xHQICzVGX|K6sVO zAH74VTt;Lm`@=nk@gbARh{55Q@7Evk+c!@Oq3-cR7>0MQeX_>dhnJ}Z4WyO~CVg_1 zljM^lgXeJR-E(-M!_T*O%-^BUfv)SC*RQUycI^rajYXnTg*1!FWrkn!(MBOHg|Rit zGAyjNh!10S?+;#p+RrvYrOefj-(#jaOFf*XHPt5arzm+xFk=~{$x*gEf@;P5Yb|W| z#j2kH&FYnxX;d5do{#5vcwPz5J%!Q|WfV#&q{%Tz3=(ZAT+d>5wFbw!|2*M^m2+5@ zLz<-=jQ9AZ*JXSEF}>j~aXLoG6s9tmZ^kw>?xNGx+j4MX_AoX43Q@c(;*^@8H))*WN4{zEsuJ+$-?wm zszHr!yY~x$*2c|Ev;5`-q9{OWiBJNm1aX!ka|yY@!Q*t;qFtS5y3(XS==1gUdlY^f zDHL~ae8)k*PdtthaYhnns8pjejb}=2mzb%|BC?blpWY%D60hW*NC;s4^yRN6 zsQAn;&tfctWrJmG%67=n8*M+`;-ZeCyKhc6x#`U@upU>wip;@e9sEuW{;=`bFS*?hRky;~3YGtobJ ki{*GW6wJfp@Ad!GAD5tKxAlTf%m4rY07*qoM6N<$g18WaeE1KIqEP)1uc)!u_0+o|I?PTI6lQA&jp1Ojf5K+s0&1@wX& z{sI4w-n0!+6(po0N>iv%icABfN~n`KKJD)8&Vh^2l9Gi>BwlHxnUUT{?>FD*ga1m# z7z;23>tAIRfn3+sr+k-J-hYWRmpW8t0-ikHVe7#*-LJM$nJM(1xHQICzVGX|K6sVO zAH74VTt;Lm`@=nk@gbARh{55Q@7Evk+c!@Oq3-cR7>0MQeX_>dhnJ}Z4WyO~CVg_1 zljM^lgXeJR-E(-M!_T*O%-^BUfv)SC*RQUycI^rajYXnTg*1!FWrkn!(MBOHg|Rit zGAyjNh!10S?+;#p+RrvYrOefj-(#jaOFf*XHPt5arzm+xFk=~{$x*gEf@;P5Yb|W| z#j2kH&FYnxX;d5do{#5vcwPz5J%!Q|WfV#&q{%Tz3=(ZAT+d>5wFbw!|2*M^m2+5@ zLz<-=jQ9AZ*JXSEF}>j~aXLoG6s9tmZ^kw>?xNGx+j4MX_AoX43Q@c(;*^@8H))*WN4{zEsuJ+$-?wm zszHr!yY~x$*2c|Ev;5`-q9{OWiBJNm1aX!ka|yY@!Q*t;qFtS5y3(XS==1gUdlY^f zDHL~ae8)k*PdtthaYhnns8pjejb}=2mzb%|BC?blpWY%D60hW*NC;s4^yRN6 zsQAn;&tfctWrJmG%67=n8*M+`;-ZeCyKhc6x#`U@upU>wip;@e9sEuW{;=`bFS*?hRky;~3YGtobJ ki{*GW6wJfp@Ad!GAD5tKxAlTf%m4rY07*qoM6N<$g18WaeE>qAzb+ z>%@!OI6atVF&((D^vofSrtlqh?%xJUi4_+UG-77USXr{U4ZTm7OcNRoU=&Q?|p&M=l2^%~>h5Gh;*S+U3@3 zx`Ub-72YP^h~sBSuzNANVcFdj-5Ncq%ddY%t>b?z{*{gGMp{Gejn*qbZ@X57M3e;Q zrsR+eb2 zJEQBNbJFMB_0#%Z>&ArUbJWPx{7#TWLI08kcoVNyQXYh3Ob6Mw<&;$S@j<@^( literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_close.png b/gtk/stock-icons/stock_close.png new file mode 100644 index 0000000000000000000000000000000000000000..4338bdc3f67d63af7de8272f44e182aef9bf7ef8 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1rX+877lys^v2U1xJa11I$B>F! zZ~He2F&MBozx@Bdcvnzo_HsQV%Q%6}7k3M286wiZ29Q z`*OzD$N#IZ&v~D7VFnkCFBk`I*mA+#;G(%fh=<-O9lez$8tcyJdgz?=Id}cEz85<~ zO&0&pifODrjcm}u-{xY@+m)X>b>+t}aG)YH_<#N5Qt$JE%s$H&;f b+?<7>g@uDF! zcl!?VG8k|$9sOIrY`t0666O=DANu7UxwT=>jlig>MrJN1Jg)zC2#Bt?`o$xk)!2Vw z#%&H`73rT+QF;8u|B8M2P9G9vx%=<>I-rrRRUr{2!TD(=<%vb93=9>wiZ29Q`*OzD z$N#IZ&v~D7VFnkCFBk`I*mA+#;G(%fh=<-O9lez$8tcyJdgz?=Id}cEz85<~O&0&p zifODrjcm}qQZ=Cj$r)62-u%oj+S8Txpd8Jc;R7 literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_close_24.png b/gtk/stock-icons/stock_close_24.png new file mode 100644 index 0000000000000000000000000000000000000000..4338bdc3f67d63af7de8272f44e182aef9bf7ef8 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1rX+877lys^v2U1xJa11I$B>F! zZ~He2F&MBozx@Bdcvnzo_HsQV%Q%6}7k3M286wiZ29Q z`*OzD$N#IZ&v~D7VFnkCFBk`I*mA+#;G(%fh=<-O9lez$8tcyJdgz?=Id}cEz85<~ zO&0&pifODrjcm}u-{xY@+m)X>b>+t}aG)YH_<#N5Qt$JE%s$H&;f b+?<7>g@uDE1R|xn~>y3l7*qhKpIgDs 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 M07*qoM6N<$f=zj6oB#j- literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_dialog_warning_48.png b/gtk/stock-icons/stock_dialog_warning_48.png new file mode 100644 index 0000000000000000000000000000000000000000..d6f2306dba4ece5c3880ef9e0f4ad3eb0c438bff GIT binary patch literal 1968 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 literal 0 HcmV?d00001 diff --git a/gtk/stock-icons/stock_open.png b/gtk/stock-icons/stock_open.png new file mode 100644 index 0000000000000000000000000000000000000000..e966ad7bf84d935f6a26c974d5e16607ef3ab595 GIT binary patch literal 393 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