1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32 #include "gtkbutton.h"
33 #include "gtkdialog.h"
36 #include "gtkmarshalers.h"
40 #include "gtkbindings.h"
41 #include "gtkprivate.h"
42 #include "gtkbuildable.h"
46 * @Short_description: Create popup windows
48 * @See_also: #GtkVBox, #GtkWindow, #GtkButton
50 * Dialog boxes are a convenient way to prompt the user for a small amount
51 * of input, e.g. to display a message, ask a question, or anything else
52 * that does not require extensive effort on the user's part.
54 * GTK+ treats a dialog as a window split vertically. The top section is a
55 * #GtkVBox, and is where widgets such as a #GtkLabel or a #GtkEntry should
56 * be packed. The bottom area is known as the
57 * <structfield>action_area</structfield>. This is generally used for
58 * packing buttons into the dialog which may perform functions such as
59 * cancel, ok, or apply.
61 * #GtkDialog boxes are created with a call to gtk_dialog_new() or
62 * gtk_dialog_new_with_buttons(). gtk_dialog_new_with_buttons() is
63 * recommended; it allows you to set the dialog title, some convenient flags,
64 * and add simple buttons.
66 * If 'dialog' is a newly created dialog, the two primary areas of the
67 * window can be accessed through gtk_dialog_get_content_area() and
68 * gtk_dialog_get_action_area(), as can be seen from the example below.
70 * A 'modal' dialog (that is, one which freezes the rest of the application
71 * from user input), can be created by calling gtk_window_set_modal() on the
72 * dialog. Use the GTK_WINDOW() macro to cast the widget returned from
73 * gtk_dialog_new() into a #GtkWindow. When using gtk_dialog_new_with_buttons()
74 * you can also pass the #GTK_DIALOG_MODAL flag to make a dialog modal.
76 * If you add buttons to #GtkDialog using gtk_dialog_new_with_buttons(),
77 * gtk_dialog_add_button(), gtk_dialog_add_buttons(), or
78 * gtk_dialog_add_action_widget(), clicking the button will emit a signal
79 * called #GtkDialog::response with a response ID that you specified. GTK+
80 * will never assign a meaning to positive response IDs; these are entirely
81 * user-defined. But for convenience, you can use the response IDs in the
82 * #GtkResponseType enumeration (these all have values less than zero). If
83 * a dialog receives a delete event, the #GtkDialog::response signal will
84 * be emitted with a response ID of #GTK_RESPONSE_DELETE_EVENT.
86 * If you want to block waiting for a dialog to return before returning
87 * control flow to your code, you can call gtk_dialog_run(). This function
88 * enters a recursive main loop and waits for the user to respond to the
89 * dialog, returning the response ID corresponding to the button the user
92 * For the simple dialog in the following example, in reality you'd probably
93 * use #GtkMessageDialog to save yourself some effort. But you'd need to
94 * create the dialog contents manually if you had more than a simple message
97 * <title>Simple GtkDialog usage</title>
99 * /* Function to open a dialog box displaying the message provided. */
101 * quick_message (gchar *message)
103 * GtkWidget *dialog, *label, *content_area;
105 * /* Create the widgets */
106 * dialog = gtk_dialog_new_with_buttons ("Message",
107 * main_application_window,
108 * GTK_DIALOG_DESTROY_WITH_PARENT,
112 * content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
113 * label = gtk_label_new (message);
115 * /* Ensure that the dialog box is destroyed when the user responds */
116 * g_signal_connect_swapped (dialog,
118 * G_CALLBACK (gtk_widget_destroy),
121 * /* Add the label, and show everything we've added to the dialog */
123 * gtk_container_add (GTK_CONTAINER (content_area), label);
124 * gtk_widget_show_all (dialog);
129 * <refsect2 id="GtkDialog-BUILDER-UI"><title>GtkDialog as GtkBuildable</title>
131 * The GtkDialog implementation of the #GtkBuildable interface exposes the
132 * @vbox and @action_area as internal children with the names "vbox" and
136 * GtkDialog supports a custom <action-widgets> element, which
137 * can contain multiple <action-widget> elements. The "response"
138 * attribute specifies a numeric response, and the content of the element
139 * is the id of widget (which should be a child of the dialogs @action_area).
142 * <title>A <structname>GtkDialog</structname> UI definition fragment.</title>
143 * <programlisting><![CDATA[
144 * <object class="GtkDialog" id="dialog1">
145 * <child internal-child="vbox">"
146 * <object class="GtkVBox" id="vbox">
147 * <child internal-child="action_area">
148 * <object class="GtkHButtonBox" id="button_box">
150 * <object class="GtkButton" id="button_cancel"/>
153 * <object class="GtkButton" id="button_ok"/>
160 * <action-widget response="3">button_ok</action-widget>
161 * <action-widget response="-5">button_cancel</action-widget>
164 * ]]></programlisting>
169 struct _GtkDialogPrivate
172 GtkWidget *action_area;
175 typedef struct _ResponseData ResponseData;
182 static void gtk_dialog_add_buttons_valist (GtkDialog *dialog,
183 const gchar *first_button_text,
186 static gboolean gtk_dialog_delete_event_handler (GtkWidget *widget,
189 static void gtk_dialog_style_updated (GtkWidget *widget);
190 static void gtk_dialog_map (GtkWidget *widget);
192 static void gtk_dialog_close (GtkDialog *dialog);
194 static ResponseData * get_response_data (GtkWidget *widget,
197 static void gtk_dialog_buildable_interface_init (GtkBuildableIface *iface);
198 static GObject * gtk_dialog_buildable_get_internal_child (GtkBuildable *buildable,
200 const gchar *childname);
201 static gboolean gtk_dialog_buildable_custom_tag_start (GtkBuildable *buildable,
204 const gchar *tagname,
205 GMarkupParser *parser,
207 static void gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
210 const gchar *tagname,
225 static guint dialog_signals[LAST_SIGNAL];
227 G_DEFINE_TYPE_WITH_CODE (GtkDialog, gtk_dialog, GTK_TYPE_WINDOW,
228 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
229 gtk_dialog_buildable_interface_init))
232 gtk_dialog_class_init (GtkDialogClass *class)
234 GObjectClass *gobject_class;
235 GtkWidgetClass *widget_class;
236 GtkBindingSet *binding_set;
238 gobject_class = G_OBJECT_CLASS (class);
239 widget_class = GTK_WIDGET_CLASS (class);
241 widget_class->map = gtk_dialog_map;
242 widget_class->style_updated = gtk_dialog_style_updated;
244 gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_DIALOG);
246 class->close = gtk_dialog_close;
248 g_type_class_add_private (gobject_class, sizeof (GtkDialogPrivate));
251 * GtkDialog::response:
252 * @dialog: the object on which the signal is emitted
253 * @response_id: the response ID
255 * Emitted when an action widget is clicked, the dialog receives a
256 * delete event, or the application programmer calls gtk_dialog_response().
257 * On a delete event, the response ID is #GTK_RESPONSE_DELETE_EVENT.
258 * Otherwise, it depends on which action widget was clicked.
260 dialog_signals[RESPONSE] =
261 g_signal_new (I_("response"),
262 G_OBJECT_CLASS_TYPE (class),
264 G_STRUCT_OFFSET (GtkDialogClass, response),
266 _gtk_marshal_VOID__INT,
273 * The ::close signal is a
274 * <link linkend="keybinding-signals">keybinding signal</link>
275 * which gets emitted when the user uses a keybinding to close
278 * The default binding for this signal is the Escape key.
280 dialog_signals[CLOSE] =
281 g_signal_new (I_("close"),
282 G_OBJECT_CLASS_TYPE (class),
283 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
284 G_STRUCT_OFFSET (GtkDialogClass, close),
286 _gtk_marshal_VOID__VOID,
289 gtk_widget_class_install_style_property (widget_class,
290 g_param_spec_int ("content-area-border",
291 P_("Content area border"),
292 P_("Width of border around the main dialog area"),
296 GTK_PARAM_READABLE));
298 * GtkDialog:content-area-spacing:
300 * The default spacing used between elements of the
301 * content area of the dialog, as returned by
302 * gtk_dialog_get_content_area(), unless gtk_box_set_spacing()
303 * was called on that widget directly.
307 gtk_widget_class_install_style_property (widget_class,
308 g_param_spec_int ("content-area-spacing",
309 P_("Content area spacing"),
310 P_("Spacing between elements of the main dialog area"),
314 GTK_PARAM_READABLE));
315 gtk_widget_class_install_style_property (widget_class,
316 g_param_spec_int ("button-spacing",
317 P_("Button spacing"),
318 P_("Spacing between buttons"),
322 GTK_PARAM_READABLE));
324 gtk_widget_class_install_style_property (widget_class,
325 g_param_spec_int ("action-area-border",
326 P_("Action area border"),
327 P_("Width of border around the button area at the bottom of the dialog"),
331 GTK_PARAM_READABLE));
333 binding_set = gtk_binding_set_by_class (class);
335 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
339 update_spacings (GtkDialog *dialog)
341 GtkDialogPrivate *priv = dialog->priv;
342 gint content_area_border;
343 gint content_area_spacing;
345 gint action_area_border;
347 gtk_widget_style_get (GTK_WIDGET (dialog),
348 "content-area-border", &content_area_border,
349 "content-area-spacing", &content_area_spacing,
350 "button-spacing", &button_spacing,
351 "action-area-border", &action_area_border,
355 gtk_container_set_border_width (GTK_CONTAINER (priv->vbox),
356 content_area_border);
357 if (!_gtk_box_get_spacing_set (GTK_BOX (priv->vbox)))
359 gtk_box_set_spacing (GTK_BOX (priv->vbox), content_area_spacing);
360 _gtk_box_set_spacing_set (GTK_BOX (priv->vbox), FALSE);
362 gtk_box_set_spacing (GTK_BOX (priv->action_area),
364 gtk_container_set_border_width (GTK_CONTAINER (priv->action_area),
369 gtk_dialog_init (GtkDialog *dialog)
371 GtkDialogPrivate *priv;
373 dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
378 /* To avoid breaking old code that prevents destroy on delete event
379 * by connecting a handler, we have to have the FIRST signal
380 * connection on the dialog.
382 g_signal_connect (dialog,
384 G_CALLBACK (gtk_dialog_delete_event_handler),
387 priv->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
388 gtk_container_add (GTK_CONTAINER (dialog), priv->vbox);
389 gtk_widget_show (priv->vbox);
391 priv->action_area = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
393 gtk_button_box_set_layout (GTK_BUTTON_BOX (priv->action_area),
396 gtk_box_pack_end (GTK_BOX (priv->vbox), priv->action_area,
398 gtk_widget_show (priv->action_area);
400 gtk_window_set_type_hint (GTK_WINDOW (dialog),
401 GDK_WINDOW_TYPE_HINT_DIALOG);
402 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
404 update_spacings (dialog);
407 static GtkBuildableIface *parent_buildable_iface;
410 gtk_dialog_buildable_interface_init (GtkBuildableIface *iface)
412 parent_buildable_iface = g_type_interface_peek_parent (iface);
413 iface->get_internal_child = gtk_dialog_buildable_get_internal_child;
414 iface->custom_tag_start = gtk_dialog_buildable_custom_tag_start;
415 iface->custom_finished = gtk_dialog_buildable_custom_finished;
419 gtk_dialog_buildable_get_internal_child (GtkBuildable *buildable,
421 const gchar *childname)
423 GtkDialogPrivate *priv = GTK_DIALOG (buildable)->priv;
425 if (strcmp (childname, "vbox") == 0)
426 return G_OBJECT (priv->vbox);
427 else if (strcmp (childname, "action_area") == 0)
428 return G_OBJECT (priv->action_area);
430 return parent_buildable_iface->get_internal_child (buildable,
436 gtk_dialog_delete_event_handler (GtkWidget *widget,
440 /* emit response signal */
441 gtk_dialog_response (GTK_DIALOG (widget), GTK_RESPONSE_DELETE_EVENT);
443 /* Do the destroy by default */
447 /* A far too tricky heuristic for getting the right initial
448 * focus widget if none was set. What we do is we focus the first
449 * widget in the tab chain, but if this results in the focus
450 * ending up on one of the response widgets _other_ than the
451 * default response, we focus the default response instead.
453 * Additionally, skip selectable labels when looking for the
454 * right initial focus widget.
457 gtk_dialog_map (GtkWidget *widget)
459 GtkWidget *default_widget, *focus;
460 GtkWindow *window = GTK_WINDOW (widget);
461 GtkDialog *dialog = GTK_DIALOG (widget);
462 GtkDialogPrivate *priv = dialog->priv;
464 GTK_WIDGET_CLASS (gtk_dialog_parent_class)->map (widget);
466 focus = gtk_window_get_focus (window);
469 GList *children, *tmp_list;
470 GtkWidget *first_focus = NULL;
474 g_signal_emit_by_name (window, "move_focus", GTK_DIR_TAB_FORWARD);
476 focus = gtk_window_get_focus (window);
477 if (GTK_IS_LABEL (focus) &&
478 !gtk_label_get_current_uri (GTK_LABEL (focus)))
479 gtk_label_select_region (GTK_LABEL (focus), 0, 0);
481 if (first_focus == NULL)
483 else if (first_focus == focus)
486 if (!GTK_IS_LABEL (focus))
491 tmp_list = children = gtk_container_get_children (GTK_CONTAINER (priv->action_area));
495 GtkWidget *child = tmp_list->data;
497 default_widget = gtk_window_get_default_widget (window);
498 if ((focus == NULL || child == focus) &&
499 child != default_widget &&
502 gtk_widget_grab_focus (default_widget);
506 tmp_list = tmp_list->next;
509 g_list_free (children);
514 gtk_dialog_style_updated (GtkWidget *widget)
516 GTK_WIDGET_CLASS (gtk_dialog_parent_class)->style_updated (widget);
518 update_spacings (GTK_DIALOG (widget));
522 dialog_find_button (GtkDialog *dialog,
525 GtkDialogPrivate *priv = dialog->priv;
526 GtkWidget *child = NULL;
527 GList *children, *tmp_list;
529 children = gtk_container_get_children (GTK_CONTAINER (priv->action_area));
531 for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
533 ResponseData *rd = get_response_data (tmp_list->data, FALSE);
535 if (rd && rd->response_id == response_id)
537 child = tmp_list->data;
542 g_list_free (children);
548 gtk_dialog_close (GtkDialog *dialog)
550 /* Synthesize delete_event to close dialog. */
552 GtkWidget *widget = GTK_WIDGET (dialog);
555 event = gdk_event_new (GDK_DELETE);
557 event->any.window = g_object_ref (gtk_widget_get_window (widget));
558 event->any.send_event = TRUE;
560 gtk_main_do_event (event);
561 gdk_event_free (event);
567 * Creates a new dialog box.
569 * Widgets should not be packed into this #GtkWindow
570 * directly, but into the @vbox and @action_area, as described above.
572 * Returns: the new dialog as a #GtkWidget
575 gtk_dialog_new (void)
577 return g_object_new (GTK_TYPE_DIALOG, NULL);
581 gtk_dialog_new_empty (const gchar *title,
583 GtkDialogFlags flags)
587 dialog = g_object_new (GTK_TYPE_DIALOG, NULL);
590 gtk_window_set_title (GTK_WINDOW (dialog), title);
593 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
595 if (flags & GTK_DIALOG_MODAL)
596 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
598 if (flags & GTK_DIALOG_DESTROY_WITH_PARENT)
599 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
601 return GTK_WIDGET (dialog);
605 * gtk_dialog_new_with_buttons:
606 * @title: (allow-none): Title of the dialog, or %NULL
607 * @parent: (allow-none): Transient parent of the dialog, or %NULL
608 * @flags: from #GtkDialogFlags
609 * @first_button_text: (allow-none): stock ID or text to go in first button, or %NULL
610 * @Varargs: response ID for first button, then additional buttons, ending with %NULL
612 * Creates a new #GtkDialog with title @title (or %NULL for the default
613 * title; see gtk_window_set_title()) and transient parent @parent (or
614 * %NULL for none; see gtk_window_set_transient_for()). The @flags
615 * argument can be used to make the dialog modal (#GTK_DIALOG_MODAL)
616 * and/or to have it destroyed along with its transient parent
617 * (#GTK_DIALOG_DESTROY_WITH_PARENT). After @flags, button
618 * text/response ID pairs should be listed, with a %NULL pointer ending
619 * the list. Button text can be either a stock ID such as
620 * #GTK_STOCK_OK, or some arbitrary text. A response ID can be
621 * any positive number, or one of the values in the #GtkResponseType
622 * enumeration. If the user clicks one of these dialog buttons,
623 * #GtkDialog will emit the #GtkDialog::response signal with the corresponding
624 * response ID. If a #GtkDialog receives the #GtkWidget::delete-event signal,
625 * it will emit ::response with a response ID of #GTK_RESPONSE_DELETE_EVENT.
626 * However, destroying a dialog does not emit the ::response signal;
627 * so be careful relying on ::response when using the
628 * #GTK_DIALOG_DESTROY_WITH_PARENT flag. Buttons are from left to right,
629 * so the first button in the list will be the leftmost button in the dialog.
631 * Here's a simple example:
633 * GtkWidget *dialog = gtk_dialog_new_with_buttons ("My dialog",
635 * GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
637 * GTK_RESPONSE_ACCEPT,
639 * GTK_RESPONSE_REJECT,
643 * Return value: a new #GtkDialog
646 gtk_dialog_new_with_buttons (const gchar *title,
648 GtkDialogFlags flags,
649 const gchar *first_button_text,
655 dialog = GTK_DIALOG (gtk_dialog_new_empty (title, parent, flags));
657 va_start (args, first_button_text);
659 gtk_dialog_add_buttons_valist (dialog,
665 return GTK_WIDGET (dialog);
669 response_data_free (gpointer data)
671 g_slice_free (ResponseData, data);
675 get_response_data (GtkWidget *widget,
678 ResponseData *ad = g_object_get_data (G_OBJECT (widget),
679 "gtk-dialog-response-data");
681 if (ad == NULL && create)
683 ad = g_slice_new (ResponseData);
685 g_object_set_data_full (G_OBJECT (widget),
686 I_("gtk-dialog-response-data"),
695 action_widget_activated (GtkWidget *widget, GtkDialog *dialog)
699 response_id = gtk_dialog_get_response_for_widget (dialog, widget);
701 gtk_dialog_response (dialog, response_id);
705 * gtk_dialog_add_action_widget:
706 * @dialog: a #GtkDialog
707 * @child: an activatable widget
708 * @response_id: response ID for @child
710 * Adds an activatable widget to the action area of a #GtkDialog,
711 * connecting a signal handler that will emit the #GtkDialog::response
712 * signal on the dialog when the widget is activated. The widget is
713 * appended to the end of the dialog's action area. If you want to add a
714 * non-activatable widget, simply pack it into the @action_area field
715 * of the #GtkDialog struct.
718 gtk_dialog_add_action_widget (GtkDialog *dialog,
722 GtkDialogPrivate *priv;
726 g_return_if_fail (GTK_IS_DIALOG (dialog));
727 g_return_if_fail (GTK_IS_WIDGET (child));
731 ad = get_response_data (child, TRUE);
733 ad->response_id = response_id;
735 if (GTK_IS_BUTTON (child))
736 signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
738 signal_id = GTK_WIDGET_GET_CLASS (child)->activate_signal;
744 closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
746 g_signal_connect_closure_by_id (child,
753 g_warning ("Only 'activatable' widgets can be packed into the action area of a GtkDialog");
755 gtk_box_pack_end (GTK_BOX (priv->action_area),
759 if (response_id == GTK_RESPONSE_HELP)
760 gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (priv->action_area), child, TRUE);
764 * gtk_dialog_add_button:
765 * @dialog: a #GtkDialog
766 * @button_text: text of button, or stock ID
767 * @response_id: response ID for the button
769 * Adds a button with the given text (or a stock button, if @button_text is a
770 * stock ID) and sets things up so that clicking the button will emit the
771 * #GtkDialog::response signal with the given @response_id. The button is
772 * appended to the end of the dialog's action area. The button widget is
773 * returned, but usually you don't need it.
775 * Return value: (transfer none): the #GtkButton widget that was added
778 gtk_dialog_add_button (GtkDialog *dialog,
779 const gchar *button_text,
784 g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
785 g_return_val_if_fail (button_text != NULL, NULL);
787 button = gtk_button_new_from_stock (button_text);
789 gtk_widget_set_can_default (button, TRUE);
791 gtk_widget_show (button);
793 gtk_dialog_add_action_widget (dialog,
801 gtk_dialog_add_buttons_valist (GtkDialog *dialog,
802 const gchar *first_button_text,
808 g_return_if_fail (GTK_IS_DIALOG (dialog));
810 if (first_button_text == NULL)
813 text = first_button_text;
814 response_id = va_arg (args, gint);
818 gtk_dialog_add_button (dialog, text, response_id);
820 text = va_arg (args, gchar*);
823 response_id = va_arg (args, int);
828 * gtk_dialog_add_buttons:
829 * @dialog: a #GtkDialog
830 * @first_button_text: button text or stock ID
831 * @Varargs: response ID for first button, then more text-response_id pairs
833 * Adds more buttons, same as calling gtk_dialog_add_button()
834 * repeatedly. The variable argument list should be %NULL-terminated
835 * as with gtk_dialog_new_with_buttons(). Each button must have both
836 * text and response ID.
839 gtk_dialog_add_buttons (GtkDialog *dialog,
840 const gchar *first_button_text,
845 va_start (args, first_button_text);
847 gtk_dialog_add_buttons_valist (dialog,
855 * gtk_dialog_set_response_sensitive:
856 * @dialog: a #GtkDialog
857 * @response_id: a response ID
858 * @setting: %TRUE for sensitive
860 * Calls <literal>gtk_widget_set_sensitive (widget, @setting)</literal>
861 * for each widget in the dialog's action area with the given @response_id.
862 * A convenient way to sensitize/desensitize dialog buttons.
865 gtk_dialog_set_response_sensitive (GtkDialog *dialog,
869 GtkDialogPrivate *priv;
873 g_return_if_fail (GTK_IS_DIALOG (dialog));
877 children = gtk_container_get_children (GTK_CONTAINER (priv->action_area));
880 while (tmp_list != NULL)
882 GtkWidget *widget = tmp_list->data;
883 ResponseData *rd = get_response_data (widget, FALSE);
885 if (rd && rd->response_id == response_id)
886 gtk_widget_set_sensitive (widget, setting);
888 tmp_list = g_list_next (tmp_list);
891 g_list_free (children);
895 * gtk_dialog_set_default_response:
896 * @dialog: a #GtkDialog
897 * @response_id: a response ID
899 * Sets the last widget in the dialog's action area with the given @response_id
900 * as the default widget for the dialog. Pressing "Enter" normally activates
901 * the default widget.
904 gtk_dialog_set_default_response (GtkDialog *dialog,
907 GtkDialogPrivate *priv;
911 g_return_if_fail (GTK_IS_DIALOG (dialog));
915 children = gtk_container_get_children (GTK_CONTAINER (priv->action_area));
918 while (tmp_list != NULL)
920 GtkWidget *widget = tmp_list->data;
921 ResponseData *rd = get_response_data (widget, FALSE);
923 if (rd && rd->response_id == response_id)
924 gtk_widget_grab_default (widget);
926 tmp_list = g_list_next (tmp_list);
929 g_list_free (children);
933 * gtk_dialog_response:
934 * @dialog: a #GtkDialog
935 * @response_id: response ID
937 * Emits the #GtkDialog::response signal with the given response ID.
938 * Used to indicate that the user has responded to the dialog in some way;
939 * typically either you or gtk_dialog_run() will be monitoring the
940 * ::response signal and take appropriate action.
943 gtk_dialog_response (GtkDialog *dialog,
946 g_return_if_fail (GTK_IS_DIALOG (dialog));
948 g_signal_emit (dialog,
949 dialog_signals[RESPONSE],
963 shutdown_loop (RunInfo *ri)
965 if (g_main_loop_is_running (ri->loop))
966 g_main_loop_quit (ri->loop);
970 run_unmap_handler (GtkDialog *dialog, gpointer data)
978 run_response_handler (GtkDialog *dialog,
986 ri->response_id = response_id;
992 run_delete_handler (GtkDialog *dialog,
1000 return TRUE; /* Do not destroy */
1004 run_destroy_handler (GtkDialog *dialog, gpointer data)
1008 /* shutdown_loop will be called by run_unmap_handler */
1010 ri->destroyed = TRUE;
1015 * @dialog: a #GtkDialog
1017 * Blocks in a recursive main loop until the @dialog either emits the
1018 * #GtkDialog::response signal, or is destroyed. If the dialog is
1019 * destroyed during the call to gtk_dialog_run(), gtk_dialog_run() returns
1020 * #GTK_RESPONSE_NONE. Otherwise, it returns the response ID from the
1021 * ::response signal emission.
1023 * Before entering the recursive main loop, gtk_dialog_run() calls
1024 * gtk_widget_show() on the dialog for you. Note that you still
1025 * need to show any children of the dialog yourself.
1027 * During gtk_dialog_run(), the default behavior of #GtkWidget::delete-event
1028 * is disabled; if the dialog receives ::delete_event, it will not be
1029 * destroyed as windows usually are, and gtk_dialog_run() will return
1030 * #GTK_RESPONSE_DELETE_EVENT. Also, during gtk_dialog_run() the dialog
1031 * will be modal. You can force gtk_dialog_run() to return at any time by
1032 * calling gtk_dialog_response() to emit the ::response signal. Destroying
1033 * the dialog during gtk_dialog_run() is a very bad idea, because your
1034 * post-run code won't know whether the dialog was destroyed or not.
1036 * After gtk_dialog_run() returns, you are responsible for hiding or
1037 * destroying the dialog if you wish to do so.
1039 * Typical usage of this function might be:
1041 * gint result = gtk_dialog_run (GTK_DIALOG (dialog));
1044 * case GTK_RESPONSE_ACCEPT:
1045 * do_application_specific_something ();
1048 * do_nothing_since_dialog_was_cancelled ();
1051 * gtk_widget_destroy (dialog);
1054 * Note that even though the recursive main loop gives the effect of a
1055 * modal dialog (it prevents the user from interacting with other
1056 * windows in the same window group while the dialog is run), callbacks
1057 * such as timeouts, IO channel watches, DND drops, etc, <emphasis>will</emphasis>
1058 * be triggered during a gtk_dialog_run() call.
1060 * Return value: response ID
1063 gtk_dialog_run (GtkDialog *dialog)
1065 RunInfo ri = { NULL, GTK_RESPONSE_NONE, NULL, FALSE };
1067 gulong response_handler;
1068 gulong unmap_handler;
1069 gulong destroy_handler;
1070 gulong delete_handler;
1072 g_return_val_if_fail (GTK_IS_DIALOG (dialog), -1);
1074 g_object_ref (dialog);
1076 was_modal = gtk_window_get_modal (GTK_WINDOW (dialog));
1078 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1080 if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
1081 gtk_widget_show (GTK_WIDGET (dialog));
1084 g_signal_connect (dialog,
1086 G_CALLBACK (run_response_handler),
1090 g_signal_connect (dialog,
1092 G_CALLBACK (run_unmap_handler),
1096 g_signal_connect (dialog,
1098 G_CALLBACK (run_delete_handler),
1102 g_signal_connect (dialog,
1104 G_CALLBACK (run_destroy_handler),
1107 ri.loop = g_main_loop_new (NULL, FALSE);
1109 GDK_THREADS_LEAVE ();
1110 g_main_loop_run (ri.loop);
1111 GDK_THREADS_ENTER ();
1113 g_main_loop_unref (ri.loop);
1120 gtk_window_set_modal (GTK_WINDOW(dialog), FALSE);
1122 g_signal_handler_disconnect (dialog, response_handler);
1123 g_signal_handler_disconnect (dialog, unmap_handler);
1124 g_signal_handler_disconnect (dialog, delete_handler);
1125 g_signal_handler_disconnect (dialog, destroy_handler);
1128 g_object_unref (dialog);
1130 return ri.response_id;
1134 * gtk_dialog_get_widget_for_response:
1135 * @dialog: a #GtkDialog
1136 * @response_id: the response ID used by the @dialog widget
1138 * Gets the widget button that uses the given response ID in the action area
1141 * Returns: (transfer none): the @widget button that uses the given
1142 * @response_id, or %NULL.
1147 gtk_dialog_get_widget_for_response (GtkDialog *dialog,
1150 GtkDialogPrivate *priv;
1154 g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
1156 priv = dialog->priv;
1158 children = gtk_container_get_children (GTK_CONTAINER (priv->action_area));
1160 tmp_list = children;
1161 while (tmp_list != NULL)
1163 GtkWidget *widget = tmp_list->data;
1164 ResponseData *rd = get_response_data (widget, FALSE);
1166 if (rd && rd->response_id == response_id)
1168 g_list_free (children);
1172 tmp_list = g_list_next (tmp_list);
1175 g_list_free (children);
1181 * gtk_dialog_get_response_for_widget:
1182 * @dialog: a #GtkDialog
1183 * @widget: a widget in the action area of @dialog
1185 * Gets the response id of a widget in the action area
1188 * Returns: the response id of @widget, or %GTK_RESPONSE_NONE
1189 * if @widget doesn't have a response id set.
1194 gtk_dialog_get_response_for_widget (GtkDialog *dialog,
1199 rd = get_response_data (widget, FALSE);
1201 return GTK_RESPONSE_NONE;
1203 return rd->response_id;
1207 * gtk_alternative_dialog_button_order:
1208 * @screen: (allow-none): a #GdkScreen, or %NULL to use the default screen
1210 * Returns %TRUE if dialogs are expected to use an alternative
1211 * button order on the screen @screen. See
1212 * gtk_dialog_set_alternative_button_order() for more details
1213 * about alternative button order.
1215 * If you need to use this function, you should probably connect
1216 * to the ::notify:gtk-alternative-button-order signal on the
1217 * #GtkSettings object associated to @screen, in order to be
1218 * notified if the button order setting changes.
1220 * Returns: Whether the alternative button order should be used
1225 gtk_alternative_dialog_button_order (GdkScreen *screen)
1227 GtkSettings *settings;
1231 settings = gtk_settings_get_for_screen (screen);
1233 settings = gtk_settings_get_default ();
1235 g_object_get (settings,
1236 "gtk-alternative-button-order", &result, NULL);
1242 gtk_dialog_set_alternative_button_order_valist (GtkDialog *dialog,
1243 gint first_response_id,
1246 GtkDialogPrivate *priv = dialog->priv;
1251 response_id = first_response_id;
1253 while (response_id != -1)
1255 /* reorder child with response_id to position */
1256 child = dialog_find_button (dialog, response_id);
1257 gtk_box_reorder_child (GTK_BOX (priv->action_area), child, position);
1259 response_id = va_arg (args, gint);
1265 * gtk_dialog_set_alternative_button_order:
1266 * @dialog: a #GtkDialog
1267 * @first_response_id: a response id used by one @dialog's buttons
1268 * @Varargs: a list of more response ids of @dialog's buttons, terminated by -1
1270 * Sets an alternative button order. If the
1271 * #GtkSettings:gtk-alternative-button-order setting is set to %TRUE,
1272 * the dialog buttons are reordered according to the order of the
1273 * response ids passed to this function.
1275 * By default, GTK+ dialogs use the button order advocated by the Gnome
1276 * <ulink url="http://library.gnome.org/devel/hig-book/stable/">Human
1277 * Interface Guidelines</ulink> with the affirmative button at the far
1278 * right, and the cancel button left of it. But the builtin GTK+ dialogs
1279 * and #GtkMessageDialog<!-- -->s do provide an alternative button order,
1280 * which is more suitable on some platforms, e.g. Windows.
1282 * Use this function after adding all the buttons to your dialog, as the
1283 * following example shows:
1285 * cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
1287 * GTK_RESPONSE_CANCEL);
1289 * ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
1293 * gtk_widget_grab_default (ok_button);
1295 * help_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
1297 * GTK_RESPONSE_HELP);
1299 * gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
1301 * GTK_RESPONSE_CANCEL,
1302 * GTK_RESPONSE_HELP,
1309 gtk_dialog_set_alternative_button_order (GtkDialog *dialog,
1310 gint first_response_id,
1316 g_return_if_fail (GTK_IS_DIALOG (dialog));
1318 screen = gtk_widget_get_screen (GTK_WIDGET (dialog));
1319 if (!gtk_alternative_dialog_button_order (screen))
1322 va_start (args, first_response_id);
1324 gtk_dialog_set_alternative_button_order_valist (dialog,
1330 * gtk_dialog_set_alternative_button_order_from_array:
1331 * @dialog: a #GtkDialog
1332 * @n_params: the number of response ids in @new_order
1333 * @new_order: (array length=n_params): an array of response ids of
1336 * Sets an alternative button order. If the
1337 * #GtkSettings:gtk-alternative-button-order setting is set to %TRUE,
1338 * the dialog buttons are reordered according to the order of the
1339 * response ids in @new_order.
1341 * See gtk_dialog_set_alternative_button_order() for more information.
1343 * This function is for use by language bindings.
1348 gtk_dialog_set_alternative_button_order_from_array (GtkDialog *dialog,
1352 GtkDialogPrivate *priv = dialog->priv;
1357 g_return_if_fail (GTK_IS_DIALOG (dialog));
1358 g_return_if_fail (new_order != NULL);
1360 screen = gtk_widget_get_screen (GTK_WIDGET (dialog));
1361 if (!gtk_alternative_dialog_button_order (screen))
1364 for (position = 0; position < n_params; position++)
1366 /* reorder child with response_id to position */
1367 child = dialog_find_button (dialog, new_order[position]);
1368 gtk_box_reorder_child (GTK_BOX (priv->action_area), child, position);
1379 GtkBuilder *builder;
1382 } ActionWidgetsSubParserData;
1385 attributes_start_element (GMarkupParseContext *context,
1386 const gchar *element_name,
1387 const gchar **names,
1388 const gchar **values,
1392 ActionWidgetsSubParserData *parser_data = (ActionWidgetsSubParserData*)user_data;
1395 if (strcmp (element_name, "action-widget") == 0)
1397 for (i = 0; names[i]; i++)
1398 if (strcmp (names[i], "response") == 0)
1399 parser_data->response = g_strdup (values[i]);
1401 else if (strcmp (element_name, "action-widgets") == 0)
1404 g_warning ("Unsupported tag for GtkDialog: %s\n", element_name);
1408 attributes_text_element (GMarkupParseContext *context,
1414 ActionWidgetsSubParserData *parser_data = (ActionWidgetsSubParserData*)user_data;
1415 ActionWidgetInfo *item;
1417 if (!parser_data->response)
1420 item = g_new (ActionWidgetInfo, 1);
1421 item->widget_name = g_strndup (text, text_len);
1422 item->response_id = parser_data->response;
1423 parser_data->items = g_slist_prepend (parser_data->items, item);
1424 parser_data->response = NULL;
1427 static const GMarkupParser attributes_parser =
1429 attributes_start_element,
1431 attributes_text_element,
1435 gtk_dialog_buildable_custom_tag_start (GtkBuildable *buildable,
1436 GtkBuilder *builder,
1438 const gchar *tagname,
1439 GMarkupParser *parser,
1442 ActionWidgetsSubParserData *parser_data;
1447 if (strcmp (tagname, "action-widgets") == 0)
1449 parser_data = g_slice_new0 (ActionWidgetsSubParserData);
1450 parser_data->dialog = GTK_DIALOG (buildable);
1451 parser_data->items = NULL;
1453 *parser = attributes_parser;
1454 *data = parser_data;
1458 return parent_buildable_iface->custom_tag_start (buildable, builder, child,
1459 tagname, parser, data);
1463 gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
1464 GtkBuilder *builder,
1466 const gchar *tagname,
1469 GtkDialog *dialog = GTK_DIALOG (buildable);
1470 GtkDialogPrivate *priv = dialog->priv;
1472 ActionWidgetsSubParserData *parser_data;
1477 if (strcmp (tagname, "action-widgets"))
1479 parent_buildable_iface->custom_finished (buildable, builder, child,
1480 tagname, user_data);
1484 parser_data = (ActionWidgetsSubParserData*)user_data;
1485 parser_data->items = g_slist_reverse (parser_data->items);
1487 for (l = parser_data->items; l; l = l->next)
1489 ActionWidgetInfo *item = l->data;
1491 object = gtk_builder_get_object (builder, item->widget_name);
1494 g_warning ("Unknown object %s specified in action-widgets of %s",
1496 gtk_buildable_get_name (GTK_BUILDABLE (buildable)));
1500 ad = get_response_data (GTK_WIDGET (object), TRUE);
1501 ad->response_id = g_ascii_strtoll (item->response_id, NULL, 10);
1503 if (GTK_IS_BUTTON (object))
1504 signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
1506 signal_id = GTK_WIDGET_GET_CLASS (object)->activate_signal;
1512 closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
1514 g_signal_connect_closure_by_id (object,
1521 if (ad->response_id == GTK_RESPONSE_HELP)
1522 gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (priv->action_area),
1523 GTK_WIDGET (object), TRUE);
1525 g_free (item->widget_name);
1526 g_free (item->response_id);
1529 g_slist_free (parser_data->items);
1530 g_slice_free (ActionWidgetsSubParserData, parser_data);
1534 * gtk_dialog_get_action_area:
1535 * @dialog: a #GtkDialog
1537 * Returns the action area of @dialog.
1539 * Returns: (transfer none): the action area.
1544 gtk_dialog_get_action_area (GtkDialog *dialog)
1546 g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
1548 return dialog->priv->action_area;
1552 * gtk_dialog_get_content_area:
1553 * @dialog: a #GtkDialog
1555 * Returns the content area of @dialog.
1557 * Returns: (transfer none): the content area #GtkBox.
1562 gtk_dialog_get_content_area (GtkDialog *dialog)
1564 g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
1566 return dialog->priv->vbox;