The difference between a good dialog and a great dialog
is in the details.
GnomeDialog comes with a number of features to
make that final polish easy. Figure 4 sums
them up.
Dialogs have a logical parent,
usually the main application window. You can tell the
library about this parent-child relationship; this lets
Gnome honor certain user preferences, and in turn
indicates the relationship to the window manager. Most
window managers will minimize child dialogs when the
parent window is minimized, and keep child dialogs on
top of their parent.
It's important to use
gnome_dialog_set_parent() with transient dialogs only. A transient
dialog is one that appears and is dismissed relatively
quickly. (GnomeDialog is
really meant for transient dialogs.) Some "dialogs" are
just small windows, such as the tool palette in the
Gimp. These persistent ("floating") dialogs should be
minimizable without minimizing the parent, and they
should not be forced to stay above the parent window.
Your dialog should have a sensible default button---this is the button
activated when the user presses the Enter key. gnome_dialog_set_default()
specifies the default button. It's a judgment call
which button should be the default. Often the best
choice is the least-destructive action (i.e., "Cancel"
rather than "OK"), but if neither is destructive, user
convenience might guide your decision.
Typically, operations such as deleting data or quitting
an application have "Cancel" or "No" as the default;
dialogs that ask the user to enter text or other
information typically have "OK" as the default.
Remember that many window managers will focus windows
when they pop up, so keystrokes users intend to go to
their current application might go to your dialog
instead. If your dialog has "delete all my files" as
the default button, you will get hate mail.
Editable widgets emit the
"activate" signal when Enter is pressed.
Typically users expect Enter to activate the default
dialog button, but if you have an editable widget such
as GtkEntry in your dialog,
it will capture any Enter presses, and keep the
dialog's buttons from responding to them. gnome_dialog_editable_enters()
activates the dialog's default button when the GtkEditable is activated,
solving the problem.
gnome_dialog_set_sensitive()
calls
gtk_widget_set_sensitive() on button. If clicking a button makes
no sense at a given time it should be desensitized.
Finally, you should make sure you do not create
multiple instances of a dialog. Many applications allow
you to pop up multiple Preferences or About dialogs;
users will not trigger this bug very often, but it is a
nice touch to avoid the problem. The following code
deals with it in a simple way (note that the details of
creating and showing the dialog have been omitted).
void
do_dialog()
{
static GtkWidget* dialog = NULL;
if (dialog != NULL)
{
/* This code tries to de-iconify and raise the dialog.
* It assumes the dialog is realized; if you can't
* ensure that, check that dialog->window != NULL.
*/
gdk_window_show(dialog->window);
gdk_window_raise(dialog->window);
}
else
{
dialog = gnome_dialog_new(); /* Arguments elided. */
gtk_signal_connect(GTK_OBJECT(dialog),
"destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed),
&dialog);
/* Show the dialog, connect callbacks, etc. here */
}
}
|
gtk_widget_destroyed() is
defined in gtk/gtkwidget.h,
and simply assigns NULL
to its second argument. The code resets the dialog variable each time the
user closes the dialog, and raises/deiconifies the
dialog if the user tries to open it while another one
is active. Note that the window manager has some say in
whether the raise/deiconify is successful, so it is not
guaranteed to happen.