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.
14
ChangeLog
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
BIN
demos/gtk-demo/apple-red.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
demos/gtk-demo/background.jpg
Normal file
After Width: | Height: | Size: 22 KiB |
@ -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);
|
||||
}
|
||||
|
||||
|
322
demos/gtk-demo/drawingarea.c
Normal 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;
|
||||
}
|
BIN
demos/gtk-demo/gnome-applets.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
demos/gtk-demo/gnome-calendar.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
demos/gtk-demo/gnome-foot.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
demos/gtk-demo/gnome-gimp.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
demos/gtk-demo/gnome-gmush.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
demos/gtk-demo/gnome-gsame.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
demos/gtk-demo/gnu-keys.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
demos/gtk-demo/gtk-logo-rgb.gif
Normal file
After Width: | Height: | Size: 6.3 KiB |
396
demos/gtk-demo/images.c
Normal 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;
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|