Dialogs
GtkDialog is a very flexible API (really, too flexible), and lets you do many things in multiple ways. This document tries to capture best practices. The Dialogs section of the HIG is a very good source for design questions about dialog.
Constructing Dialogs
GtkDialog and GtkMessageDialog have a number of constructors that allow to specify multiple ingredients in a compact form:
- transient parent
- flags, including modality and whether to use a header bar
- buttons
- text content (for message dialogs)
Typical usage looks like this
dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
GTK_DIALOG_MODAL|
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"The system network services are not compatible with this version.");
or this
dialog = gtk_dialog_new_with_buttons ("Warning",
GTK_WINDOW (parent),
GTK_DIALOG_MODAL|
GTK_DIALOG_DESTROY_WITH_PARENT,
"OK", GTK_RESPONSE_APPLY,
NULL);
Dialogs should always have a transient parent, GTK+ warns you if you don't do it.
You can also use a GtkBuilder ui file to create a dialog:
<object class="GtkDialog" id="dialog">
<child type="action">
<object class="GtkButton" id="cancel">
<property name="visible">True</property>
<property name="label">Cancel</property>
</object>
</child>
<child type="action">
<object class="GtkButton" id="apply">
<property name="visible">True</property>
<property name="label">Create Event</property>
<property name="can-default">True</property>
</object>
</child>
...
<action-widgets>
<action-widget response="cancel">cancel</action-widget>
<action-widget response="apply" default="true">apply</action-widget>
</action-widgets>
</object>
Headerbars
GTK+ dialogs can use header bars to place buttons and other action widgets at the top instead of the traditional action area at the bottom. The builtin dialogs in GTK+ adapt to the needs of the desktop they run under by looking at the gtk-dialogs-use-header. Custom dialogs use the action area by default.
To specify that a custom dialog should use a header bar when using a dialog constructor, it is best to use the GTK_DIALOG_USE_HEADER_BAR flag:
dialog = gtk_dialog_new_with_buttons ("Warning",
GTK_WINDOW (parent),
GTK_DIALOG_MODAL|
GTK_DIALOG_USE_HEADER_BAR|
GTK_DIALOG_DESTROY_WITH_PARENT,
"OK", GTK_RESPONSE_APPLY,
NULL);
To specify that a custom dialog should use a header bar when using a dialog constructor, it is best to specify the use-header-bar property for the dialog:
<object class="GtkDialog" id="dialog">
<property name="use-header-bar">1</property>
<child type="action">
<object class="GtkButton" id="cancel">
<property name="visible">True</property>
<property name="label">Cancel</property>
</object>
</child>
<child type="action">
<object class="GtkButton" id="apply">
<property name="visible">True</property>
<property name="label">Create Event</property>
<property name="can-default">True</property>
</object>
</child>
...
<action-widgets>
<action-widget response="cancel">cancel</action-widget>
<action-widget response="apply" default="true">apply</action-widget>
</action-widgets>
</object>
GTK+ will move buttons (and action widgets) to the header bar that are added in the constructor, and buttons that are added via gtk_dialog_add_button() or gtk_dialog_add_action_widget(), and buttons that are specified as child with type="action" in a ui file. Widgets that are manually added to the action area or header bar (in code or in a ui file) will not be moved, and GTK+ will ensure that the action area is visible if it contains such children.
Note in particular that children that are added manually in the ui file like this:
<object class="GtkDialog" id="dialog">
...
<child internal-child="action_area">
<object class="GtkButtonBox">
<child>
<object class="GtkButton" id="cancel">
<property name="visible">True</property>
<property name="label">Cancel</property>
</object>
</child>
</object>
</child>
...
are not relocated. Please use
<object class="GtkDialog" id="dialog">
...
<child type="action">
<object class="GtkButton" id="cancel">
<property name="visible">True</property>
<property name="label">Cancel</property>
</object>
</child>
...
for creating relocatable action widgets in a ui file.
Adaptive dialogs
GTK+ builtin dialogs will automatically use a header bar or not, depending on the value of the gtk-dialogs-use-header setting. To achieve the same behavior for custom dialogs, apply the setting yourself like this:
g_object_get (gtk_settings_get_default (), "gtk-dialogs-use-header", &use_header, NULL);
dialog = g_object_new (GTK_TYPE_DIALOG,
"transient-for", parent,
"use-header-bar", use_header,
NULL);
Note that use-header-bar is a construct property, and thus can't be set in a widget template .ui file. Instead you have to specify it when constructing the object, as shown above.