diff options
author | Havoc Pennington <hp@redhat.com> | 2000-10-20 23:14:41 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2000-10-20 23:14:41 +0000 |
commit | 1c9f0c0bac5e73d80968fc791568f1566e3ec5e6 (patch) | |
tree | a274b213438121a8a69c6a61318322b94164d59e /gtk | |
parent | 779e461e89dc5d423d9d5440d76e1f607b074b21 (diff) | |
download | gtk+-1c9f0c0bac5e73d80968fc791568f1566e3ec5e6.tar.gz |
create some stock buttons with the default accel group (create_image):
2000-10-04 Havoc Pennington <hp@redhat.com>
* gtk/testgtk.c (create_buttons): create some stock buttons
with the default accel group
(create_image): test some new GtkImage features
(make_message_dialog): test GtkMessageDialog
(create_modal_window): fix someone's bizzarro indentation
* gtk/gtkwindow.h, gtk/gtkwindow.c: Implement
GTK_WIN_POS_CENTER_ON_PARENT.
Add "destroy with parent" setting, which means the window goes
away with its transient parent.
(gtk_window_get_default_accel_group): get the default accel group
for the window.
(gtk_window_set_destroy_with_parent): set/unset destroy with
parent flag
(gtk_window_read_rcfiles): invalidate icon set caches
after reloading rcfiles
* gtk/gtkenums.h (GtkWindowPosition): add
GTK_WIN_POS_CENTER_ON_PARENT, which centers a dialog
on its parent window when the dialog is mapped for the first time.
* gtk/gtkmessagedialog.h, gtk/gtkmessagedialog.c: Add
a simple message dialog class
* gtk/gtkdialog.c (gtk_dialog_init): Connect delete event
handler to emit response signal, and maybe later it would
honor a hide_on_delete flag - though that isn't there yet.
Set border width on the vbox to 2, so we get some padding.
Use a button box for the action area.
(gtk_dialog_key_press): synthesize a delete event if Esc
is pressed and the GtkWidget key press handler didn't
handle the escape key.
(gtk_dialog_new_with_buttons): new function creates a dialog
with some default buttons in it.
(gtk_dialog_add_action_widget): add an activatable widget
as a button in the dialog - you can also add a non-activatable
widget by accessing the action area directly.
(gtk_dialog_add_button): add a simple button - stock ID or
label - to the action area
(gtk_dialog_response): emit response signal
(gtk_dialog_run): block waiting for the dialog, return
the response. Override normal delete_event behavior, so that
delete_event does nothing inside gtk_dialog_run().
* gtk/gtkdialog.h, gtk/gtkdialog.c: Add "response" signal
emitted when an action widget is clicked or the dialog gets
delete_event
* gtk/gtk.h: add gtkmessagedialog.h
* gtk/Makefile.am: add gtkmessagedialog.[hc]
2000-10-20 Havoc Pennington <hp@redhat.com>
* gtk/gtk-sections.txt: Add dialog docs
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/Makefile.am | 2 | ||||
-rw-r--r-- | gtk/gtk.h | 1 | ||||
-rw-r--r-- | gtk/gtkdialog.c | 550 | ||||
-rw-r--r-- | gtk/gtkdialog.h | 57 | ||||
-rw-r--r-- | gtk/gtkenums.h | 3 | ||||
-rw-r--r-- | gtk/gtkmessagedialog.c | 251 | ||||
-rw-r--r-- | gtk/gtkmessagedialog.h | 98 | ||||
-rw-r--r-- | gtk/gtkwindow.c | 145 | ||||
-rw-r--r-- | gtk/gtkwindow.h | 5 | ||||
-rw-r--r-- | gtk/testgtk.c | 134 | ||||
-rw-r--r-- | gtk/testgtkrc | 10 |
11 files changed, 1229 insertions, 27 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 5687bde019..14921862af 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -122,6 +122,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \ gtkmenufactory.h \ gtkmenuitem.h \ gtkmenushell.h \ + gtkmessagedialog.h \ gtkmisc.h \ gtkmodelsimple.h \ gtknotebook.h \ @@ -290,6 +291,7 @@ gtk_c_sources = @STRIP_BEGIN@ \ gtkmenufactory.c \ gtkmenuitem.c \ gtkmenushell.c \ + gtkmessagedialog.c \ gtkmisc.c \ gtkmodelsimple.c \ gtknotebook.c \ @@ -99,6 +99,7 @@ #include <gtk/gtkmenufactory.h> #include <gtk/gtkmenuitem.h> #include <gtk/gtkmenushell.h> +#include <gtk/gtkmessagedialog.h> #include <gtk/gtkmisc.h> #include <gtk/gtkmodelsimple.h> #include <gtk/gtknotebook.h> diff --git a/gtk/gtkdialog.c b/gtk/gtkdialog.c index 41d8a3e236..d21be69c24 100644 --- a/gtk/gtkdialog.c +++ b/gtk/gtkdialog.c @@ -26,14 +26,34 @@ #include "gtkbutton.h" #include "gtkdialog.h" -#include "gtkhbox.h" +#include "gtkhbbox.h" #include "gtkhseparator.h" #include "gtkvbox.h" - +#include "gtksignal.h" +#include "gdkkeysyms.h" +#include "gtkmain.h" static void gtk_dialog_class_init (GtkDialogClass *klass); static void gtk_dialog_init (GtkDialog *dialog); +static gint gtk_dialog_key_press (GtkWidget *widget, + GdkEventKey *key); + +static void gtk_dialog_add_buttons_valist (GtkDialog *dialog, + const gchar *first_button_text, + va_list args); + +static gint gtk_dialog_delete_event_handler (GtkWidget *widget, + GdkEventAny *event, + gpointer user_data); + + +enum { + RESPONSE, + LAST_SIGNAL +}; +static gpointer parent_class; +static guint dialog_signals[LAST_SIGNAL]; GtkType gtk_dialog_get_type (void) @@ -63,6 +83,26 @@ gtk_dialog_get_type (void) static void gtk_dialog_class_init (GtkDialogClass *class) { + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + + parent_class = g_type_class_peek_parent (class); + + dialog_signals[RESPONSE] = + gtk_signal_new ("response", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkDialogClass, response), + gtk_marshal_NONE__INT, + GTK_TYPE_NONE, 1, + GTK_TYPE_INT); + + gtk_object_class_add_signals (object_class, dialog_signals, LAST_SIGNAL); + + widget_class->key_press_event = gtk_dialog_key_press; } static void @@ -70,13 +110,30 @@ gtk_dialog_init (GtkDialog *dialog) { GtkWidget *separator; + /* To avoid breaking old code that prevents destroy on delete event + * by connecting a handler, we have to have the FIRST signal + * connection on the dialog. + */ + gtk_signal_connect (GTK_OBJECT (dialog), + "delete_event", + GTK_SIGNAL_FUNC (gtk_dialog_delete_event_handler), + NULL); + dialog->vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 2); + gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox); gtk_widget_show (dialog->vbox); - dialog->action_area = gtk_hbox_new (TRUE, 5); + dialog->action_area = gtk_hbutton_box_new (); + + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog->action_area), + GTK_BUTTONBOX_SPREAD); + gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 10); - gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area, FALSE, TRUE, 0); + gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area, + FALSE, TRUE, 0); gtk_widget_show (dialog->action_area); separator = gtk_hseparator_new (); @@ -84,8 +141,493 @@ gtk_dialog_init (GtkDialog *dialog) gtk_widget_show (separator); } +static gint +gtk_dialog_delete_event_handler (GtkWidget *widget, + GdkEventAny *event, + gpointer user_data) +{ + /* emit response signal */ + gtk_dialog_response (GTK_DIALOG (widget), GTK_RESPONSE_NONE); + + /* Do the destroy by default */ + return FALSE; +} + +static gint +gtk_dialog_key_press (GtkWidget *widget, + GdkEventKey *key) +{ + GdkEventAny event; + + event.type = GDK_DELETE; + event.window = widget->window; + event.send_event = TRUE; + + if (GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, key)) + return TRUE; + + if (key->keyval != GDK_Escape) + return FALSE; + + /* Synthesize delete_event on key press. */ + g_object_ref (G_OBJECT (event.window)); + + gtk_main_do_event ((GdkEvent*)&event); + + g_object_unref (G_OBJECT (event.window)); + + return TRUE; +} + GtkWidget* gtk_dialog_new (void) { return GTK_WIDGET (gtk_type_new (GTK_TYPE_DIALOG)); } + +static GtkWidget* +gtk_dialog_new_empty (const gchar *title, + GtkWindow *parent, + GtkDialogFlags flags) +{ + GtkDialog *dialog; + + dialog = GTK_DIALOG (g_object_new (GTK_TYPE_DIALOG, NULL)); + + if (title) + gtk_window_set_title (GTK_WINDOW (dialog), title); + + if (parent) + gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); + + if (flags & GTK_DIALOG_MODAL) + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + if (flags & GTK_DIALOG_DESTROY_WITH_PARENT) + gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); + + return GTK_WIDGET (dialog); +} + +/** + * gtk_dialog_new_with_buttons: + * @title: Title of the dialog, or NULL + * @parent: Transient parent of the dialog, or NULL + * @flags: from #GtkDialogFlags + * @first_button_text: stock ID or text to go in first button, or NULL + * @Varargs: response ID for first button, then additional buttons, ending with NULL + * + * Creates a new #GtkDialog with title @title (or NULL for the default + * title; see gtk_window_set_title()) and transient parent @parent (or + * NULL for none; see gtk_window_set_transient_for()). The @flags + * argument can be used to make the dialog modal (GTK_DIALOG_MODAL) + * and/or to have it destroyed along with its transient parent + * (GTK_DIALOG_DESTROY_WITH_PARENT). After @flags, button + * text/response ID pairs should be listed, with a NULL pointer ending + * the list. Button text can be either a stock ID such as + * GTK_STOCK_BUTTON_OK, or some arbitrary text. A response ID can be + * any positive number, or one of the values in the #GtkResponseType + * enumeration. If the user clicks one of these dialog buttons, + * #GtkDialog will emit the "response" signal with the corresponding + * response ID. If a #GtkDialog receives the "delete_event" signal, it + * will emit "response" with a response ID of GTK_RESPONSE_NONE. + * However, destroying a dialog does not emit the "response" signal; + * so be careful relying on "response" when using + * the GTK_DIALOG_DESTROY_WITH_PARENT flag. Buttons are from left to right, + * so the first button in the list will be the leftmost button in the dialog. + * + * Here's a simple example: + * <programlisting> + * GtkWidget *dialog = gtk_dialog_new_with_buttons ("My dialog", + * main_app_window, + * GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + * GTK_STOCK_BUTTON_OK, + * GTK_RESPONSE_ACCEPT, + * GTK_STOCK_BUTTON_CANCEL, + * GTK_RESPONSE_NONE, + * NULL); + * </programlisting> + * + * Return value: a new #GtkDialog + **/ +GtkWidget* +gtk_dialog_new_with_buttons (const gchar *title, + GtkWindow *parent, + GtkDialogFlags flags, + const gchar *first_button_text, + ...) +{ + GtkDialog *dialog; + va_list args; + + dialog = GTK_DIALOG (gtk_dialog_new_empty (title, parent, flags)); + + va_start (args, first_button_text); + + gtk_dialog_add_buttons_valist (dialog, + first_button_text, + args); + + va_end (args); + + return GTK_WIDGET (dialog); +} + +typedef struct _ResponseData ResponseData; + +struct _ResponseData +{ + gint response_id; +}; + +static ResponseData* +get_response_data (GtkWidget *widget) +{ + ResponseData *ad = gtk_object_get_data (GTK_OBJECT (widget), + "gtk-dialog-response-data"); + + if (ad == NULL) + { + ad = g_new (ResponseData, 1); + + gtk_object_set_data_full (GTK_OBJECT (widget), + "gtk-dialog-response-data", + ad, + g_free); + } + + return ad; +} + +static void +action_widget_activated (GtkWidget *widget, GtkDialog *dialog) +{ + ResponseData *ad; + gint response_id; + + g_return_if_fail (GTK_IS_DIALOG (dialog)); + + response_id = GTK_RESPONSE_NONE; + + ad = get_response_data (widget); + + g_assert (ad != NULL); + + response_id = ad->response_id; + + gtk_dialog_response (dialog, response_id); +} +/** + * gtk_dialog_add_action_widget: + * @dialog: a #GtkDialog + * @child: an activatable widget + * @response_id: response ID for @child + * + * Adds an activatable widget to the action area of a #GtkDialog, + * connecting a signal handler that will emit the "response" signal on + * the dialog when the widget is activated. The widget is appended to + * the end of the dialog's action area. If you want to add a + * non-activatable widget, simply pack it into the + * <literal>action_area</literal> field of the #GtkDialog struct. + * + **/ +void +gtk_dialog_add_action_widget (GtkDialog *dialog, + GtkWidget *child, + gint response_id) +{ + ResponseData *ad; + + g_return_if_fail (GTK_IS_DIALOG (dialog)); + g_return_if_fail (GTK_IS_WIDGET (child)); + + ad = get_response_data (child); + + ad->response_id = response_id; + + if (GTK_WIDGET_GET_CLASS (child)->activate_signal != 0) + { + const gchar* name = + gtk_signal_name (GTK_WIDGET_GET_CLASS (child)->activate_signal); + + gtk_signal_connect_while_alive (GTK_OBJECT (child), + name, + GTK_SIGNAL_FUNC (action_widget_activated), + dialog, + GTK_OBJECT (dialog)); + } + else + g_warning ("Only 'activatable' widgets can be packed into the action area of a GtkDialog"); + + gtk_box_pack_end (GTK_BOX (dialog->action_area), + child, + FALSE, TRUE, 5); +} + +/** + * gtk_dialog_add_button: + * @dialog: a #GtkDialog + * @button_text: text of button, or stock ID + * @response_id: response ID for the button + * + * Adds a button with the given text (or a stock button, if @button_text is a + * stock ID) and sets things up so that clicking the button will emit the + * "response" signal with the given @response_id. The button is appended to the + * end of the dialog's action area. + * + **/ +void +gtk_dialog_add_button (GtkDialog *dialog, + const gchar *button_text, + gint response_id) +{ + GtkWidget *button; + + g_return_if_fail (GTK_IS_DIALOG (dialog)); + g_return_if_fail (button_text != NULL); + + button = gtk_button_new_stock (button_text, + gtk_window_get_default_accel_group (GTK_WINDOW (dialog))); + + gtk_widget_show (button); + + gtk_dialog_add_action_widget (dialog, + button, + response_id); +} + +static void +gtk_dialog_add_buttons_valist(GtkDialog *dialog, + const gchar *first_button_text, + va_list args) +{ + const gchar* text; + gint response_id; + + if (first_button_text == NULL) + return; + + text = first_button_text; + response_id = va_arg (args, gint); + + while (text != NULL) + { + gtk_dialog_add_button (dialog, text, response_id); + + text = va_arg (args, gchar*); + if (text == NULL) + break; + response_id = va_arg (args, int); + } +} + +/** + * gtk_dialog_add_buttons: + * @dialog: a #GtkDialog + * @first_button_text: button text or stock ID + * @Varargs: response ID for first button, then more text-response_id pairs + * + * Adds more buttons, same as calling gtk_dialog_add_button() + * repeatedly. The variable argument list should be NULL-terminated + * as with gtk_dialog_new_with_buttons(). Each button must have both + * text and response ID. + * + **/ +void +gtk_dialog_add_buttons (GtkDialog *dialog, + const gchar *first_button_text, + ...) +{ + + va_list args; + + va_start (args, first_button_text); + + gtk_dialog_add_buttons_valist (dialog, + first_button_text, + args); + + va_end (args); +} + +/** + * gtk_dialog_response: + * @dialog: a #GtkDialog + * @response_id: response ID + * + * Emits the "response" signal with the given response ID. Used to + * indicate that the user has responded to the dialog in some way; + * typically either you or gtk_dialog_run() will be monitoring the + * "response" signal and take appropriate action. + **/ +void +gtk_dialog_response (GtkDialog *dialog, + gint response_id) +{ + g_return_if_fail (dialog != NULL); + g_return_if_fail (GTK_IS_DIALOG (dialog)); + + gtk_signal_emit (GTK_OBJECT (dialog), + dialog_signals[RESPONSE], + response_id); +} + +typedef struct +{ + GtkDialog *dialog; + gint response_id; + GMainLoop *loop; +} RunInfo; + +static void +shutdown_loop (RunInfo *ri) +{ + if (ri->loop != NULL) + { + g_main_quit (ri->loop); + g_main_destroy (ri->loop); + ri->loop = NULL; + } +} + +static void +run_destroy_handler (GtkDialog *dialog, gpointer data) +{ + RunInfo *ri = data; + + shutdown_loop (ri); +} + +static void +run_response_handler (GtkDialog *dialog, + gint response_id, + gpointer data) +{ + RunInfo *ri; + + ri = data; + + ri->response_id = response_id; + + shutdown_loop (ri); +} + +static gint +run_delete_handler (GtkDialog *dialog, + GdkEventAny *event, + gpointer data) +{ + RunInfo *ri = data; + + shutdown_loop (ri); + + /* emit response signal */ + gtk_dialog_response (dialog, GTK_RESPONSE_NONE); + + return TRUE; /* Do not destroy */ +} + +/** + * gtk_dialog_run: + * @dialog: a #GtkDialog + * + * Blocks in a recursive main loop until the @dialog either emits the + * response signal, or is destroyed. If the dialog is destroyed, + * gtk_dialog_run() returns GTK_RESPONSE_NONE. Otherwise, it returns + * the response ID from the "response" signal emission. Before + * entering the recursive main loop, gtk_dialog_run() calls + * gtk_widget_show() on the dialog for you. Note that you still + * need to show any children of the dialog yourself. + * + * During gtk_dialog_run(), the default behavior of "delete_event" is + * disabled; if the dialog receives "delete_event", it will not be + * destroyed as windows usually are, and gtk_dialog_run() will return + * GTK_RESPONSE_NONE. Also, during gtk_dialog_run() the dialog will be + * modal. You can force gtk_dialog_run() to return at any time by + * calling gtk_dialog_response() to emit the "response" + * signal. Destroying the dialog during gtk_dialog_run() is a very bad + * idea, because your post-run code won't know whether the dialog was + * destroyed or not. + * + * After gtk_dialog_run() returns, you are responsible for hiding or + * destroying the dialog if you wish to do so. + * + * Typical usage of this function might be: + * <programlisting> + * gint result = gtk_dialog_run (GTK_DIALOG (dialog)); + * switch (result) + * { + * case GTK_RESPONSE_ACCEPT: + * do_application_specific_something (); + * break; + * default: + * do_nothing_since_dialog_was_cancelled (); + * break; + * } + * gtk_widget_destroy (dialog); + * </programlisting> + * + * Return value: response ID + **/ +gint +gtk_dialog_run (GtkDialog *dialog) +{ + RunInfo ri = { NULL, GTK_RESPONSE_NONE, NULL }; + gboolean was_modal; + guint response_handler; + guint destroy_handler; + guint delete_handler; + + g_return_val_if_fail (GTK_IS_DIALOG (dialog), -1); + + gtk_object_ref (GTK_OBJECT (dialog)); + + if (!GTK_WIDGET_VISIBLE (dialog)) + gtk_widget_show (GTK_WIDGET (dialog)); + + was_modal = GTK_WINDOW (dialog)->modal; + if (!was_modal) + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + response_handler = + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (run_response_handler), + &ri); + + destroy_handler = + gtk_signal_connect (GTK_OBJECT (dialog), + "destroy", + GTK_SIGNAL_FUNC (run_destroy_handler), + &ri); + + delete_handler = + gtk_signal_connect (GTK_OBJECT (dialog), + "delete_event", + GTK_SIGNAL_FUNC (run_delete_handler), + &ri); + + ri.loop = g_main_new (FALSE); + + g_main_run (ri.loop); + + g_assert (ri.loop == NULL); + + if (!GTK_OBJECT_DESTROYED (dialog)) + { + if (!was_modal) + gtk_window_set_modal (GTK_WINDOW(dialog), FALSE); + + gtk_signal_disconnect (GTK_OBJECT (dialog), destroy_handler); + gtk_signal_disconnect (GTK_OBJECT (dialog), response_handler); + gtk_signal_disconnect (GTK_OBJECT (dialog), delete_handler); + } + + gtk_object_unref (GTK_OBJECT (dialog)); + + return ri.response_id; +} + + + + diff --git a/gtk/gtkdialog.h b/gtk/gtkdialog.h index cb2340ee08..fb8d10cf6c 100644 --- a/gtk/gtkdialog.h +++ b/gtk/gtkdialog.h @@ -36,6 +36,35 @@ extern "C" { #endif /* __cplusplus */ +/* Parameters for dialog construction */ +typedef enum +{ + GTK_DIALOG_MODAL, /* call gtk_window_set_modal (win, TRUE) */ + GTK_DIALOG_DESTROY_WITH_PARENT /* call gtk_window_set_destroy_with_parent () */ + +} GtkDialogFlags; + +/* Convenience enum to use for action_id's. Positive values are + * totally user-interpreted. GTK will sometimes return + * GTK_ACTION_NONE if no action_id is available. + * + * Typical usage is: + * if (gtk_dialog_run(dialog) == GTK_ACTION_ACCEPT) + * blah(); + */ +typedef enum +{ + /* GTK returns this if a response widget has no response_id, + * or the dialog gets destroyed with no response + */ + GTK_RESPONSE_NONE = -1, + /* GTK won't return these unless you pass them in + * as the response for an action widget + */ + GTK_RESPONSE_REJECT = -2, + GTK_RESPONSE_ACCEPT = -3 +} GtkResponseType; + #define GTK_TYPE_DIALOG (gtk_dialog_get_type ()) #define GTK_DIALOG(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_DIALOG, GtkDialog)) @@ -47,8 +76,6 @@ extern "C" { typedef struct _GtkDialog GtkDialog; typedef struct _GtkDialogClass GtkDialogClass; -typedef struct _GtkDialogButton GtkDialogButton; - struct _GtkDialog { @@ -61,12 +88,38 @@ struct _GtkDialog struct _GtkDialogClass { GtkWindowClass parent_class; + + void (* response) (GtkDialog *dialog, gint response_id); }; GtkType gtk_dialog_get_type (void) G_GNUC_CONST; GtkWidget* gtk_dialog_new (void); +GtkWidget* gtk_dialog_new_with_buttons (const gchar *title, + GtkWindow *parent, + GtkDialogFlags flags, + const gchar *first_button_text, + ...); + +void gtk_dialog_add_action_widget (GtkDialog *dialog, + GtkWidget *child, + gint response_id); + +void gtk_dialog_add_button (GtkDialog *dialog, + const gchar *button_text, + gint response_id); + +void gtk_dialog_add_buttons (GtkDialog *dialog, + const gchar *first_button_text, + ...); + +/* Emit response signal */ +void gtk_dialog_response (GtkDialog *dialog, + gint response_id); + +/* Returns response_id */ +gint gtk_dialog_run (GtkDialog *dialog); #ifdef __cplusplus } diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h index dd8fe45fc0..9f8e1f93d8 100644 --- a/gtk/gtkenums.h +++ b/gtk/gtkenums.h @@ -338,7 +338,8 @@ typedef enum GTK_WIN_POS_NONE, GTK_WIN_POS_CENTER, GTK_WIN_POS_MOUSE, - GTK_WIN_POS_CENTER_ALWAYS + GTK_WIN_POS_CENTER_ALWAYS, + GTK_WIN_POS_CENTER_ON_PARENT } GtkWindowPosition; /* Window types */ diff --git a/gtk/gtkmessagedialog.c b/gtk/gtkmessagedialog.c new file mode 100644 index 0000000000..6ecb161c0b --- /dev/null +++ b/gtk/gtkmessagedialog.c @@ -0,0 +1,251 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "gtkmessagedialog.h" +#include "gtklabel.h" +#include "gtkhbox.h" +#include "gtkimage.h" +#include "gtkstock.h" +#include "gtkiconfactory.h" + +static void gtk_message_dialog_class_init (GtkMessageDialogClass *klass); +static void gtk_message_dialog_init (GtkMessageDialog *dialog); + + +GtkType +gtk_message_dialog_get_type (void) +{ + static GtkType dialog_type = 0; + + if (!dialog_type) + { + static const GtkTypeInfo dialog_info = + { + "GtkMessageDialog", + sizeof (GtkMessageDialog), + sizeof (GtkMessageDialogClass), + (GtkClassInitFunc) gtk_message_dialog_class_init, + (GtkObjectInitFunc) gtk_message_dialog_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + dialog_type = gtk_type_unique (GTK_TYPE_DIALOG, &dialog_info); + } + + return dialog_type; +} + +static void +gtk_message_dialog_class_init (GtkMessageDialogClass *class) +{ +} + +static void +gtk_message_dialog_init (GtkMessageDialog *dialog) +{ + GtkWidget *hbox; + + dialog->label = gtk_label_new (NULL); + dialog->image = gtk_image_new_from_stock (NULL, GTK_ICON_SIZE_DIALOG); + + gtk_label_set_line_wrap (GTK_LABEL (dialog->label), TRUE); + + hbox = gtk_hbox_new (FALSE, 10); + + gtk_container_set_border_width (GTK_CONTAINER (hbox), 10); + + gtk_box_pack_start (GTK_BOX (hbox), dialog->image, + FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX (hbox), dialog->label, + TRUE, TRUE, 2); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + hbox, + FALSE, FALSE, 10); + + gtk_widget_show_all (hbox); +} + +static void +setup_type(GtkMessageDialog *dialog, GtkMessageType type) +{ + /* Note: this function can be called more than once, + * and after showing the dialog, due to object args + */ + + const gchar *stock_id = NULL; + GtkStockItem item; + + switch (type) + { + case GTK_MESSAGE_INFO: + stock_id = GTK_STOCK_DIALOG_INFO; + break; + + case GTK_MESSAGE_QUESTION: + stock_id = GTK_STOCK_DIALOG_QUESTION; + break; + + case GTK_MESSAGE_WARNING: + stock_id = GTK_STOCK_DIALOG_WARNING; + break; + + case GTK_MESSAGE_ERROR: + stock_id = GTK_STOCK_DIALOG_ERROR; + break; + + default: + g_warning ("Unknown GtkMessageType %d", type); + break; + } + + if (stock_id == NULL) + stock_id = GTK_STOCK_DIALOG_INFO; + + if (gtk_stock_lookup (stock_id, &item)) + { + gtk_image_set_from_stock (GTK_IMAGE (dialog->image), stock_id, + GTK_ICON_SIZE_DIALOG); + + gtk_window_set_title (GTK_WINDOW (dialog), item.label); + } + else + g_warning ("Stock dialog ID doesn't exist?"); +} + +/** + * gtk_message_dialog_new: + * @parent: transient parent, or NULL for none + * @flags: flags + * @type: type of message + * @buttons: set of buttons to use + * @message_format: printf()-style format string, or NULL + * @Varargs: arguments for @message_format + * + * Creates a new message dialog, which is a simple dialog with an icon + * indicating the dialog type (error, warning, etc.) and some text the + * user may want to see. If the button set you select with the @buttons + * argument has positive buttons (OK, Yes) they will result in a response ID + * of GTK_RESPONSE_ACCEPT. If it has negative buttons (Cancel, No) they will + * result in a response ID of GTK_RESPONSE_REJECT. See #GtkDialog for more + * details. + * + * Return value: a new #GtkMessageDialog + **/ +GtkWidget* +gtk_message_dialog_new (GtkWindow *parent, + GtkDialogFlags flags, + GtkMessageType type, + GtkButtonsType buttons, + const gchar *message_format, + ...) +{ + GtkWidget *widget; + GtkDialog *dialog; + gchar* msg; + va_list args; + + widget = GTK_WIDGET (gtk_type_new (GTK_TYPE_MESSAGE_DIALOG)); + dialog = GTK_DIALOG (widget); + + if (message_format) + { + va_start (args, message_format); + msg = g_strdup_vprintf(message_format, args); + va_end (args); + + + gtk_label_set_text (GTK_LABEL (GTK_MESSAGE_DIALOG (widget)->label), + msg); + + g_free (msg); + } + + if (parent != NULL) + gtk_window_set_transient_for (GTK_WINDOW (widget), + GTK_WINDOW (parent)); + + + if (flags & GTK_DIALOG_MODAL) + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + if (flags & GTK_DIALOG_DESTROY_WITH_PARENT) + gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); + + setup_type (GTK_MESSAGE_DIALOG (dialog), type); + + switch (buttons) + { + case GTK_BUTTONS_NONE: + /* nothing */ + break; + + case GTK_BUTTONS_OK: + gtk_dialog_add_button (dialog, + GTK_STOCK_BUTTON_OK, + GTK_RESPONSE_ACCEPT); + break; + + case GTK_BUTTONS_CLOSE: + gtk_dialog_add_button (dialog, + GTK_STOCK_BUTTON_CLOSE, + GTK_RESPONSE_ACCEPT); + break; + + case GTK_BUTTONS_CANCEL: + gtk_dialog_add_button (dialog, + GTK_STOCK_BUTTON_CANCEL, + GTK_RESPONSE_REJECT); + break; + + case GTK_BUTTONS_YES_NO: + gtk_dialog_add_button (dialog, + GTK_STOCK_BUTTON_YES, + GTK_RESPONSE_ACCEPT); + gtk_dialog_add_button (dialog, + GTK_STOCK_BUTTON_NO, + GTK_RESPONSE_REJECT); + break; + + case GTK_BUTTONS_OK_CANCEL: + gtk_dialog_add_button (dialog, + GTK_STOCK_BUTTON_OK, + GTK_RESPONSE_ACCEPT); + gtk_dialog_add_button (dialog, + GTK_STOCK_BUTTON_CANCEL, + GTK_RESPONSE_REJECT); + break; + + default: + g_warning ("Unknown GtkButtonsType"); + break; + } + + return widget; +} diff --git a/gtk/gtkmessagedialog.h b/gtk/gtkmessagedialog.h new file mode 100644 index 0000000000..688798c652 --- /dev/null +++ b/gtk/gtkmessagedialog.h @@ -0,0 +1,98 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __GTK_MESSAGE_DIALOG_H__ +#define __GTK_MESSAGE_DIALOG_H__ + +#include <gtk/gtkdialog.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef enum +{ + GTK_MESSAGE_INFO, + GTK_MESSAGE_WARNING, + GTK_MESSAGE_QUESTION, + GTK_MESSAGE_ERROR +} GtkMessageType; + +typedef enum +{ + GTK_BUTTONS_NONE, + GTK_BUTTONS_OK, + GTK_BUTTONS_CLOSE, + GTK_BUTTONS_CANCEL, + GTK_BUTTONS_YES_NO, + GTK_BUTTONS_OK_CANCEL +} GtkButtonsType; + +#define GTK_TYPE_MESSAGE_DIALOG (gtk_message_dialog_get_type ()) +#define GTK_MESSAGE_DIALOG(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_MESSAGE_DIALOG, GtkMessageDialog)) +#define GTK_MESSAGE_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_MESSAGE_DIALOG, GtkMessageDialogClass)) +#define GTK_IS_MESSAGE_DIALOG(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_MESSAGE_DIALOG)) +#define GTK_IS_MESSAGE_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_MESSAGE_DIALOG)) +#define GTK_MESSAGE_DIALOG_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_MESSAGE_DIALOG, GtkMessageDialogClass)) + + +typedef struct _GtkMessageDialog GtkMessageDialog; +typedef struct _GtkMessageDialogClass GtkMessageDialogClass; + +struct _GtkMessageDialog +{ + /*< private >*/ + + GtkDialog parent_instance; + + GtkWidget *image; + GtkWidget *label; +}; + +struct _GtkMessageDialogClass +{ + GtkDialogClass parent_class; + + +}; + +GtkType gtk_message_dialog_get_type (void); + +GtkWidget* gtk_message_dialog_new (GtkWindow *parent, + GtkDialogFlags flags, + GtkMessageType type, + GtkButtonsType buttons, + const gchar *message_format, + ...) G_GNUC_PRINTF (5, 6); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GTK_MESSAGE_DIALOG_H__ */ diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index bfd2a46e72..481f1d2c71 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -45,6 +45,7 @@ #include "gtkwindow.h" #include "gtkbindings.h" #include "gtkmain.h" +#include "gtkiconfactory.h" /* TODO: remove this define and assorted code in 1.3 and fix up the * real culprits. @@ -65,7 +66,8 @@ enum { ARG_MODAL, ARG_WIN_POS, ARG_DEFAULT_WIDTH, - ARG_DEFAULT_HEIGHT + ARG_DEFAULT_HEIGHT, + ARG_DESTROY_WITH_PARENT }; typedef struct { @@ -225,6 +227,7 @@ gtk_window_class_init (GtkWindowClass *klass) gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS); gtk_object_add_arg_type ("GtkWindow::default_width", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_WIDTH); gtk_object_add_arg_type ("GtkWindow::default_height", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_HEIGHT); + gtk_object_add_arg_type ("GtkWindow::destroy_with_parent", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DESTROY_WITH_PARENT); window_signals[SET_FOCUS] = gtk_signal_new ("set_focus", @@ -335,6 +338,9 @@ gtk_window_set_arg (GtkObject *object, case ARG_DEFAULT_HEIGHT: gtk_window_set_default_size (window, -2, GTK_VALUE_INT (*arg)); break; + case ARG_DESTROY_WITH_PARENT: + gtk_window_set_destroy_with_parent (window, GTK_VALUE_BOOL (*arg)); + break; default: break; } @@ -387,6 +393,9 @@ gtk_window_get_arg (GtkObject *object, else GTK_VALUE_INT (*arg) = info->height; break; + case ARG_DESTROY_WITH_PARENT: + GTK_VALUE_BOOL (*arg) = window->destroy_with_parent; + break; default: arg->type = GTK_TYPE_INVALID; break; @@ -527,6 +536,29 @@ gtk_window_remove_accel_group (GtkWindow *window, gtk_accel_group_detach (accel_group, GTK_OBJECT (window)); } +GtkAccelGroup* +gtk_window_get_default_accel_group (GtkWindow *window) +{ + GtkAccelGroup *group; + + g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); + + group = gtk_object_get_data (GTK_OBJECT (window), + "gtk-accel-group"); + + if (group == NULL) + { + group = gtk_accel_group_new (); + gtk_window_add_accel_group (window, group); + gtk_object_set_data (GTK_OBJECT (window), + "gtk-accel-group", + group); + gtk_accel_group_unref (group); + } + + return group; +} + void gtk_window_set_position (GtkWindow *window, GtkWindowPosition position) @@ -688,6 +720,35 @@ gtk_window_shutdown (GObject *object) } static void +parent_destroyed_callback (GtkWindow *parent, GtkWindow *child) +{ + gtk_widget_destroy (GTK_WIDGET (child)); +} + +static void +connect_parent_destroyed (GtkWindow *window) +{ + if (window->transient_parent) + { + gtk_signal_connect (GTK_OBJECT (window->transient_parent), + "destroy", + GTK_SIGNAL_FUNC (parent_destroyed_callback), + window); + } +} + +static void +disconnect_parent_destroyed (GtkWindow *window) +{ + if (window->transient_parent) + { + gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent), + GTK_SIGNAL_FUNC (parent_destroyed_callback), + window); + } +} + +static void gtk_window_transient_parent_realized (GtkWidget *parent, GtkWidget *window) { @@ -719,6 +780,9 @@ gtk_window_unset_transient_for (GtkWindow *window) GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window->transient_parent); + if (window->destroy_with_parent) + disconnect_parent_destroyed (window); + window->transient_parent = NULL; } } @@ -727,8 +791,11 @@ void gtk_window_set_transient_for (GtkWindow *window, GtkWindow *parent) { - g_return_if_fail (window != 0); + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent)); + g_return_if_fail (window != parent); + if (window->transient_parent) { if (GTK_WIDGET_REALIZED (window) && @@ -754,6 +821,9 @@ gtk_window_set_transient_for (GtkWindow *window, GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized), window); + if (window->destroy_with_parent) + connect_parent_destroyed (window); + if (GTK_WIDGET_REALIZED (window) && GTK_WIDGET_REALIZED (parent)) gtk_window_transient_parent_realized (GTK_WIDGET (parent), @@ -761,6 +831,37 @@ gtk_window_set_transient_for (GtkWindow *window, } } +/** + * gtk_window_set_destroy_with_parent: + * @window: a #GtkWindow + * @setting: whether to destroy @window with its transient parent + * + * If @setting is TRUE, then destroying the transient parent of @window + * will also destroy @window itself. This is useful for dialogs that + * shouldn't persist beyond the lifetime of the main window they're + * associated with, for example. + **/ +void +gtk_window_set_destroy_with_parent (GtkWindow *window, + gboolean setting) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + + if (window->destroy_with_parent == (setting != FALSE)) + return; + + if (window->destroy_with_parent) + { + disconnect_parent_destroyed (window); + } + else + { + connect_parent_destroyed (window); + } + + window->destroy_with_parent = setting; +} + static void gtk_window_geometry_destroy (GtkWindowGeometryInfo *info) { @@ -859,7 +960,7 @@ gtk_window_destroy (GtkObject *object) window = GTK_WINDOW (object); if (window->transient_parent) - gtk_window_unset_transient_for (window); + gtk_window_set_transient_for (window, NULL); if (window->has_user_ref_count) { @@ -1432,10 +1533,15 @@ gtk_window_read_rcfiles (GtkWidget *widget, * of date, so we need to reset all our widgets. Our other * toplevel windows will also get the message, but by * then, the RC file will up to date, so we have to tell - * them now. + * them now. Also, we have to invalidate cached icons in + * icon sets so they get re-rendered. */ - GList *list, *toplevels = gtk_window_list_toplevels (); + GList *list, *toplevels; + _gtk_icon_set_invalidate_caches (); + + toplevels = gtk_window_list_toplevels (); + for (list = toplevels; list; list = list->next) { gtk_widget_reset_rc_styles (list->data); @@ -2056,14 +2162,24 @@ gtk_window_compute_reposition (GtkWindow *window, gint *y) { GtkWidget *widget; - + GtkWindowPosition pos; + GtkWidget *parent_widget; + widget = GTK_WIDGET (window); *x = -1; *y = -1; + + parent_widget = (GtkWidget*) window->transient_parent; - switch (window->position) - { + pos = window->position; + if (pos == GTK_WIN_POS_CENTER_ON_PARENT && + (parent_widget == NULL || + !GTK_WIDGET_MAPPED (parent_widget))) + pos = GTK_WIN_POS_NONE; + + switch (pos) + { case GTK_WIN_POS_CENTER: case GTK_WIN_POS_CENTER_ALWAYS: if (window->use_uposition) @@ -2075,6 +2191,19 @@ gtk_window_compute_reposition (GtkWindow *window, *y = (screen_height - new_height) / 2; } break; + + case GTK_WIN_POS_CENTER_ON_PARENT: + if (window->use_uposition) + { + gint ox, oy; + gdk_window_get_origin (parent_widget->window, + &ox, &oy); + + *x = ox + (parent_widget->allocation.width - new_width) / 2; + *y = oy + (parent_widget->allocation.height - new_height) / 2; + } + break; + case GTK_WIN_POS_MOUSE: if (window->use_uposition) { diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 1b86c76d5e..058da9fc51 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -79,6 +79,7 @@ struct _GtkWindow */ guint use_uposition : 1; guint modal : 1; + guint destroy_with_parent : 1; }; struct _GtkWindowClass @@ -112,6 +113,8 @@ gint gtk_window_activate_default (GtkWindow *window); void gtk_window_set_transient_for (GtkWindow *window, GtkWindow *parent); +void gtk_window_set_destroy_with_parent (GtkWindow *window, + gboolean setting); void gtk_window_set_geometry_hints (GtkWindow *window, GtkWidget *geometry_widget, GdkGeometry *geometry, @@ -129,6 +132,8 @@ void gtk_window_set_modal (GtkWindow *window, gboolean modal); GList* gtk_window_list_toplevels (void); +/* Get the "built-in" accel group (convenience thing) */ +GtkAccelGroup* gtk_window_get_default_accel_group (GtkWindow *window); /* --- internal functions --- */ void gtk_window_set_focus (GtkWindow *window, diff --git a/gtk/testgtk.c b/gtk/testgtk.c index 86d9be5915..a24554f6bc 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -161,8 +161,12 @@ create_buttons (void) if (!window) { + GtkAccelGroup *accel_group; + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + accel_group = gtk_window_get_default_accel_group (GTK_WINDOW (window)); + gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); @@ -180,15 +184,15 @@ create_buttons (void) gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0); button[0] = gtk_button_new_with_label ("button1"); - button[1] = gtk_button_new_with_label ("button2"); + button[1] = gtk_button_new_accel ("_button2", accel_group); button[2] = gtk_button_new_with_label ("button3"); - button[3] = gtk_button_new_with_label ("button4"); + button[3] = gtk_button_new_stock (GTK_STOCK_BUTTON_OK, NULL); button[4] = gtk_button_new_with_label ("button5"); button[5] = gtk_button_new_with_label ("button6"); button[6] = gtk_button_new_with_label ("button7"); - button[7] = gtk_button_new_with_label ("button8"); + button[7] = gtk_button_new_stock (GTK_STOCK_BUTTON_CLOSE, accel_group); button[8] = gtk_button_new_with_label ("button9"); - + gtk_signal_connect (GTK_OBJECT (button[0]), "clicked", GTK_SIGNAL_FUNC(button_window), button[1]); @@ -2222,6 +2226,65 @@ create_tooltips (void) } /* + * GtkImage + */ + +static void +pack_image (GtkWidget *box, + const gchar *text, + GtkWidget *image) +{ + gtk_box_pack_start (GTK_BOX (box), + gtk_label_new (text), + FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (box), + image, + TRUE, TRUE, 0); +} + +static void +create_image (void) +{ + static GtkWidget *window = NULL; + + if (window == NULL) + { + GtkWidget *vbox; + GdkPixmap *pixmap; + GdkBitmap *mask; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), + &window); + + vbox = gtk_vbox_new (FALSE, 5); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + pack_image (vbox, "Stock Warning Dialog", + gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, + GTK_ICON_SIZE_DIALOG)); + + pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, + gtk_widget_get_colormap (window), + &mask, + NULL, + openfile); + + pack_image (vbox, "Pixmap", + gtk_image_new_from_pixmap (pixmap, mask)); + } + + if (!GTK_WIDGET_VISIBLE (window)) + gtk_widget_show_all (window); + else + gtk_widget_destroy (window); +} + +/* * Menu demo */ @@ -2609,12 +2672,12 @@ create_modal_window (void) /* Pack widgets */ gtk_container_add (GTK_CONTAINER (window), box1); - gtk_box_pack_start (GTK_BOX (box1), frame1, TRUE, TRUE, 4); - gtk_container_add (GTK_CONTAINER (frame1), box2); - gtk_box_pack_start (GTK_BOX (box2), btnColor, FALSE, FALSE, 4); - gtk_box_pack_start (GTK_BOX (box2), btnFile, FALSE, FALSE, 4); - gtk_box_pack_start (GTK_BOX (box1), gtk_hseparator_new (), FALSE, FALSE, 4); - gtk_box_pack_start (GTK_BOX (box1), btnClose, FALSE, FALSE, 4); + gtk_box_pack_start (GTK_BOX (box1), frame1, TRUE, TRUE, 4); + gtk_container_add (GTK_CONTAINER (frame1), box2); + gtk_box_pack_start (GTK_BOX (box2), btnColor, FALSE, FALSE, 4); + gtk_box_pack_start (GTK_BOX (box2), btnFile, FALSE, FALSE, 4); + gtk_box_pack_start (GTK_BOX (box1), gtk_hseparator_new (), FALSE, FALSE, 4); + gtk_box_pack_start (GTK_BOX (box1), btnClose, FALSE, FALSE, 4); /* connect signals */ gtk_signal_connect_object (GTK_OBJECT (btnClose), "clicked", @@ -2637,6 +2700,53 @@ create_modal_window (void) } /* + * GtkMessageDialog + */ + +static void +make_message_dialog (GtkWidget **dialog, + GtkMessageType type, + GtkButtonsType buttons) +{ + if (*dialog) + { + if (GTK_WIDGET_REALIZED (*dialog)) + gdk_window_show ((*dialog)->window); + + return; + } + + *dialog = gtk_message_dialog_new (NULL, 0, type, buttons, + "This is a message dialog; it can wrap long lines. This is a long line. La la la. Look this line is wrapped. Blah blah blah blah blah blah. (Note: testgtk has a nonstandard gtkrc that changes some of the message dialog icons.)"); + + gtk_signal_connect_object (GTK_OBJECT (*dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (*dialog)); + + gtk_signal_connect (GTK_OBJECT (*dialog), + "destroy", + GTK_SIGNAL_FUNC (gtk_widget_destroyed), + dialog); + + gtk_widget_show (*dialog); +} + +static void +create_message_dialog (void) +{ + static GtkWidget *info = NULL; + static GtkWidget *warning = NULL; + static GtkWidget *error = NULL; + static GtkWidget *question = NULL; + + make_message_dialog (&info, GTK_MESSAGE_INFO, GTK_BUTTONS_OK); + make_message_dialog (&warning, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE); + make_message_dialog (&error, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK_CANCEL); + make_message_dialog (&question, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO); +} + +/* * GtkScrolledWindow */ @@ -8624,11 +8734,13 @@ create_main_window (void) { "font selection", create_font_selection }, { "gamma curve", create_gamma_curve }, { "handle box", create_handle_box }, + { "image", create_image }, { "item factory", create_item_factory }, { "labels", create_labels }, { "layout", create_layout }, { "list", create_list }, { "menus", create_menus }, + { "message dialog", create_message_dialog }, { "modal window", create_modal_window }, { "notebook", create_notebook }, { "panes", create_panes }, @@ -8771,8 +8883,6 @@ main (int argc, char *argv[]) gtk_init (&argc, &argv); - gdk_rgb_init (); - /* bindings test */ binding_set = gtk_binding_set_by_class (gtk_type_class (GTK_TYPE_WIDGET)); diff --git a/gtk/testgtkrc b/gtk/testgtkrc index 85fb904530..170ad4d1f1 100644 --- a/gtk/testgtkrc +++ b/gtk/testgtkrc @@ -29,6 +29,16 @@ style "defaultfont" font_name = "Sans 12" } +style "myicons" +{ + stock["gtk-dialog-warning"] = + { + { "3DRings.xpm", *, *, *} + } +} + +class "GtkImage" style "myicons" + # common default class "GtkWidget" style "defaultfont" |