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.

HowDoI/Dialogs (last edited 2014-07-30 07:15:17 by DavidKing)