diff options
author | Havoc Pennington <hp@redhat.com> | 2001-04-18 18:09:18 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2001-04-18 18:09:18 +0000 |
commit | 60b6a010e931aaaf97d723c893068381a421f0a0 (patch) | |
tree | 14982e448c4281c77bdfb5cd17add1a61fe72fce | |
parent | ebd3958c0641d82b54f26118155e4669725900e2 (diff) | |
download | gtk+-60b6a010e931aaaf97d723c893068381a421f0a0.tar.gz |
fix to properly queue resizes when the image is set
2001-04-18 Havoc Pennington <hp@redhat.com>
* gtk/gtkimage.c: fix to properly queue resizes when the image is
set
* gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste
if the insertion point isn't editable
* demos/gtk-demo/images.c: Added a GtkImage demo
* demos/gtk-demo/drawingarea.c: drawing area demo
* demos/gtk-demo/menus.c (create_menu): cleanups
2001-04-18 Havoc Pennington <hp@redhat.com>
* gdk-pixbuf.c (gdk_pixbuf_fill): Function to fill pixbuf with a
given color.
33 files changed, 1274 insertions, 53 deletions
@@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington <hp@redhat.com> + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington <hp@redhat.com> + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington <hp@redhat.com> + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington <hp@redhat.com> + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington <hp@redhat.com> + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington <hp@redhat.com> + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 1d1b3753e2..b984620d1e 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,17 @@ +2001-04-18 Havoc Pennington <hp@redhat.com> + + * gtk/gtkimage.c: fix to properly queue resizes when the image is + set + + * gtk/gtktextview.c (gtk_text_view_do_popup): desensitize Paste + if the insertion point isn't editable + + * demos/gtk-demo/images.c: Added a GtkImage demo + + * demos/gtk-demo/drawingarea.c: drawing area demo + + * demos/gtk-demo/menus.c (create_menu): cleanups + Wed Apr 18 12:15:52 2001 Owen Taylor <otaylor@redhat.com> * gdk/x11/gdkwindow-x11.c gdk/x11/gdkwindow-x11.h diff --git a/demos/gtk-demo/Makefile.am b/demos/gtk-demo/Makefile.am index 6fa87fac72..b581f51e14 100644 --- a/demos/gtk-demo/Makefile.am +++ b/demos/gtk-demo/Makefile.am @@ -2,12 +2,17 @@ democodedir=$(datadir)/gtk-2.0/demo +## These should be in the order you want them to appear in the +## demo app, which means alphabetized by demo title, not filename demos = @STRIP_BEGIN@ \ button_box.c \ + dialog.c \ + drawingarea.c \ + images.c \ item_factory.c \ menus.c \ panes.c \ - dialog.c \ + pixbufs.c \ textview.c \ @STRIP_END@ @@ -63,4 +68,17 @@ gtk_demo_SOURCES = \ gtk_demo_DEPENDENCIES = $(DEPS) gtk_demo_LDADD = $(LDADDS) -democode_DATA = $(demos) +IMAGEFILES= apple-red.png \ + background.jpg \ + gnome-applets.png \ + gnome-calendar.png \ + gnome-foot.png \ + gnome-gimp.png \ + gnome-gmush.png \ + gnome-gsame.png \ + gnu-keys.png \ + gtk-logo-rgb.gif + +democode_DATA = $(demos) $(IMAGEFILES) + +EXTRA_DIST = $(IMAGEFILES) diff --git a/demos/gtk-demo/apple-red.png b/demos/gtk-demo/apple-red.png Binary files differnew file mode 100644 index 0000000000..b0a24e9418 --- /dev/null +++ b/demos/gtk-demo/apple-red.png diff --git a/demos/gtk-demo/background.jpg b/demos/gtk-demo/background.jpg Binary files differnew file mode 100644 index 0000000000..86c006aa46 --- /dev/null +++ b/demos/gtk-demo/background.jpg diff --git a/demos/gtk-demo/button_box.c b/demos/gtk-demo/button_box.c index a0fae11226..f8e7bd3838 100644 --- a/demos/gtk-demo/button_box.c +++ b/demos/gtk-demo/button_box.c @@ -72,19 +72,19 @@ do_button_box (void) gtk_container_add (GTK_CONTAINER (frame_horz), vbox); gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Spread", 40, GTK_BUTTONBOX_SPREAD), + create_bbox (TRUE, "Spread", 40, GTK_BUTTONBOX_SPREAD), TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Edge", 40, GTK_BUTTONBOX_EDGE), + create_bbox (TRUE, "Edge", 40, GTK_BUTTONBOX_EDGE), TRUE, TRUE, 5); - + gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Start", 40, GTK_BUTTONBOX_START), + create_bbox (TRUE, "Start", 40, GTK_BUTTONBOX_START), TRUE, TRUE, 5); - + gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "End", 40, GTK_BUTTONBOX_END), + create_bbox (TRUE, "End", 40, GTK_BUTTONBOX_END), TRUE, TRUE, 5); frame_vert = gtk_frame_new ("Vertical Button Boxes"); @@ -95,19 +95,19 @@ do_button_box (void) gtk_container_add (GTK_CONTAINER (frame_vert), hbox); gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Spread", 30, GTK_BUTTONBOX_SPREAD), + create_bbox (FALSE, "Spread", 30, GTK_BUTTONBOX_SPREAD), TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Edge", 30, GTK_BUTTONBOX_EDGE), + create_bbox (FALSE, "Edge", 30, GTK_BUTTONBOX_EDGE), TRUE, TRUE, 5); gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Start", 30, GTK_BUTTONBOX_START), + create_bbox (FALSE, "Start", 30, GTK_BUTTONBOX_START), TRUE, TRUE, 5); gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "End", 30, GTK_BUTTONBOX_END), + create_bbox (FALSE, "End", 30, GTK_BUTTONBOX_END), TRUE, TRUE, 5); } diff --git a/demos/gtk-demo/drawingarea.c b/demos/gtk-demo/drawingarea.c new file mode 100644 index 0000000000..101b159730 --- /dev/null +++ b/demos/gtk-demo/drawingarea.c @@ -0,0 +1,322 @@ +/* Drawing Area + * + * GtkDrawingArea is a blank area where you can draw custom displays + * of various kinds. + * + * This demo has two drawing areas. The checkerboard area shows + * how you can just draw something; all you have to do is write + * a signal handler for expose_event, as shown here. + * + * The "scribble" area is a bit more advanced, and shows how to handle + * events such as button presses and mouse motion. Click the mouse + * and drag in the scribble area to draw squiggles. Resize the window + * to clear the area. + */ + +#include <gtk/gtk.h> + +static GtkWidget *window = NULL; +/* Pixmap for scribble area, to store current scribbles */ +static GdkPixmap *pixmap = NULL; + +/* Create a new pixmap of the appropriate size to store our scribbles */ +static gboolean +scribble_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer data) +{ + if (pixmap) + g_object_unref (G_OBJECT (pixmap)); + + pixmap = gdk_pixmap_new (widget->window, + widget->allocation.width, + widget->allocation.height, + -1); + + /* Initialize the pixmap to white */ + gdk_draw_rectangle (pixmap, + widget->style->white_gc, + TRUE, + 0, 0, + widget->allocation.width, + widget->allocation.height); + + /* We've handled the configure event, no need for further processing. */ + return TRUE; +} + +/* Redraw the screen from the pixmap */ +static gboolean +scribble_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ + /* We use the "foreground GC" for the widget since it already exists, + * but honestly any GC would work. The only thing to worry about + * is whether the GC has an inappropriate clip region set. + */ + + gdk_draw_drawable (widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + pixmap, + /* Only copy the area that was exposed. */ + event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + + return FALSE; +} + +/* Draw a rectangle on the screen */ +static void +draw_brush (GtkWidget *widget, + gdouble x, + gdouble y) +{ + GdkRectangle update_rect; + + update_rect.x = x - 3; + update_rect.y = y - 3; + update_rect.width = 6; + update_rect.height = 6; + + /* Paint to the pixmap, where we store our state */ + gdk_draw_rectangle (pixmap, + widget->style->black_gc, + TRUE, + update_rect.x, update_rect.y, + update_rect.width, update_rect.height); + + /* Now invalidate the affected region of the drawing area. */ + gdk_window_invalidate_rect (widget->window, + &update_rect, + FALSE); +} + +static gboolean +scribble_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + if (pixmap == NULL) + return FALSE; /* paranoia check, in case we haven't gotten a configure event */ + + if (event->button == 1) + draw_brush (widget, event->x, event->y); + + /* We've handled the event, stop processing */ + return TRUE; +} + +static gboolean +scribble_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer data) +{ + int x, y; + GdkModifierType state; + + if (pixmap == NULL) + return FALSE; /* paranoia check, in case we haven't gotten a configure event */ + + /* This call is very important; it requests the next motion event. + * If you don't call gdk_window_get_pointer() you'll only get + * a single motion event. The reason is that we specified + * GDK_POINTER_MOTION_HINT_MASK to gtk_widget_set_events(). + * If we hadn't specified that, we could just use event->x, event->y + * as the pointer location. But we'd also get deluged in events. + * By requesting the next event as we handle the current one, + * we avoid getting a huge number of events faster than we + * can cope. + */ + + gdk_window_get_pointer (event->window, &x, &y, &state); + + if (state & GDK_BUTTON1_MASK) + draw_brush (widget, x, y); + + /* We've handled it, stop processing */ + return TRUE; +} + + +static gboolean +checkerboard_expose (GtkWidget *da, + GdkEventExpose *event, + gpointer data) +{ + gint i, j, xcount, ycount; + GdkGC *gc1, *gc2; + GdkColor color; + +#define CHECK_SIZE 10 +#define SPACING 2 + + /* At the start of an expose handler, a clip region of event->area + * is set on the window, and event->area has been cleared to the + * widget's background color. The docs for + * gdk_window_begin_paint_region() give more details on how this + * works. + */ + + /* It would be a bit more efficient to keep these + * GC's around instead of recreating on each expose, but + * this is the lazy/slow way. + */ + gc1 = gdk_gc_new (da->window); + color.red = 30000; + color.green = 0; + color.blue = 30000; + gdk_gc_set_rgb_fg_color (gc1, &color); + + gc2 = gdk_gc_new (da->window); + color.red = 65535; + color.green = 65535; + color.blue = 65535; + gdk_gc_set_rgb_fg_color (gc2, &color); + + xcount = 0; + i = SPACING; + while (i < da->allocation.width) + { + j = SPACING; + ycount = xcount % 2; /* start with even/odd depending on row */ + while (j < da->allocation.height) + { + GdkGC *gc; + + if (ycount % 2) + gc = gc1; + else + gc = gc2; + + /* If we're outside event->area, this will do nothing. + * It might be mildly more efficient if we handled + * the clipping ourselves, but again we're feeling lazy. + */ + gdk_draw_rectangle (da->window, + gc, + TRUE, + i, j, + CHECK_SIZE, + CHECK_SIZE); + + j += CHECK_SIZE + SPACING; + ++ycount; + } + + i += CHECK_SIZE + SPACING; + ++xcount; + } + + g_object_unref (G_OBJECT (gc1)); + g_object_unref (G_OBJECT (gc2)); + + /* return TRUE because we've handled this event, so no + * further processing is required. + */ + return TRUE; +} + +GtkWidget * +do_drawingarea (void) +{ + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *da; + GtkWidget *label; + + if (!window) + { + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Drawing Area"); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); + + gtk_container_set_border_width (GTK_CONTAINER (window), 8); + + vbox = gtk_vbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 8); + gtk_container_add (GTK_CONTAINER (window), vbox); + + /* + * Create the checkerboard area + */ + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "<u>Checkerboard pattern</u>"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); + + da = gtk_drawing_area_new (); + /* set a minimum size */ + gtk_widget_set_usize (da, 100, 100); + + gtk_container_add (GTK_CONTAINER (frame), da); + + gtk_signal_connect (GTK_OBJECT (da), + "expose_event", + GTK_SIGNAL_FUNC (checkerboard_expose), + NULL); + + /* + * Create the scribble area + */ + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "<u>Scribble area</u>"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); + + da = gtk_drawing_area_new (); + /* set a minimum size */ + gtk_widget_set_usize (da, 100, 100); + + gtk_container_add (GTK_CONTAINER (frame), da); + + /* Signals used to handle backing pixmap */ + + gtk_signal_connect (GTK_OBJECT (da), "expose_event", + GTK_SIGNAL_FUNC (scribble_expose_event), NULL); + gtk_signal_connect (GTK_OBJECT (da),"configure_event", + GTK_SIGNAL_FUNC (scribble_configure_event), NULL); + + /* Event signals */ + + gtk_signal_connect (GTK_OBJECT (da), "motion_notify_event", + GTK_SIGNAL_FUNC (scribble_motion_notify_event), NULL); + gtk_signal_connect (GTK_OBJECT (da), "button_press_event", + GTK_SIGNAL_FUNC (scribble_button_press_event), NULL); + + + /* Ask to receive events the drawing area doesn't normally + * subscribe to + */ + gtk_widget_set_events (da, gtk_widget_get_events (da) + | GDK_LEAVE_NOTIFY_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK); + + } + + if (!GTK_WIDGET_VISIBLE (window)) + { + gtk_widget_show_all (window); + } + else + { + gtk_widget_destroy (window); + window = NULL; + } + + return window; +} diff --git a/demos/gtk-demo/gnome-applets.png b/demos/gtk-demo/gnome-applets.png Binary files differnew file mode 100644 index 0000000000..8d3549e97c --- /dev/null +++ b/demos/gtk-demo/gnome-applets.png diff --git a/demos/gtk-demo/gnome-calendar.png b/demos/gtk-demo/gnome-calendar.png Binary files differnew file mode 100644 index 0000000000..889f329ae5 --- /dev/null +++ b/demos/gtk-demo/gnome-calendar.png diff --git a/demos/gtk-demo/gnome-foot.png b/demos/gtk-demo/gnome-foot.png Binary files differnew file mode 100644 index 0000000000..0476658517 --- /dev/null +++ b/demos/gtk-demo/gnome-foot.png diff --git a/demos/gtk-demo/gnome-gimp.png b/demos/gtk-demo/gnome-gimp.png Binary files differnew file mode 100644 index 0000000000..f6bbc6d36c --- /dev/null +++ b/demos/gtk-demo/gnome-gimp.png diff --git a/demos/gtk-demo/gnome-gmush.png b/demos/gtk-demo/gnome-gmush.png Binary files differnew file mode 100644 index 0000000000..0a4b0d04e6 --- /dev/null +++ b/demos/gtk-demo/gnome-gmush.png diff --git a/demos/gtk-demo/gnome-gsame.png b/demos/gtk-demo/gnome-gsame.png Binary files differnew file mode 100644 index 0000000000..01c061151f --- /dev/null +++ b/demos/gtk-demo/gnome-gsame.png diff --git a/demos/gtk-demo/gnu-keys.png b/demos/gtk-demo/gnu-keys.png Binary files differnew file mode 100644 index 0000000000..58a33770e6 --- /dev/null +++ b/demos/gtk-demo/gnu-keys.png diff --git a/demos/gtk-demo/gtk-logo-rgb.gif b/demos/gtk-demo/gtk-logo-rgb.gif Binary files differnew file mode 100644 index 0000000000..f6e934d5e6 --- /dev/null +++ b/demos/gtk-demo/gtk-logo-rgb.gif diff --git a/demos/gtk-demo/images.c b/demos/gtk-demo/images.c new file mode 100644 index 0000000000..756046ecfd --- /dev/null +++ b/demos/gtk-demo/images.c @@ -0,0 +1,396 @@ +/* Images + * + * GtkImage is used to display an image; the image can be in a number of formats. + * Typically, you load an image into a GdkPixbuf, then display the pixbuf. + * + * This demo code shows some of the more obscure cases, in the simple + * case a call to gtk_image_new_from_file() is all you need. + * + * If you want to put image data in your program as a C variable, + * use the make-inline-pixbuf program that comes with GTK+. + */ + +#include <gtk/gtk.h> +#include <stdio.h> +#include <errno.h> + +static GtkWidget *window = NULL; +static GdkPixbufLoader *pixbuf_loader = NULL; +static guint load_timeout = 0; +static FILE* image_stream = NULL; + +static void +progressive_prepared_callback (GdkPixbufLoader* loader, gpointer data) +{ + GdkPixbuf* pixbuf; + GtkWidget* image; + + image = GTK_WIDGET (data); + + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + + /* Avoid displaying random memory contents, since the pixbuf + * isn't filled in yet. + */ + gdk_pixbuf_fill (pixbuf, 0xaaaaaaff); + + gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); +} + +static void +progressive_updated_callback (GdkPixbufLoader* loader, + guint x, guint y, guint width, guint height, + gpointer data) +{ + GtkWidget* image; + + image = GTK_WIDGET (data); + + /* We know the pixbuf inside the image has changed, but the image + * itself doesn't know this; so queue a redraw. If we wanted to be + * really efficient, we could use a drawing area or something + * instead of a GtkImage, so we could control the exact position of + * the pixbuf on the display, then we could queue a draw for only + * the updated area of the image. + */ + + gtk_widget_queue_draw (image); +} + +static gint +progressive_timeout (gpointer data) +{ + GtkWidget *image; + + image = GTK_WIDGET (data); + + /* This shows off fully-paranoid error handling, so looks scary. + * You could factor out the error handling code into a nice separate + * function to make things nicer. + */ + + if (image_stream) + { + size_t bytes_read; + guchar buf[256]; + GError *error = NULL; + + bytes_read = fread (buf, 1, 256, image_stream); + + if (ferror (image_stream)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failure reading image file 'gtk-logo-rgb.gif': %s", + g_strerror (errno)); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + fclose (image_stream); + image_stream = NULL; + + gtk_widget_show (dialog); + + load_timeout = 0; + + return FALSE; /* uninstall the timeout */ + } + + if (!gdk_pixbuf_loader_write (pixbuf_loader, + buf, bytes_read, + &error)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failed to load image: %s", + error->message); + + g_error_free (error); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + fclose (image_stream); + image_stream = NULL; + + gtk_widget_show (dialog); + + load_timeout = 0; + + return FALSE; /* uninstall the timeout */ + } + + if (feof (image_stream)) + { + fclose (image_stream); + image_stream = NULL; + + /* Errors can happen on close, e.g. if the image + * file was truncated we'll know on close that + * it was incomplete. + */ + error = NULL; + if (!gdk_pixbuf_loader_close (pixbuf_loader, + &error)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failed to load image: %s", + error->message); + + g_error_free (error); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); + + g_object_unref (G_OBJECT (pixbuf_loader)); + pixbuf_loader = NULL; + + load_timeout = 0; + + return FALSE; /* uninstall the timeout */ + } + + g_object_unref (G_OBJECT (pixbuf_loader)); + pixbuf_loader = NULL; + } + } + else + { + const gchar *filename; + + if (g_file_test ("./gtk-logo-rgb.gif", G_FILE_TEST_EXISTS)) + filename = "./gtk-logo-rgb.gif"; + else + filename = DEMOCODEDIR"/gtk-log-rgb.gif"; + + image_stream = fopen (filename, "r"); + + if (image_stream == NULL) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Unable to open image file 'gtk-logo-rgb.gif': %s", + g_strerror (errno)); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); + + load_timeout = 0; + + return FALSE; /* uninstall the timeout */ + } + + if (pixbuf_loader) + { + gdk_pixbuf_loader_close (pixbuf_loader, NULL); + g_object_unref (G_OBJECT (pixbuf_loader)); + pixbuf_loader = NULL; + } + + pixbuf_loader = gdk_pixbuf_loader_new (); + + g_signal_connect_data (G_OBJECT (pixbuf_loader), + "area_prepared", + G_CALLBACK (progressive_prepared_callback), + image, + NULL, FALSE, FALSE); + + g_signal_connect_data (G_OBJECT (pixbuf_loader), + "area_updated", + G_CALLBACK (progressive_updated_callback), + image, + NULL, FALSE, FALSE); + } + + /* leave timeout installed */ + return TRUE; +} + +static void +start_progressive_loading (GtkWidget *image) +{ + /* This is obviously totally contrived (we slow down loading + * on purpose to show how incremental loading works). + * The real purpose of incremental loading is the case where + * you are reading data from a slow source such as the network. + * The timeout simply simulates a slow data source by inserting + * pauses in the reading process. + */ + load_timeout = g_timeout_add (300, + progressive_timeout, + image); +} + +static void +cleanup_callback (GtkObject *object, + gpointer data) +{ + if (load_timeout) + { + g_source_remove (load_timeout); + load_timeout = 0; + } + + if (pixbuf_loader) + { + gdk_pixbuf_loader_close (pixbuf_loader, NULL); + g_object_unref (G_OBJECT (pixbuf_loader)); + pixbuf_loader = NULL; + } + + if (image_stream) + fclose (image_stream); + image_stream = NULL; +} + +GtkWidget * +do_images (void) +{ + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *image; + GtkWidget *label; + GtkWidget *align; + + if (!window) + { + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Images"); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (cleanup_callback), NULL); + + gtk_container_set_border_width (GTK_CONTAINER (window), 8); + + vbox = gtk_vbox_new (FALSE, 8); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 8); + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "<u>Image loaded from a file</u>"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + /* The alignment keeps the frame from growing when users resize + * the window + */ + align = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_container_add (GTK_CONTAINER (align), frame); + gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0); + + /* We look for the image in the current directory first, + * so you can run gtk-demo without installing GTK + */ + if (g_file_test ("./gtk-logo-rgb.gif", G_FILE_TEST_EXISTS)) + { + /* This code shows off error handling. You can just use + * gtk_image_new_from_file() instead if you don't want to report + * errors to the user. If the file doesn't load when using + * gtk_image_new_from_file(), a "missing image" icon will + * be displayed instead. + */ + GdkPixbuf *pixbuf; + GError *error = NULL; + + pixbuf = gdk_pixbuf_new_from_file ("./gtk-logo-rgb.gif", + &error); + if (error) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Unable to open image file 'gtk-logo-rgb.gif': %s", + error->message); + g_error_free (error); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); + } + + image = gtk_image_new_from_pixbuf (pixbuf); + } + else + { + /* This is the simpler code, with no error handling. + * Here we're loading the installed gtk-logo-rgb.gif instead + * of the one in the current directory. + */ + image = gtk_image_new_from_file (DEMOCODEDIR"/gtk-logo-rgb.gif"); + } + + gtk_container_add (GTK_CONTAINER (frame), image); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), + "<u>Progressive image loading</u>"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + /* The alignment keeps the frame from growing when users resize + * the window + */ + align = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_container_add (GTK_CONTAINER (align), frame); + gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0); + + /* Create an empty image for now; the progressive loader + * will create the pixbuf and fill it in. + */ + image = gtk_image_new_from_pixbuf (NULL); + gtk_container_add (GTK_CONTAINER (frame), image); + + start_progressive_loading (image); + } + + if (!GTK_WIDGET_VISIBLE (window)) + { + gtk_widget_show_all (window); + } + else + { + gtk_widget_destroy (window); + window = NULL; + } + + return window; +} diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c index 0dfb4b1e26..fabf898d44 100644 --- a/demos/gtk-demo/main.c +++ b/demos/gtk-demo/main.c @@ -299,16 +299,18 @@ button_press_event_cb (GtkTreeView *tree_view, return FALSE; } -gboolean +void row_activated_cb (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column, - GtkTreeModel *model) + GtkTreePath *path, + GtkTreeViewColumn *column) { GtkTreeIter iter; gboolean italic; GDoDemoFunc func; GtkWidget *window; + GtkTreeModel *model; + + model = gtk_tree_view_get_model (tree_view); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (GTK_TREE_MODEL (model), @@ -321,6 +323,7 @@ row_activated_cb (GtkTreeView *tree_view, ITALIC_COLUMN, !italic, -1); window = (func) (); + if (window != NULL) { CallbackData *cbdata; @@ -334,10 +337,6 @@ row_activated_cb (GtkTreeView *tree_view, window_closed_cb, cbdata); } - else - { - gtk_tree_path_free (path); - } } static void @@ -385,9 +384,20 @@ create_text (GtkTextBuffer **buffer, font_desc = pango_font_description_from_string ("Courier 10"); gtk_widget_modify_font (text_view, font_desc); pango_font_description_free (font_desc); + + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), + GTK_WRAP_NONE); + } + else + { + /* Make it a bit nicer for text. */ + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), + GTK_WRAP_WORD); + gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (text_view), + 2); + gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (text_view), + 2); } - - gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), !is_source); return scrolled_window; } @@ -458,6 +468,7 @@ main (int argc, char **argv) gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "GTK+ Code Demos"); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_main_quit), NULL); diff --git a/demos/gtk-demo/menus.c b/demos/gtk-demo/menus.c index ac8a7e2c53..4788edd861 100644 --- a/demos/gtk-demo/menus.c +++ b/demos/gtk-demo/menus.c @@ -1,10 +1,31 @@ /* Menus * - * GTK+ includes a number of widgets for menus of actions. - * GtkMenu is a drop-down menu, GtkMenuBar a horizontal menu bar. - * Each of these widgets can hold various types of menuitem. - * As well as the base type, GtkMenuItem, there are GtkCheckMenuItem, - * GtkRadioMenuItem and GtkTearoffMenuItem. + * There are several widgets involved in displaying menus. The + * GtkMenuBar widget is a horizontal menu bar, which normally appears + * at the top of an application. The GtkMenu widget is the actual menu + * that pops up. Both GtkMenuBar and GtkMenu are subclasses of + * GtkMenuShell; a GtkMenuShell contains menu items + * (GtkMenuItem). Each menu item contains text and/or images and can + * be selected by the user. + * + * There are several kinds of menu item, including plain GtkMenuItem, + * GtkCheckMenuItem which can be checked/unchecked, GtkRadioMenuItem + * which is a check menu item that's in a mutually exclusive group, + * GtkSeparatorMenuItem which is a separator bar, GtkTearoffMenuItem + * which allows a GtkMenu to be torn off, and GtkImageMenuItem which + * can place a GtkImage or other widget next to the menu text. + * + * A GtkMenuItem can have a submenu, which is simply a GtkMenu to pop + * up when the menu item is selected. Typically, all menu items in a menu bar + * have submenus. + * + * The GtkOptionMenu widget is a button that pops up a GtkMenu when clicked. + * It's used inside dialogs and such. + * + * GtkItemFactory provides a higher-level interface for creating menu bars + * and menus; while you can construct menus manually, most people don't + * do that. There's a separate demo for GtkItemFactory. + * */ #include <stdio.h> @@ -39,8 +60,7 @@ create_menu (gint depth, gboolean tearoff) sprintf (buf, "item %2d - %d", depth, j); menuitem = gtk_radio_menu_item_new_with_label (group, buf); group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); - if (depth % 2) - gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menuitem), TRUE); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show (menuitem); if (i == 3) diff --git a/demos/gtk-demo/pixbufs.c b/demos/gtk-demo/pixbufs.c new file mode 100644 index 0000000000..6c067098ac --- /dev/null +++ b/demos/gtk-demo/pixbufs.c @@ -0,0 +1,277 @@ +/* Pixbufs + * + * A GdkPixbuf represents an image, normally in RGB or RGBA format. + * Pixbufs are normally used to load files from disk and perform + * image scaling. + * + * This demo is not all that educational, but looks cool. It was written + * by Extreme Pixbuf Hacker Federico Mena Quintero. It also shows + * off how to use GtkDrawingArea to do a simple animation. + * + * Look at the Image demo for additional pixbuf usage examples. + * + */ + +#include <config.h> +#include <stdlib.h> +#include <gtk/gtk.h> +#include <math.h> + + + +#define FRAME_DELAY 50 + +#define RELATIVE_BACKGROUND_NAME "background.jpg" +#define INSTALLED_BACKGROUND_NAME DEMOCODEDIR"/background.jpg" + +static const char *relative_image_names[] = { + "apple-red.png", + "gnome-applets.png", + "gnome-calendar.png", + "gnome-foot.png", + "gnome-gmush.png", + "gnome-gimp.png", + "gnome-gsame.png", + "gnu-keys.png" +}; + +static const char *installed_image_names[] = { + DEMOCODEDIR"/apple-red.png", + DEMOCODEDIR"/gnome-applets.png", + DEMOCODEDIR"/gnome-calendar.png", + DEMOCODEDIR"/gnome-foot.png", + DEMOCODEDIR"/gnome-gmush.png", + DEMOCODEDIR"/gnome-gimp.png", + DEMOCODEDIR"/gnome-gsame.png", + DEMOCODEDIR"/gnu-keys.png" +}; + +#define N_IMAGES G_N_ELEMENTS (relative_image_names) + +/* demo window */ +static GtkWindow *window = NULL; + +/* Current frame */ +static GdkPixbuf *frame; + +/* Background image */ +static GdkPixbuf *background; +static int back_width, back_height; + +/* Images */ +static GdkPixbuf *images[N_IMAGES]; + +/* Widgets */ +static GtkWidget *da; + + + +/* Loads the images for the demo and returns whether the operation succeeded */ +static gboolean +load_pixbufs (GError **error) +{ + int i; + const char **image_names; + + if (background) + return TRUE; /* already loaded earlier */ + + background = gdk_pixbuf_new_from_file (RELATIVE_BACKGROUND_NAME, NULL); + + if (!background) + background = gdk_pixbuf_new_from_file (INSTALLED_BACKGROUND_NAME, error); + + if (!background) + return FALSE; /* note that "error" was filled in and returned */ + + back_width = gdk_pixbuf_get_width (background); + back_height = gdk_pixbuf_get_height (background); + + if (g_file_test (relative_image_names[0], G_FILE_TEST_EXISTS)) + image_names = relative_image_names; + else + image_names = installed_image_names; + + for (i = 0; i < N_IMAGES; i++) + { + images[i] = gdk_pixbuf_new_from_file (image_names[i], error); + if (!images[i]) + return FALSE; /* Note that "error" was filled with a GError */ + } + + return TRUE; +} + +/* Expose callback for the drawing area */ +static gint +expose_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + guchar *pixels; + int rowstride; + + rowstride = gdk_pixbuf_get_rowstride (frame); + + pixels = gdk_pixbuf_get_pixels (frame) + rowstride * event->area.y + event->area.x * 3; + + gdk_draw_rgb_image_dithalign (widget->window, + widget->style->black_gc, + event->area.x, event->area.y, + event->area.width, event->area.height, + GDK_RGB_DITHER_NORMAL, + pixels, rowstride, + event->area.x, event->area.y); + + return TRUE; +} + +#define CYCLE_LEN 60 + +static int frame_num; + +/* Timeout handler to regenerate the frame */ +static gint +timeout (gpointer data) +{ + double f; + int i; + double xmid, ymid; + double radius; + + gdk_pixbuf_copy_area (background, 0, 0, back_width, back_height, + frame, 0, 0); + + f = (double) (frame_num % CYCLE_LEN) / CYCLE_LEN; + + xmid = back_width / 2.0; + ymid = back_height / 2.0; + + radius = MIN (xmid, ymid) / 2.0; + + for (i = 0; i < N_IMAGES; i++) + { + double ang; + int xpos, ypos; + int iw, ih; + double r; + GdkRectangle r1, r2, dest; + double k; + + ang = 2.0 * M_PI * (double) i / N_IMAGES - f * 2.0 * M_PI; + + iw = gdk_pixbuf_get_width (images[i]); + ih = gdk_pixbuf_get_height (images[i]); + + r = radius + (radius / 3.0) * sin (f * 2.0 * M_PI); + + xpos = floor (xmid + r * cos (ang) - iw / 2.0 + 0.5); + ypos = floor (ymid + r * sin (ang) - ih / 2.0 + 0.5); + + k = (i & 1) ? sin (f * 2.0 * M_PI) : cos (f * 2.0 * M_PI); + k = 2.0 * k * k; + k = MAX (0.25, k); + + r1.x = xpos; + r1.y = ypos; + r1.width = iw * k; + r1.height = ih * k; + + r2.x = 0; + r2.y = 0; + r2.width = back_width; + r2.height = back_height; + + if (gdk_rectangle_intersect (&r1, &r2, &dest)) + gdk_pixbuf_composite (images[i], + frame, + dest.x, dest.y, + dest.width, dest.height, + xpos, ypos, + k, k, + GDK_INTERP_NEAREST, + ((i & 1) + ? MAX (127, fabs (255 * sin (f * 2.0 * M_PI))) + : MAX (127, fabs (255 * cos (f * 2.0 * M_PI))))); + } + + gtk_widget_queue_draw (da); + + frame_num++; + return TRUE; +} + +static guint timeout_id; + +static void +cleanup_callback (GtkObject *object, + gpointer data) +{ + g_source_remove (timeout_id); + timeout_id = 0; +} + +GtkWidget * +do_pixbufs (void) +{ + if (!window) + { + GError *error; + + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Pixbufs"); + gtk_window_set_resizeable (GTK_WINDOW (window), FALSE); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (cleanup_callback), NULL); + + + error = NULL; + if (!load_pixbufs (&error)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failed to load an image: %s", + error->message); + + g_error_free (error); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); + } + else + { + gtk_widget_set_usize (window, back_width, back_height); + + frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, back_width, back_height); + + da = gtk_drawing_area_new (); + + gtk_signal_connect (GTK_OBJECT (da), "expose_event", + GTK_SIGNAL_FUNC (expose_cb), NULL); + + gtk_container_add (GTK_CONTAINER (window), da); + + timeout_id = gtk_timeout_add (FRAME_DELAY, timeout, NULL); + } + } + + if (!GTK_WIDGET_VISIBLE (window)) + { + gtk_widget_show_all (window); + } + else + { + gtk_widget_destroy (window); + window = NULL; + } + + return window; +} diff --git a/demos/pixbuf-demo.c b/demos/pixbuf-demo.c index 0ee8aca460..641bdf3468 100644 --- a/demos/pixbuf-demo.c +++ b/demos/pixbuf-demo.c @@ -49,13 +49,13 @@ static GdkPixbuf *frame; /* Background image */ static GdkPixbuf *background; -int back_width, back_height; +static int back_width, back_height; /* Images */ static GdkPixbuf *images[N_IMAGES]; /* Widgets */ -GtkWidget *da; +static GtkWidget *da; diff --git a/docs/reference/gtk/tmpl/gtk-unused.sgml b/docs/reference/gtk/tmpl/gtk-unused.sgml index 84d2e992e1..c3ee353dcb 100644 --- a/docs/reference/gtk/tmpl/gtk-unused.sgml +++ b/docs/reference/gtk/tmpl/gtk-unused.sgml @@ -723,18 +723,6 @@ produce superscript and subscript. </para> -<!-- ##### ARG GtkTextView:justify ##### --> -<para> - -</para> - - -<!-- ##### ARG GtkTextView:wrap-mode ##### --> -<para> - -</para> - - <!-- ##### SIGNAL GtkWidget::activate-mnemonic ##### --> <para> diff --git a/docs/reference/gtk/tmpl/gtkrc.sgml b/docs/reference/gtk/tmpl/gtkrc.sgml index 178b403922..4c81682d17 100644 --- a/docs/reference/gtk/tmpl/gtkrc.sgml +++ b/docs/reference/gtk/tmpl/gtkrc.sgml @@ -496,6 +496,7 @@ This can later be composited together with other #GtkRcStyle structures to form a #GtkStyle. </para> +@parent_instance: @name: @bg_pixmap_name: @font_desc: diff --git a/docs/reference/gtk/tmpl/gtktextview.sgml b/docs/reference/gtk/tmpl/gtktextview.sgml index f168889dc6..e4b5b21462 100644 --- a/docs/reference/gtk/tmpl/gtktextview.sgml +++ b/docs/reference/gtk/tmpl/gtktextview.sgml @@ -660,6 +660,16 @@ types related to the text widget and how they work together. </para> +<!-- ##### ARG GtkTextView:wrap-mode ##### --> +<para> + +</para> + +<!-- ##### ARG GtkTextView:justify ##### --> +<para> + +</para> + <!-- ##### ARG GtkTextView:left-margin ##### --> <para> diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index a3ebb8f284..59eb2f3502 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,8 @@ +2001-04-18 Havoc Pennington <hp@redhat.com> + + * gdk-pixbuf.c (gdk_pixbuf_fill): Function to fill pixbuf with a + given color. + Wed Apr 4 01:41:02 2001 Tim Janik <timj@gtk.org> * pixops/Makefile.am (noinst_LTLIBRARIES): include $top_srcdir diff --git a/gdk-pixbuf/gdk-pixbuf.c b/gdk-pixbuf/gdk-pixbuf.c index 2a65082d93..12b8e61441 100644 --- a/gdk-pixbuf/gdk-pixbuf.c +++ b/gdk-pixbuf/gdk-pixbuf.c @@ -409,6 +409,64 @@ gdk_pixbuf_error_quark (void) return q; } +/** + * gdk_pixbuf_fill: + * @pixbuf: a #GdkPixbuf + * @pixel: RGBA pixel to clear to (0xffffff00 is opaque white, 0x000000ff transparent black) + * + * Clears a pixbuf to the given RGBA value, converting the RGBA value into + * the pixbuf's pixel format. The alpha will be ignored if the pixbuf + * doesn't have an alpha channel. + * + **/ +void +gdk_pixbuf_fill (GdkPixbuf *pixbuf, + guint32 pixel) +{ + guchar *pixels; + gboolean all_the_same = FALSE; + guint r, g, b, a; + + g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); + + pixels = pixbuf->pixels; + + r = (pixel & 0xff000000) >> 24; + g = (pixel & 0x00ff0000) >> 16; + b = (pixel & 0x0000ff00) >> 8; + a = (pixel & 0x000000ff); + + if (r == g && g == b) { + if (!pixbuf->has_alpha) + all_the_same = TRUE; + else + all_the_same = (r == a); + } + + if (all_the_same) { + memset (pixels, r, + pixbuf->rowstride * pixbuf->height); + } else { + guchar *p; + guchar *end; + + /* feel free to optimize this */ + + p = pixels; + end = pixels + pixbuf->rowstride * pixbuf->height; + end -= (pixbuf->rowstride - pixbuf->width); + + while (p < end) { + *p++ = r; + *p++ = g; + *p++ = b; + if (pixbuf->has_alpha) + *p++ = a; + } + } +} + + /* Include the marshallers */ #include <glib-object.h> #include "gdk-pixbuf-marshal.c" diff --git a/gdk-pixbuf/gdk-pixbuf.h b/gdk-pixbuf/gdk-pixbuf.h index dd40abbe43..b8b5a03af0 100644 --- a/gdk-pixbuf/gdk-pixbuf.h +++ b/gdk-pixbuf/gdk-pixbuf.h @@ -145,6 +145,9 @@ GdkPixbuf *gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf, int length, GError **error); +/* Mutations */ +void gdk_pixbuf_fill (GdkPixbuf *pixbuf, + guint32 pixel); /* Saving */ diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index 48da4edcd0..03f5fe0b68 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -934,12 +934,8 @@ static void gtk_image_reset (GtkImage *image) { gtk_image_clear (image); - - 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_update_size (image, 0, 0); } static void @@ -951,6 +947,12 @@ gtk_image_size_request (GtkWidget *widget, image = GTK_IMAGE (widget); + /* We update stock/icon set on every size request, because + * the theme could have affected the size; for other kinds of + * image, we just update the requisition when the image data + * is set. + */ + switch (image->storage_type) { case GTK_IMAGE_STOCK: @@ -976,9 +978,9 @@ gtk_image_size_request (GtkWidget *widget, if (pixbuf) { - gtk_image_update_size (image, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); + GTK_WIDGET (image)->requisition.width = gdk_pixbuf_get_width (pixbuf) + GTK_MISC (image)->xpad * 2; + GTK_WIDGET (image)->requisition.height = gdk_pixbuf_get_height (pixbuf) + GTK_MISC (image)->ypad * 2; + g_object_unref (G_OBJECT (pixbuf)); } @@ -993,6 +995,9 @@ gtk_image_update_size (GtkImage *image, { GTK_WIDGET (image)->requisition.width = image_width + GTK_MISC (image)->xpad * 2; GTK_WIDGET (image)->requisition.height = image_height + GTK_MISC (image)->ypad * 2; + + if (GTK_WIDGET_VISIBLE (image)) + gtk_widget_queue_resize (GTK_WIDGET (image)); } diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index d9de973429..3f9f6bdb20 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -4970,6 +4970,8 @@ gtk_text_view_do_popup (GtkTextView *text_view, GtkWidget *menuitem; GtkWidget *submenu; gboolean have_selection; + gboolean can_insert; + GtkTextIter iter; if (text_view->popup_menu) gtk_widget_destroy (text_view->popup_menu); @@ -4982,13 +4984,20 @@ gtk_text_view_do_popup (GtkTextView *text_view, have_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view), NULL, NULL); + + gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), + &iter, + gtk_text_buffer_get_insert (get_buffer (text_view))); + + can_insert = gtk_text_iter_editable (&iter, text_view->editable); append_action_signal (text_view, text_view->popup_menu, _("Cut"), "cut_clipboard", have_selection); append_action_signal (text_view, text_view->popup_menu, _("Copy"), "copy_clipboard", have_selection); + append_action_signal (text_view, text_view->popup_menu, _("Paste"), "paste_clipboard", - TRUE); + can_insert); menuitem = gtk_separator_menu_item_new (); gtk_widget_show (menuitem); |