When the form is complete, you return it to the person who gave it to you. The attendant can check it over to see if
you forgot something. If there are errors, you typically take it back and continue until it's right. The attendant can
simply ask you the question straight out and write down whatever you say, but this prevents him from doing other
work or dealing with other people. Furthermore, if you don't know the answer to the question right away, then you
have to take the form back and fill it out the way you were doing it before. No matter how you look at it, this process
is not an interview where you are asked questions in sequence and must answer them that way. You are supposed to
prepare the form off−line, without requiring interaction from anyone else.
Window−based applications should be treated no differently. Each window, or dialog, can be considered to be a form
of some sort. Allow the user to fill out the form at her own convenience and however she chooses. If she wants to
interact with other parts of the application or other programs on the desktop, she should be allowed to do so. When the
user selects one of the buttons in the action area, this action is her way of returning the form. At this time, you may
either accept it or reject it. At no point in the process so far have we needed a modal dialog.
Once the form has been submitted, you can take whatever action is appropriate. If there are errors in any section of the
dialog, you may need to notify the user of the error. Here is where a modal dialog can be used legitimately. For
example, if the user is using a FileSelectionDialog to specify the file she wants to read and the file is unreadable, then
you must notify her so that she can make another selection. In this case, the notification is usually in the form of an
ErrorDialog, with a message that explains the error and an OK button. The user can read the message and press the
button to acknowledge the error.
It is often difficult to judge what types of questions or how much information is appropriate in modal dialogs. The rule
of thumb is that questions in modal dialogs should be limited to simple, yes/no questions. You should not prompt for
any information that is already available through an existing dialog, but instead bring up that dialog and instruct the
user to provide the necessary information there. You should also avoid posting modal dialogs that prompt for a
filename or anything else that requires typing. You should be requesting this type of information through the text
fields of modeless dialog boxes.
As for the issue of forcing the user to fill out forms in a particular order, it may be perfectly reasonable to require this
type of interaction. You should implement these restrictions by managing and unmanaging separate dialogs, rather
than by using modal dialogs to prevent interaction with all but a single dialog.
All of these admonitions are not to suggest that modal dialogs are rare or that you should avoid using them at all costs.
On the contrary, they are extremely useful in certain situations, are quite common, and are used in a wide variety of
ways−−even those that we might not recommend. We have presented all of these warnings because modal dialogs are
frequently misused and programs that use fewer of them are usually better than those that use more of them. Modal
dialogs interrupt the user and disrupt the flow of work in an application. There is no sanity checking to prevent you
from misusing dialogs so it is up to you to keep the use of modal dialogs to a minimum.
6.7.1 Implementing Modal Dialogs
Once you have determined that you need to implement a modal dialog, you can use the -XmNdialogStyle resource
to set the modality of the dialog. This resource is defined by the BulletinBoard widget class; it is only relevant when
the widget is an immediate child of a DialogShell. The resource can be set to one of the following values: The value
XmDIALOG_APPLICATION_MODAL is used for backwards compatibility with Motif 1.0; it is defined to be the same
as XmDIALOG_PRIMARY_APPLICATION_MODAL.
XmDIALOG_MODELESS
XmDIALOG_PRIMARY_APPLICATION_MODAL
XmDIALOG_FULL_APPLICATION_MODAL
XmDIALOG_SYSTEM_MODAL
6 Introduction to Dialogs 6.7.1 Implementing Modal Dialogs
133
XmDIALOG_MODELESS is the default value for the resource, so unless you change the value any dialog that you
create will be modeless.
When you use one of the modal values, the user has no choice but to respond to your dialog box before continuing to
interact with the application. If you use modality at all, you should probably avoid using
XmDIALOG_SYSTEM_MODAL, since it is rarely necessary to restrict the user from interacting with all of the other
applications on the desktop. This style of modality is typically reserved for system−level interactions. Under the Motif
Window Manager, when a system modal dialog is popped up, if the user moves the mouse outside of the modal
dialog, the cursor turns into the international "do not enter" symbol. Attempts to interact with other windows cause the
server to beep.
the source code shows a sample program that displays a dialog box that the user must reply to before continuing to
interact with the application. XtSetLanguageProc() is only available in X11R5; there is no corresponding
function in X11R4. XmStringCreateLocalized() is only available in Motif 1.2;
XmStringCreateSimple() is the corresponding function in Motif 1.1.
/* modal.c −− demonstrate modal dialogs. Display two pushbuttons
* each activating a modal dialog.
*/
#include <Xm/RowColumn.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
/* main() −−create a pushbutton whose callback pops up a dialog box */
main(argc, argv)
char *argv[];
{
XtAppContext app;
Widget toplevel, button, rowcolumn;
void pushed();
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos",
NULL, 0, &argc, argv, NULL, NULL);
rowcolumn = XtCreateManagedWidget ("rowcolumn",
xmRowColumnWidgetClass, toplevel, NULL, 0);
button = XtCreateManagedWidget ("Application Modal",
xmPushButtonWidgetClass, rowcolumn, NULL, 0);
XtAddCallback (button, XmNactivateCallback,
pushed, XmDIALOG_FULL_APPLICATION_MODAL);
button = XtCreateManagedWidget ("System Modal",
xmPushButtonWidgetClass, rowcolumn, NULL, 0);
XtAddCallback (button, XmNactivateCallback, pushed,
XmDIALOG_SYSTEM_MODAL);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
/* pushed() −−the callback routine for the main app's pushbutton.
* Create either a full−application or system modal dialog box.
*/
void
pushed(widget, client_data, call_data)
Widget widget;
6 Introduction to Dialogs 6.7.1 Implementing Modal Dialogs
134
XtPointer client_data;
XtPointer call_data;
{
static Widget dialog;
XmString t;
extern void dlg_callback();
unsigned char modality = (unsigned char) client_data;
/* See if we've already created this dialog −− if so,
* we don't need to create it again. Just re−pop it up.
*/
if (!dialog) {
Arg args[5];
int n = 0;
XmString ok = XmStringCreateLocalized ("OK");
XtSetArg(args[n], XmNautoUnmanage, False); n++;
XtSetArg(args[n], XmNcancelLabelString, ok); n++;
dialog = XmCreateInformationDialog (widget, "notice", args, n);
XtAddCallback (dialog, XmNcancelCallback, dlg_callback, NULL);
XtUnmanageChild (
XmMessageBoxGetChild (dialog, XmDIALOG_OK_BUTTON));
XtUnmanageChild (
XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));
}
t = XmStringCreateLocalized ("You must reply to this message now!");
XtVaSetValues (dialog,
XmNmessageString, t,
XmNdialogStyle, modality,
NULL);
XmStringFree (t);
XtManageChild (dialog);
XtPopup (XtParent (dialog), XtGrabNone);
}
void
dlg_callback(dialog, client_data, call_data)
Widget dialog;
XtPointer client_data;
XtPointer call_data;
{
XtPopdown (XtParent (dialog));
}
The output of this program is shown in the figure.
6 Introduction to Dialogs 6.7.1 Implementing Modal Dialogs
135

Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.