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.
This commit is contained in:
Havoc Pennington 2001-04-18 18:09:18 +00:00 committed by Havoc Pennington
parent ebd3958c06
commit 60b6a010e9
33 changed files with 1274 additions and 53 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -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);
}

View File

@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
demos/gtk-demo/gnu-keys.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

396
demos/gtk-demo/images.c Normal file
View File

@ -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;
}

View File

@ -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);

View File

@ -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)

277
demos/gtk-demo/pixbufs.c Normal file
View File

@ -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;
}

View File

@ -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;

View File

@ -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>

View File

@ -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:

View File

@ -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>

View File

@ -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

View File

@ -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"

View File

@ -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 */

View File

@ -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));
}

View File

@ -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);