diff options
author | Johannes Schmid <jhs@gnome.org> | 2009-10-28 10:57:46 +0100 |
---|---|---|
committer | Johannes Schmid <jhs@gnome.org> | 2009-10-28 10:57:46 +0100 |
commit | c229306a18f6453c144397bfbbf2284afa9731eb (patch) | |
tree | fd37ba747b10ec03b968762f01386ab0d7b926c3 /demos | |
parent | 249be999a6699752980a5e16e45b45c4db18dabf (diff) | |
parent | 4ff709c24b8d4b3e26b3d513fde0676e9c43f897 (diff) | |
download | gtk+-c229306a18f6453c144397bfbbf2284afa9731eb.tar.gz |
Merge branch 'master' into toolpalette
Diffstat (limited to 'demos')
-rw-r--r-- | demos/gtk-demo/Makefile.am | 3 | ||||
-rw-r--r-- | demos/gtk-demo/clipboard.c | 4 | ||||
-rw-r--r-- | demos/gtk-demo/links.c | 9 | ||||
-rw-r--r-- | demos/gtk-demo/list_store.c | 146 | ||||
-rw-r--r-- | demos/gtk-demo/menus.c | 35 | ||||
-rw-r--r-- | demos/gtk-demo/offscreen_window.c | 579 | ||||
-rw-r--r-- | demos/gtk-demo/offscreen_window2.c | 500 | ||||
-rw-r--r-- | demos/gtk-demo/printing.c | 2 | ||||
-rw-r--r-- | demos/gtk-demo/spinner.c | 94 |
9 files changed, 1312 insertions, 60 deletions
diff --git a/demos/gtk-demo/Makefile.am b/demos/gtk-demo/Makefile.am index 569089245b..792ee35971 100644 --- a/demos/gtk-demo/Makefile.am +++ b/demos/gtk-demo/Makefile.am @@ -28,6 +28,8 @@ demos = \ links.c \ list_store.c \ menus.c \ + offscreen_window.c \ + offscreen_window2.c \ panes.c \ pickers.c \ pixbufs.c \ @@ -35,6 +37,7 @@ demos = \ rotated_text.c \ search_entry.c \ sizegroup.c \ + spinner.c \ stock_browser.c \ textview.c \ textscroll.c \ diff --git a/demos/gtk-demo/clipboard.c b/demos/gtk-demo/clipboard.c index 8e6c2809d4..5559c5e78d 100644 --- a/demos/gtk-demo/clipboard.c +++ b/demos/gtk-demo/clipboard.c @@ -203,6 +203,10 @@ do_clipboard (GtkWidget *do_widget) GtkClipboard *clipboard; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_screen (GTK_WINDOW (window), + gtk_widget_get_screen (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "Clipboard demo"); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); diff --git a/demos/gtk-demo/links.c b/demos/gtk-demo/links.c index c506144c87..569cd91231 100644 --- a/demos/gtk-demo/links.c +++ b/demos/gtk-demo/links.c @@ -43,11 +43,11 @@ activate_link (GtkWidget *label, return FALSE; } +static GtkWidget *window = NULL; + GtkWidget * do_links (GtkWidget *do_widget) { - static GtkWidget *window = NULL; - GtkWidget *box; GtkWidget *label; if (!window) @@ -55,11 +55,10 @@ do_links (GtkWidget *do_widget) window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "Links"); gtk_container_set_border_width (GTK_CONTAINER (window), 12); g_signal_connect (window, "destroy", - G_CALLBACK(gtk_widget_destroyed), &window); - g_signal_connect (window, "delete-event", - G_CALLBACK (gtk_true), NULL); + G_CALLBACK (gtk_widget_destroyed), &window); label = gtk_label_new ("Some <a href=\"http://en.wikipedia.org/wiki/Text\"" "title=\"plain text\">text</a> may be marked up\n" diff --git a/demos/gtk-demo/list_store.c b/demos/gtk-demo/list_store.c index 990e489921..94335afdf8 100644 --- a/demos/gtk-demo/list_store.c +++ b/demos/gtk-demo/list_store.c @@ -10,6 +10,8 @@ #include <gtk/gtk.h> static GtkWidget *window = NULL; +static GtkTreeModel *model = NULL; +static guint timeout = 0; typedef struct { @@ -26,6 +28,8 @@ enum COLUMN_NUMBER, COLUMN_SEVERITY, COLUMN_DESCRIPTION, + COLUMN_PULSE, + COLUMN_ACTIVE, NUM_COLUMNS }; @@ -47,6 +51,33 @@ static Bug data[] = { FALSE, 1, "Normal", "First bug :=)" }, }; +static gboolean +spinner_timeout (gpointer data) +{ + GtkTreeIter iter; + guint pulse; + + if (model == NULL) + return FALSE; + + gtk_tree_model_get_iter_first (model, &iter); + gtk_tree_model_get (model, &iter, + COLUMN_PULSE, &pulse, + -1); + if (pulse == G_MAXUINT) + pulse = 0; + else + pulse++; + + gtk_list_store_set (GTK_LIST_STORE (model), + &iter, + COLUMN_PULSE, pulse, + COLUMN_ACTIVE, TRUE, + -1); + + return TRUE; +} + static GtkTreeModel * create_model (void) { @@ -56,21 +87,25 @@ create_model (void) /* create list store */ store = gtk_list_store_new (NUM_COLUMNS, - G_TYPE_BOOLEAN, - G_TYPE_UINT, - G_TYPE_STRING, - G_TYPE_STRING); + G_TYPE_BOOLEAN, + G_TYPE_UINT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT, + G_TYPE_BOOLEAN); /* add data to the list store */ for (i = 0; i < G_N_ELEMENTS (data); i++) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, - COLUMN_FIXED, data[i].fixed, - COLUMN_NUMBER, data[i].number, - COLUMN_SEVERITY, data[i].severity, - COLUMN_DESCRIPTION, data[i].description, - -1); + COLUMN_FIXED, data[i].fixed, + COLUMN_NUMBER, data[i].number, + COLUMN_SEVERITY, data[i].severity, + COLUMN_DESCRIPTION, data[i].description, + COLUMN_PULSE, 0, + COLUMN_ACTIVE, FALSE, + -1); } return GTK_TREE_MODEL (store); @@ -78,8 +113,8 @@ create_model (void) static void fixed_toggled (GtkCellRendererToggle *cell, - gchar *path_str, - gpointer data) + gchar *path_str, + gpointer data) { GtkTreeModel *model = (GtkTreeModel *)data; GtkTreeIter iter; @@ -110,48 +145,75 @@ add_columns (GtkTreeView *treeview) /* column for fixed toggles */ renderer = gtk_cell_renderer_toggle_new (); g_signal_connect (renderer, "toggled", - G_CALLBACK (fixed_toggled), model); + G_CALLBACK (fixed_toggled), model); column = gtk_tree_view_column_new_with_attributes ("Fixed?", - renderer, - "active", COLUMN_FIXED, - NULL); + renderer, + "active", COLUMN_FIXED, + NULL); /* set this column to a fixed sizing (of 50 pixels) */ gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column), - GTK_TREE_VIEW_COLUMN_FIXED); + GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50); gtk_tree_view_append_column (treeview, column); /* column for bug numbers */ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Bug number", - renderer, - "text", - COLUMN_NUMBER, - NULL); + renderer, + "text", + COLUMN_NUMBER, + NULL); gtk_tree_view_column_set_sort_column_id (column, COLUMN_NUMBER); gtk_tree_view_append_column (treeview, column); /* column for severities */ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Severity", - renderer, - "text", - COLUMN_SEVERITY, - NULL); + renderer, + "text", + COLUMN_SEVERITY, + NULL); gtk_tree_view_column_set_sort_column_id (column, COLUMN_SEVERITY); gtk_tree_view_append_column (treeview, column); /* column for description */ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Description", - renderer, - "text", - COLUMN_DESCRIPTION, - NULL); + renderer, + "text", + COLUMN_DESCRIPTION, + NULL); gtk_tree_view_column_set_sort_column_id (column, COLUMN_DESCRIPTION); gtk_tree_view_append_column (treeview, column); + + /* column for spinner */ + renderer = gtk_cell_renderer_spinner_new (); + column = gtk_tree_view_column_new_with_attributes ("Spinning", + renderer, + "pulse", + COLUMN_PULSE, + "active", + COLUMN_ACTIVE, + NULL); + gtk_tree_view_column_set_sort_column_id (column, COLUMN_PULSE); + gtk_tree_view_append_column (treeview, column); +} + +static gboolean +window_closed (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + model = NULL; + window = NULL; + if (timeout != 0) + { + g_source_remove (timeout); + timeout = 0; + } + return FALSE; } GtkWidget * @@ -162,17 +224,16 @@ do_list_store (GtkWidget *do_widget) GtkWidget *vbox; GtkWidget *label; GtkWidget *sw; - GtkTreeModel *model; GtkWidget *treeview; /* create window, etc */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_screen (GTK_WINDOW (window), - gtk_widget_get_screen (do_widget)); + gtk_widget_get_screen (do_widget)); gtk_window_set_title (GTK_WINDOW (window), "GtkListStore demo"); g_signal_connect (window, "destroy", - G_CALLBACK (gtk_widget_destroyed), &window); + G_CALLBACK (gtk_widget_destroyed), &window); gtk_container_set_border_width (GTK_CONTAINER (window), 8); vbox = gtk_vbox_new (FALSE, 8); @@ -183,10 +244,10 @@ do_list_store (GtkWidget *do_widget) sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), - GTK_SHADOW_ETCHED_IN); + GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0); /* create tree model */ @@ -196,7 +257,7 @@ do_list_store (GtkWidget *do_widget) treeview = gtk_tree_view_new_with_model (model); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE); gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview), - COLUMN_DESCRIPTION); + COLUMN_DESCRIPTION); g_object_unref (model); @@ -207,14 +268,27 @@ do_list_store (GtkWidget *do_widget) /* finish & show */ gtk_window_set_default_size (GTK_WINDOW (window), 280, 250); + g_signal_connect (window, "delete-event", + G_CALLBACK (window_closed), NULL); } if (!GTK_WIDGET_VISIBLE (window)) - gtk_widget_show_all (window); + { + gtk_widget_show_all (window); + if (timeout == 0) { + /* FIXME this should use the animation-duration instead */ + timeout = g_timeout_add (80, spinner_timeout, NULL); + } + } else { gtk_widget_destroy (window); window = NULL; + if (timeout != 0) + { + g_source_remove (timeout); + timeout = 0; + } } return window; diff --git a/demos/gtk-demo/menus.c b/demos/gtk-demo/menus.c index ddb4cf462f..2e6fe2951c 100644 --- a/demos/gtk-demo/menus.c +++ b/demos/gtk-demo/menus.c @@ -2,10 +2,10 @@ * * There are several widgets involved in displaying menus. The * GtkMenuBar widget is a menu bar, which normally appears horizontally - * at the top of an application, but can also be layed out vertically. - * 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 + * at the top of an application, but can also be layed out vertically. + * 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, @@ -22,7 +22,6 @@ * GtkUIManager 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 GtkUIManager. - * */ #include <gtk/gtk.h> @@ -118,37 +117,35 @@ change_orientation (GtkWidget *button, } } +static GtkWidget *window = NULL; + GtkWidget * do_menus (GtkWidget *do_widget) { - static GtkWidget *window = NULL; GtkWidget *box; GtkWidget *box1; GtkWidget *box2; GtkWidget *button; - + if (!window) { GtkWidget *menubar; GtkWidget *menu; GtkWidget *menuitem; GtkAccelGroup *accel_group; - + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "Menus"); g_signal_connect (window, "destroy", G_CALLBACK(gtk_widget_destroyed), &window); - g_signal_connect (window, "delete-event", - G_CALLBACK (gtk_true), NULL); - + accel_group = gtk_accel_group_new (); gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - gtk_window_set_title (GTK_WINDOW (window), "menus"); gtk_container_set_border_width (GTK_CONTAINER (window), 0); - - + box = gtk_hbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (window), box); gtk_widget_show (box); @@ -156,18 +153,18 @@ do_menus (GtkWidget *do_widget) box1 = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (box), box1); gtk_widget_show (box1); - + menubar = gtk_menu_bar_new (); gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0); gtk_widget_show (menubar); - + menu = create_menu (2, TRUE); - + menuitem = gtk_menu_item_new_with_label ("test\nline2"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu); gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem); gtk_widget_show (menuitem); - + menuitem = gtk_menu_item_new_with_label ("foo"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (3, TRUE)); gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem); @@ -178,7 +175,7 @@ do_menus (GtkWidget *do_widget) gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE); gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem); gtk_widget_show (menuitem); - + box2 = gtk_vbox_new (FALSE, 10); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); diff --git a/demos/gtk-demo/offscreen_window.c b/demos/gtk-demo/offscreen_window.c new file mode 100644 index 0000000000..32c9c8c095 --- /dev/null +++ b/demos/gtk-demo/offscreen_window.c @@ -0,0 +1,579 @@ +/* Offscreen windows/Rotated button + * + * Offscreen windows can be used to transform parts of a widget + * hierarchy. Note that the rotated button is fully functional. + */ +#include <math.h> +#include <gtk/gtk.h> + +#define GTK_TYPE_ROTATED_BIN (gtk_rotated_bin_get_type ()) +#define GTK_ROTATED_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ROTATED_BIN, GtkRotatedBin)) +#define GTK_ROTATED_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ROTATED_BIN, GtkRotatedBinClass)) +#define GTK_IS_ROTATED_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ROTATED_BIN)) +#define GTK_IS_ROTATED_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ROTATED_BIN)) +#define GTK_ROTATED_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ROTATED_BIN, GtkRotatedBinClass)) + +typedef struct _GtkRotatedBin GtkRotatedBin; +typedef struct _GtkRotatedBinClass GtkRotatedBinClass; + +struct _GtkRotatedBin +{ + GtkContainer container; + + GtkWidget *child; + GdkWindow *offscreen_window; + gdouble angle; +}; + +struct _GtkRotatedBinClass +{ + GtkContainerClass parent_class; +}; + +GType gtk_rotated_bin_get_type (void) G_GNUC_CONST; +GtkWidget* gtk_rotated_bin_new (void); +void gtk_rotated_bin_set_angle (GtkRotatedBin *bin, + gdouble angle); + +/*** implementation ***/ + +static void gtk_rotated_bin_realize (GtkWidget *widget); +static void gtk_rotated_bin_unrealize (GtkWidget *widget); +static void gtk_rotated_bin_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_rotated_bin_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gboolean gtk_rotated_bin_damage (GtkWidget *widget, + GdkEventExpose *event); +static gboolean gtk_rotated_bin_expose (GtkWidget *widget, + GdkEventExpose *offscreen); + +static void gtk_rotated_bin_add (GtkContainer *container, + GtkWidget *child); +static void gtk_rotated_bin_remove (GtkContainer *container, + GtkWidget *widget); +static void gtk_rotated_bin_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static GType gtk_rotated_bin_child_type (GtkContainer *container); + +G_DEFINE_TYPE (GtkRotatedBin, gtk_rotated_bin, GTK_TYPE_CONTAINER); + +static void +to_child (GtkRotatedBin *bin, + double widget_x, + double widget_y, + double *x_out, + double *y_out) +{ + GtkAllocation child_area; + double x, y, xr, yr; + double c, s; + double w, h; + + s = sin (bin->angle); + c = cos (bin->angle); + child_area = bin->child->allocation; + + w = c * child_area.width + s * child_area.height; + h = s * child_area.width + c * child_area.height; + + x = widget_x; + y = widget_y; + + x -= (w - child_area.width) / 2; + y -= (h - child_area.height) / 2; + + x -= child_area.width / 2; + y -= child_area.height / 2; + + xr = x * c + y * s; + yr = y * c - x * s; + x = xr; + y = yr; + + x += child_area.width / 2; + y += child_area.height / 2; + + *x_out = x; + *y_out = y; +} + +static void +to_parent (GtkRotatedBin *bin, + double offscreen_x, + double offscreen_y, + double *x_out, + double *y_out) +{ + GtkAllocation child_area; + double x, y, xr, yr; + double c, s; + double w, h; + + s = sin (bin->angle); + c = cos (bin->angle); + child_area = bin->child->allocation; + + w = c * child_area.width + s * child_area.height; + h = s * child_area.width + c * child_area.height; + + x = offscreen_x; + y = offscreen_y; + + x -= child_area.width / 2; + y -= child_area.height / 2; + + xr = x * c - y * s; + yr = x * s + y * c; + x = xr; + y = yr; + + x += child_area.width / 2; + y += child_area.height / 2; + + x -= (w - child_area.width) / 2; + y -= (h - child_area.height) / 2; + + *x_out = x; + *y_out = y; +} + +static void +gtk_rotated_bin_class_init (GtkRotatedBinClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); + + widget_class->realize = gtk_rotated_bin_realize; + widget_class->unrealize = gtk_rotated_bin_unrealize; + widget_class->size_request = gtk_rotated_bin_size_request; + widget_class->size_allocate = gtk_rotated_bin_size_allocate; + widget_class->expose_event = gtk_rotated_bin_expose; + + g_signal_override_class_closure (g_signal_lookup ("damage-event", GTK_TYPE_WIDGET), + GTK_TYPE_ROTATED_BIN, + g_cclosure_new (G_CALLBACK (gtk_rotated_bin_damage), + NULL, NULL)); + + container_class->add = gtk_rotated_bin_add; + container_class->remove = gtk_rotated_bin_remove; + container_class->forall = gtk_rotated_bin_forall; + container_class->child_type = gtk_rotated_bin_child_type; +} + +static void +gtk_rotated_bin_init (GtkRotatedBin *bin) +{ + GTK_WIDGET_UNSET_FLAGS (bin, GTK_NO_WINDOW); +} + +GtkWidget * +gtk_rotated_bin_new (void) +{ + return g_object_new (GTK_TYPE_ROTATED_BIN, NULL); +} + +static GdkWindow * +pick_offscreen_child (GdkWindow *offscreen_window, + double widget_x, + double widget_y, + GtkRotatedBin *bin) +{ + GtkAllocation child_area; + double x, y; + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + to_child (bin, widget_x, widget_y, &x, &y); + + child_area = bin->child->allocation; + + if (x >= 0 && x < child_area.width && + y >= 0 && y < child_area.height) + return bin->offscreen_window; + } + + return NULL; +} + +static void +offscreen_window_to_parent (GdkWindow *offscreen_window, + double offscreen_x, + double offscreen_y, + double *parent_x, + double *parent_y, + GtkRotatedBin *bin) +{ + to_parent (bin, offscreen_x, offscreen_y, parent_x, parent_y); +} + +static void +offscreen_window_from_parent (GdkWindow *window, + double parent_x, + double parent_y, + double *offscreen_x, + double *offscreen_y, + GtkRotatedBin *bin) +{ + to_child (bin, parent_x, parent_y, offscreen_x, offscreen_y); +} + +static void +gtk_rotated_bin_realize (GtkWidget *widget) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (widget); + GdkWindowAttr attributes; + gint attributes_mask; + gint border_width; + GtkRequisition child_requisition; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + border_width = GTK_CONTAINER (widget)->border_width; + + attributes.x = widget->allocation.x + border_width; + attributes.y = widget->allocation.y + border_width; + attributes.width = widget->allocation.width - 2 * border_width; + attributes.height = widget->allocation.height - 2 * border_width; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = gtk_widget_get_events (widget) + | GDK_EXPOSURE_MASK + | GDK_POINTER_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_SCROLL_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK; + + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.wclass = GDK_INPUT_OUTPUT; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); + g_signal_connect (widget->window, "pick-embedded-child", + G_CALLBACK (pick_offscreen_child), bin); + + attributes.window_type = GDK_WINDOW_OFFSCREEN; + + child_requisition.width = child_requisition.height = 0; + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + attributes.width = bin->child->allocation.width; + attributes.height = bin->child->allocation.height; + } + bin->offscreen_window = gdk_window_new (gtk_widget_get_root_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (bin->offscreen_window, widget); + if (bin->child) + gtk_widget_set_parent_window (bin->child, bin->offscreen_window); + gdk_offscreen_window_set_embedder (bin->offscreen_window, widget->window); + g_signal_connect (bin->offscreen_window, "to-embedder", + G_CALLBACK (offscreen_window_to_parent), bin); + g_signal_connect (bin->offscreen_window, "from-embedder", + G_CALLBACK (offscreen_window_from_parent), bin); + + widget->style = gtk_style_attach (widget->style, widget->window); + + gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + gtk_style_set_background (widget->style, bin->offscreen_window, GTK_STATE_NORMAL); + gdk_window_show (bin->offscreen_window); +} + +static void +gtk_rotated_bin_unrealize (GtkWidget *widget) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (widget); + + gdk_window_set_user_data (bin->offscreen_window, NULL); + gdk_window_destroy (bin->offscreen_window); + bin->offscreen_window = NULL; + + GTK_WIDGET_CLASS (gtk_rotated_bin_parent_class)->unrealize (widget); +} + +static GType +gtk_rotated_bin_child_type (GtkContainer *container) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (container); + + if (bin->child) + return G_TYPE_NONE; + + return GTK_TYPE_WIDGET; +} + +static void +gtk_rotated_bin_add (GtkContainer *container, + GtkWidget *widget) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (container); + + if (!bin->child) + { + gtk_widget_set_parent_window (widget, bin->offscreen_window); + gtk_widget_set_parent (widget, GTK_WIDGET (bin)); + bin->child = widget; + } + else + g_warning ("GtkRotatedBin cannot have more than one child\n"); +} + +static void +gtk_rotated_bin_remove (GtkContainer *container, + GtkWidget *widget) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (container); + gboolean was_visible; + + was_visible = GTK_WIDGET_VISIBLE (widget); + + if (bin->child == widget) + { + gtk_widget_unparent (widget); + + bin->child = NULL; + + if (was_visible && GTK_WIDGET_VISIBLE (container)) + gtk_widget_queue_resize (GTK_WIDGET (container)); + } +} + +static void +gtk_rotated_bin_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (container); + + g_return_if_fail (callback != NULL); + + if (bin->child) + (*callback) (bin->child, callback_data); +} + +void +gtk_rotated_bin_set_angle (GtkRotatedBin *bin, + gdouble angle) +{ + g_return_if_fail (GTK_IS_ROTATED_BIN (bin)); + + bin->angle = angle; + gtk_widget_queue_resize (GTK_WIDGET (bin)); + + gdk_window_geometry_changed (bin->offscreen_window); +} + +static void +gtk_rotated_bin_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (widget); + GtkRequisition child_requisition; + double s, c; + double w, h; + + child_requisition.width = 0; + child_requisition.height = 0; + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + gtk_widget_size_request (bin->child, &child_requisition); + + s = sin (bin->angle); + c = cos (bin->angle); + w = c * child_requisition.width + s * child_requisition.height; + h = s * child_requisition.width + c * child_requisition.height; + + requisition->width = GTK_CONTAINER (widget)->border_width * 2 + w; + requisition->height = GTK_CONTAINER (widget)->border_width * 2 + h; +} + +static void +gtk_rotated_bin_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (widget); + gint border_width; + gint w, h; + gdouble s, c; + + widget->allocation = *allocation; + + border_width = GTK_CONTAINER (widget)->border_width; + + w = allocation->width - border_width * 2; + h = allocation->height - border_width * 2; + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (widget->window, + allocation->x + border_width, + allocation->y + border_width, + w, h); + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + GtkRequisition child_requisition; + GtkAllocation child_allocation; + + s = sin (bin->angle); + c = cos (bin->angle); + + gtk_widget_get_child_requisition (bin->child, &child_requisition); + child_allocation.x = 0; + child_allocation.y = 0; + child_allocation.height = child_requisition.height; + if (c == 0.0) + child_allocation.width = h / s; + else if (s == 0.0) + child_allocation.width = w / c; + else + child_allocation.width = MIN ((w - s * child_allocation.height) / c, + (h - c * child_allocation.height) / s); + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (bin->offscreen_window, + child_allocation.x, + child_allocation.y, + child_allocation.width, + child_allocation.height); + + child_allocation.x = child_allocation.y = 0; + gtk_widget_size_allocate (bin->child, &child_allocation); + } +} + +static gboolean +gtk_rotated_bin_damage (GtkWidget *widget, + GdkEventExpose *event) +{ + gdk_window_invalidate_rect (widget->window, NULL, FALSE); + + return TRUE; +} + +static gboolean +gtk_rotated_bin_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + GtkRotatedBin *bin = GTK_ROTATED_BIN (widget); + gint width, height; + gdouble s, c; + gdouble w, h; + + if (GTK_WIDGET_DRAWABLE (widget)) + { + if (event->window == widget->window) + { + GdkPixmap *pixmap; + GtkAllocation child_area; + cairo_t *cr; + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + pixmap = gdk_offscreen_window_get_pixmap (bin->offscreen_window); + child_area = bin->child->allocation; + + cr = gdk_cairo_create (widget->window); + + /* transform */ + s = sin (bin->angle); + c = cos (bin->angle); + w = c * child_area.width + s * child_area.height; + h = s * child_area.width + c * child_area.height; + + cairo_translate (cr, (w - child_area.width) / 2, (h - child_area.height) / 2); + cairo_translate (cr, child_area.width / 2, child_area.height / 2); + cairo_rotate (cr, bin->angle); + cairo_translate (cr, -child_area.width / 2, -child_area.height / 2); + + /* clip */ + gdk_drawable_get_size (pixmap, &width, &height); + cairo_rectangle (cr, 0, 0, width, height); + cairo_clip (cr); + /* paint */ + gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0); + cairo_paint (cr); + + cairo_destroy (cr); + } + } + else if (event->window == bin->offscreen_window) + { + gtk_paint_flat_box (widget->style, event->window, + GTK_STATE_NORMAL, GTK_SHADOW_NONE, + &event->area, widget, "blah", + 0, 0, -1, -1); + + if (bin->child) + gtk_container_propagate_expose (GTK_CONTAINER (widget), + bin->child, + event); + } + } + + return FALSE; +} + +/*** ***/ + +static void +scale_changed (GtkRange *range, + GtkRotatedBin *bin) +{ + gtk_rotated_bin_set_angle (bin, gtk_range_get_value (range)); +} + +static GtkWidget *window = NULL; + +GtkWidget * +do_offscreen_window (GtkWidget *do_widget) +{ + if (!window) + { + GtkWidget *bin, *vbox, *scale, *button; + GdkColor black; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_screen (GTK_WINDOW (window), + gtk_widget_get_screen (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "Rotated widget"); + + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_widget_destroyed), &window); + + gdk_color_parse ("black", &black); + gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &black); + gtk_container_set_border_width (GTK_CONTAINER (window), 10); + + vbox = gtk_vbox_new (0, FALSE); + scale = gtk_hscale_new_with_range (0, G_PI/2, 0.01); + gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); + + button = gtk_button_new_with_label ("A Button"); + bin = gtk_rotated_bin_new (); + + g_signal_connect (scale, "value-changed", G_CALLBACK (scale_changed), bin); + + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), bin, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (bin), button); + } + + 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/offscreen_window2.c b/demos/gtk-demo/offscreen_window2.c new file mode 100644 index 0000000000..19ca760bda --- /dev/null +++ b/demos/gtk-demo/offscreen_window2.c @@ -0,0 +1,500 @@ +/* Offscreen windows/Effects + * + * Offscreen windows can be used to render elements multiple times to achieve + * various effects. + */ +#include <gtk/gtk.h> + +#define GTK_TYPE_MIRROR_BIN (gtk_mirror_bin_get_type ()) +#define GTK_MIRROR_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MIRROR_BIN, GtkMirrorBin)) +#define GTK_MIRROR_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_MIRROR_BIN, GtkMirrorBinClass)) +#define GTK_IS_MIRROR_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_MIRROR_BIN)) +#define GTK_IS_MIRROR_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_MIRROR_BIN)) +#define GTK_MIRROR_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MIRROR_BIN, GtkMirrorBinClass)) + +typedef struct _GtkMirrorBin GtkMirrorBin; +typedef struct _GtkMirrorBinClass GtkMirrorBinClass; + +struct _GtkMirrorBin +{ + GtkContainer container; + + GtkWidget *child; + GdkWindow *offscreen_window; +}; + +struct _GtkMirrorBinClass +{ + GtkContainerClass parent_class; +}; + +GType gtk_mirror_bin_get_type (void) G_GNUC_CONST; +GtkWidget* gtk_mirror_bin_new (void); + +/*** implementation ***/ + +static void gtk_mirror_bin_realize (GtkWidget *widget); +static void gtk_mirror_bin_unrealize (GtkWidget *widget); +static void gtk_mirror_bin_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_mirror_bin_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gboolean gtk_mirror_bin_damage (GtkWidget *widget, + GdkEventExpose *event); +static gboolean gtk_mirror_bin_expose (GtkWidget *widget, + GdkEventExpose *offscreen); + +static void gtk_mirror_bin_add (GtkContainer *container, + GtkWidget *child); +static void gtk_mirror_bin_remove (GtkContainer *container, + GtkWidget *widget); +static void gtk_mirror_bin_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static GType gtk_mirror_bin_child_type (GtkContainer *container); + +G_DEFINE_TYPE (GtkMirrorBin, gtk_mirror_bin, GTK_TYPE_CONTAINER); + +static void +to_child (GtkMirrorBin *bin, + double widget_x, + double widget_y, + double *x_out, + double *y_out) +{ + *x_out = widget_x; + *y_out = widget_y; +} + +static void +to_parent (GtkMirrorBin *bin, + double offscreen_x, + double offscreen_y, + double *x_out, + double *y_out) +{ + *x_out = offscreen_x; + *y_out = offscreen_y; +} + +static void +gtk_mirror_bin_class_init (GtkMirrorBinClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); + + widget_class->realize = gtk_mirror_bin_realize; + widget_class->unrealize = gtk_mirror_bin_unrealize; + widget_class->size_request = gtk_mirror_bin_size_request; + widget_class->size_allocate = gtk_mirror_bin_size_allocate; + widget_class->expose_event = gtk_mirror_bin_expose; + + g_signal_override_class_closure (g_signal_lookup ("damage-event", GTK_TYPE_WIDGET), + GTK_TYPE_MIRROR_BIN, + g_cclosure_new (G_CALLBACK (gtk_mirror_bin_damage), + NULL, NULL)); + + container_class->add = gtk_mirror_bin_add; + container_class->remove = gtk_mirror_bin_remove; + container_class->forall = gtk_mirror_bin_forall; + container_class->child_type = gtk_mirror_bin_child_type; +} + +static void +gtk_mirror_bin_init (GtkMirrorBin *bin) +{ + GTK_WIDGET_UNSET_FLAGS (bin, GTK_NO_WINDOW); +} + +GtkWidget * +gtk_mirror_bin_new (void) +{ + return g_object_new (GTK_TYPE_MIRROR_BIN, NULL); +} + +static GdkWindow * +pick_offscreen_child (GdkWindow *offscreen_window, + double widget_x, + double widget_y, + GtkMirrorBin *bin) +{ + GtkAllocation child_area; + double x, y; + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + to_child (bin, widget_x, widget_y, &x, &y); + + child_area = bin->child->allocation; + + if (x >= 0 && x < child_area.width && + y >= 0 && y < child_area.height) + return bin->offscreen_window; + } + + return NULL; +} + +static void +offscreen_window_to_parent (GdkWindow *offscreen_window, + double offscreen_x, + double offscreen_y, + double *parent_x, + double *parent_y, + GtkMirrorBin *bin) +{ + to_parent (bin, offscreen_x, offscreen_y, parent_x, parent_y); +} + +static void +offscreen_window_from_parent (GdkWindow *window, + double parent_x, + double parent_y, + double *offscreen_x, + double *offscreen_y, + GtkMirrorBin *bin) +{ + to_child (bin, parent_x, parent_y, offscreen_x, offscreen_y); +} + +static void +gtk_mirror_bin_realize (GtkWidget *widget) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (widget); + GdkWindowAttr attributes; + gint attributes_mask; + gint border_width; + GtkRequisition child_requisition; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + border_width = GTK_CONTAINER (widget)->border_width; + + attributes.x = widget->allocation.x + border_width; + attributes.y = widget->allocation.y + border_width; + attributes.width = widget->allocation.width - 2 * border_width; + attributes.height = widget->allocation.height - 2 * border_width; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = gtk_widget_get_events (widget) + | GDK_EXPOSURE_MASK + | GDK_POINTER_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_SCROLL_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK; + + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.wclass = GDK_INPUT_OUTPUT; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); + g_signal_connect (widget->window, "pick-embedded-child", + G_CALLBACK (pick_offscreen_child), bin); + + attributes.window_type = GDK_WINDOW_OFFSCREEN; + + child_requisition.width = child_requisition.height = 0; + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + attributes.width = bin->child->allocation.width; + attributes.height = bin->child->allocation.height; + } + bin->offscreen_window = gdk_window_new (gtk_widget_get_root_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (bin->offscreen_window, widget); + if (bin->child) + gtk_widget_set_parent_window (bin->child, bin->offscreen_window); + gdk_offscreen_window_set_embedder (bin->offscreen_window, widget->window); + g_signal_connect (bin->offscreen_window, "to-embedder", + G_CALLBACK (offscreen_window_to_parent), bin); + g_signal_connect (bin->offscreen_window, "from-embedder", + G_CALLBACK (offscreen_window_from_parent), bin); + + widget->style = gtk_style_attach (widget->style, widget->window); + + gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + gtk_style_set_background (widget->style, bin->offscreen_window, GTK_STATE_NORMAL); + gdk_window_show (bin->offscreen_window); +} + +static void +gtk_mirror_bin_unrealize (GtkWidget *widget) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (widget); + + gdk_window_set_user_data (bin->offscreen_window, NULL); + gdk_window_destroy (bin->offscreen_window); + bin->offscreen_window = NULL; + + GTK_WIDGET_CLASS (gtk_mirror_bin_parent_class)->unrealize (widget); +} + +static GType +gtk_mirror_bin_child_type (GtkContainer *container) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (container); + + if (bin->child) + return G_TYPE_NONE; + + return GTK_TYPE_WIDGET; +} + +static void +gtk_mirror_bin_add (GtkContainer *container, + GtkWidget *widget) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (container); + + if (!bin->child) + { + gtk_widget_set_parent_window (widget, bin->offscreen_window); + gtk_widget_set_parent (widget, GTK_WIDGET (bin)); + bin->child = widget; + } + else + g_warning ("GtkMirrorBin cannot have more than one child\n"); +} + +static void +gtk_mirror_bin_remove (GtkContainer *container, + GtkWidget *widget) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (container); + gboolean was_visible; + + was_visible = GTK_WIDGET_VISIBLE (widget); + + if (bin->child == widget) + { + gtk_widget_unparent (widget); + + bin->child = NULL; + + if (was_visible && GTK_WIDGET_VISIBLE (container)) + gtk_widget_queue_resize (GTK_WIDGET (container)); + } +} + +static void +gtk_mirror_bin_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (container); + + g_return_if_fail (callback != NULL); + + if (bin->child) + (*callback) (bin->child, callback_data); +} + +static void +gtk_mirror_bin_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (widget); + GtkRequisition child_requisition; + + child_requisition.width = 0; + child_requisition.height = 0; + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + gtk_widget_size_request (bin->child, &child_requisition); + + requisition->width = GTK_CONTAINER (widget)->border_width * 2 + child_requisition.width + 10; + requisition->height = GTK_CONTAINER (widget)->border_width * 2 + child_requisition.height * 2 + 10; +} + +static void +gtk_mirror_bin_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (widget); + gint border_width; + gint w, h; + widget->allocation = *allocation; + + border_width = GTK_CONTAINER (widget)->border_width; + + w = allocation->width - border_width * 2; + h = allocation->height - border_width * 2; + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (widget->window, + allocation->x + border_width, + allocation->y + border_width, + w, h); + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + GtkRequisition child_requisition; + GtkAllocation child_allocation; + + gtk_widget_get_child_requisition (bin->child, &child_requisition); + child_allocation.x = 0; + child_allocation.y = 0; + child_allocation.height = child_requisition.height; + child_allocation.width = child_requisition.width; + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (bin->offscreen_window, + allocation->x + border_width, + allocation->y + border_width, + child_allocation.width, child_allocation.height); + gtk_widget_size_allocate (bin->child, &child_allocation); + } +} + +static gboolean +gtk_mirror_bin_damage (GtkWidget *widget, + GdkEventExpose *event) +{ + gdk_window_invalidate_rect (widget->window, NULL, FALSE); + + return TRUE; +} + +static gboolean +gtk_mirror_bin_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + GtkMirrorBin *bin = GTK_MIRROR_BIN (widget); + gint width, height; + + if (GTK_WIDGET_DRAWABLE (widget)) + { + if (event->window == widget->window) + { + GdkPixmap *pixmap; + cairo_t *cr; + cairo_matrix_t matrix; + cairo_pattern_t *mask; + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + pixmap = gdk_offscreen_window_get_pixmap (bin->offscreen_window); + gdk_drawable_get_size (pixmap, &width, &height); + + cr = gdk_cairo_create (widget->window); + + cairo_save (cr); + + cairo_rectangle (cr, 0, 0, width, height); + cairo_clip (cr); + + /* paint the offscreen child */ + gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0); + cairo_paint (cr); + + cairo_restore (cr); + + cairo_matrix_init (&matrix, 1.0, 0.0, 0.3, 1.0, 0.0, 0.0); + cairo_matrix_scale (&matrix, 1.0, -1.0); + cairo_matrix_translate (&matrix, -10, - 3 * height - 10); + cairo_transform (cr, &matrix); + + cairo_rectangle (cr, 0, height, width, height); + cairo_clip (cr); + + gdk_cairo_set_source_pixmap (cr, pixmap, 0, height); + + /* create linear gradient as mask-pattern to fade out the source */ + mask = cairo_pattern_create_linear (0.0, height, 0.0, 2*height); + cairo_pattern_add_color_stop_rgba (mask, 0.0, 0.0, 0.0, 0.0, 0.0); + cairo_pattern_add_color_stop_rgba (mask, 0.25, 0.0, 0.0, 0.0, 0.01); + cairo_pattern_add_color_stop_rgba (mask, 0.5, 0.0, 0.0, 0.0, 0.25); + cairo_pattern_add_color_stop_rgba (mask, 0.75, 0.0, 0.0, 0.0, 0.5); + cairo_pattern_add_color_stop_rgba (mask, 1.0, 0.0, 0.0, 0.0, 1.0); + + /* paint the reflection */ + cairo_mask (cr, mask); + + cairo_pattern_destroy (mask); + cairo_destroy (cr); + } + } + else if (event->window == bin->offscreen_window) + { + gtk_paint_flat_box (widget->style, event->window, + GTK_STATE_NORMAL, GTK_SHADOW_NONE, + &event->area, widget, "blah", + 0, 0, -1, -1); + + if (bin->child) + gtk_container_propagate_expose (GTK_CONTAINER (widget), + bin->child, + event); + } + } + + return FALSE; +} + +/*** ***/ + +static GtkWidget *window = NULL; + +GtkWidget * +do_offscreen_window2 (GtkWidget *do_widget) +{ + if (!window) + { + GtkWidget *bin, *vbox; + GtkWidget *hbox, *entry, *applybutton, *backbutton; + GtkSizeGroup *group; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_screen (GTK_WINDOW (window), + gtk_widget_get_screen (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "Effects"); + + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_widget_destroyed), &window); + + gtk_container_set_border_width (GTK_CONTAINER (window), 10); + + vbox = gtk_vbox_new (0, FALSE); + + bin = gtk_mirror_bin_new (); + + group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); + + hbox = gtk_hbox_new (FALSE, 6); + backbutton = gtk_button_new (); + gtk_container_add (GTK_CONTAINER (backbutton), + gtk_image_new_from_stock (GTK_STOCK_GO_BACK, 4)); + gtk_size_group_add_widget (group, backbutton); + entry = gtk_entry_new (); + gtk_size_group_add_widget (group, entry); + applybutton = gtk_button_new (); + gtk_size_group_add_widget (group, applybutton); + gtk_container_add (GTK_CONTAINER (applybutton), + gtk_image_new_from_stock (GTK_STOCK_APPLY, 4)); + + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_box_pack_start (GTK_BOX (vbox), bin, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (bin), hbox); + gtk_box_pack_start (GTK_BOX (hbox), backbutton, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), applybutton, FALSE, FALSE, 0); + } + + 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/printing.c b/demos/gtk-demo/printing.c index 07c7ab2838..124eed905f 100644 --- a/demos/gtk-demo/printing.c +++ b/demos/gtk-demo/printing.c @@ -174,6 +174,8 @@ do_printing (GtkWidget *do_widget) dir = g_get_home_dir (); if (g_strcmp0 (gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT), "ps") == 0) ext = ".ps"; + else if (g_strcmp0 (gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT), "svg") == 0) + ext = ".svg"; else ext = ".pdf"; diff --git a/demos/gtk-demo/spinner.c b/demos/gtk-demo/spinner.c new file mode 100644 index 0000000000..314c922206 --- /dev/null +++ b/demos/gtk-demo/spinner.c @@ -0,0 +1,94 @@ +/* Spinner + * + * GtkSpinner allows to show that background activity is on-going. + * + */ + +#include <gtk/gtk.h> + +static GtkWidget *window = NULL; +static GtkWidget *spinner_sensitive = NULL; +static GtkWidget *spinner_unsensitive = NULL; + +static void +on_play_clicked (GtkButton *button, gpointer user_data) +{ + gtk_spinner_start (GTK_SPINNER (spinner_sensitive)); + gtk_spinner_start (GTK_SPINNER (spinner_unsensitive)); +} + +static void +on_stop_clicked (GtkButton *button, gpointer user_data) +{ + gtk_spinner_stop (GTK_SPINNER (spinner_sensitive)); + gtk_spinner_stop (GTK_SPINNER (spinner_unsensitive)); +} + +GtkWidget * +do_spinner (GtkWidget *do_widget) +{ + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *button; + GtkWidget *spinner; + + if (!window) + { + window = gtk_dialog_new_with_buttons ("GtkSpinner", + GTK_WINDOW (do_widget), + 0, + GTK_STOCK_CLOSE, + GTK_RESPONSE_NONE, + NULL); + gtk_window_set_resizable (GTK_WINDOW (window), FALSE); + + g_signal_connect (window, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_widget_destroyed), &window); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); + + /* Sensitive */ + hbox = gtk_hbox_new (FALSE, 5); + spinner = gtk_spinner_new (); + gtk_container_add (GTK_CONTAINER (hbox), spinner); + gtk_container_add (GTK_CONTAINER (hbox), gtk_entry_new ()); + gtk_container_add (GTK_CONTAINER (vbox), hbox); + spinner_sensitive = spinner; + + /* Disabled */ + hbox = gtk_hbox_new (FALSE, 5); + spinner = gtk_spinner_new (); + gtk_container_add (GTK_CONTAINER (hbox), spinner); + gtk_container_add (GTK_CONTAINER (hbox), gtk_entry_new ()); + gtk_container_add (GTK_CONTAINER (vbox), hbox); + spinner_unsensitive = spinner; + gtk_widget_set_sensitive (hbox, FALSE); + + button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PLAY); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (on_play_clicked), spinner); + gtk_container_add (GTK_CONTAINER (vbox), button); + + button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_STOP); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (on_stop_clicked), spinner); + gtk_container_add (GTK_CONTAINER (vbox), button); + + /* Start by default to test for: + * https://bugzilla.gnome.org/show_bug.cgi?id=598496 */ + on_play_clicked (NULL, NULL); + } + + if (!GTK_WIDGET_VISIBLE (window)) + gtk_widget_show_all (window); + else + gtk_widget_destroy (window); + + return window; +} + + |