8 Custom Dialogs
This chapter describes how to create new types of dialogs, either by customizing Motif dialogs or by creating entirely
new dialogs.
In this chapter we examine methods for creating your own dialogs. The need for such dialogs exists when those
provided by Motif are too limited in functionality or are not specialized enough for your application. Sometimes it is
not clear when you need to create your own dialog. In some situations, you may find that a Motif dialog would be just
fine if only they did this one little thing. Fortunately, you can often make small adjustments to a predefined Motif
dialog, rather than building an entirely new dialog box from scratch.
There are some issues to consider before you decide how you want to approach the problem of developing custom
dialogs. For example, do you want to use your own widget layout or is the layout of one of the predefined dialogs
sufficient? Do you have specialized user−-interface appearance and functionality needs that go beyond what is
provided by Motif? The answers to these questions affect the design of your dialogs. The discussion and examples
provided in this chapter address both scenarios. We provide information on how to create dialogs that are based on the
predefined Motif dialogs, as well as how to design completely new dialogs.
Before we get started, we should mention that creating your own dialogs makes heavy use of manager widgets, such
as the Form, BulletinBoard, RowColumn, and PanedWindow widgets. While we use and describe the manager
widgets in context, you may want to consult Chapter 8, Manager Widgets, for specific details about these widgets.
8.1 Modifying Motif Dialogs
We begin by discussing the simpler case of modifying existing Motif dialogs. In Chapter 5, Introduction to Dialogs,
we showed you how to modify a dialog to some extent by changing the default labels on the buttons in the action area
or by unmanaging or desensitizing certain components in the dialog. What we did not mention is that you can also add
new components to a dialog box to expand its functionality. All of the predefined Motif dialog widgets let you add
children. In this sense, you can treat a dialog as a manager widget. In Motif 1.1, you can only add a single work area
child to a Motif dialog, which limits the amount of customization that is possible. Motif 1.2 allows you to add multiple
children to an existing dialog, so you can provide additional controls, action area buttons, and even a MenuBar.
8.1.1 Modifying MessageDialogs
At the end of Chapter 5, Introduction to Dialogs, we described a scenario where an application might want to have
more than three action area buttons in a MessageDialog. If the user has selected the Quit button in a text editor but has
not saved her changes, an application might want to post a dialog that asks about saving the changes before exiting.
The user could want to save the changes and exit, not save the changes and exit anyway, cancel the exit operation, or
get help.
In Motif 1.1, the MessageDialog only supported three action area buttons, so creating a dialog with four buttons
required designing a custom dialog. However, in Motif 1.2, the MessageDialog allows you to provide additional
action area buttons. the source code demonstrates how to create a QuestionDialog with four action area buttons. This
example uses functionality that is new in Motif 1.2, so it only works with the 1.2 version of the Motif toolkit.
/* question.c −− create a QuestionDialog with four action buttons
*/
#include <Xm/MessageB.h>
165
#include <Xm/PushB.h>
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext app;
Widget toplevel, pb;
extern void pushed();
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
pb = XtVaCreateManagedWidget ("Button",
xmPushButtonWidgetClass, toplevel, NULL);
XtAddCallback (pb, XmNactivateCallback, pushed, NULL);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
void
pushed(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
Widget dialog, no_button;
extern void dlg_callback();
Arg args[5];
int n = 0;
XmString m = XmStringCreateLocalized
("Do you want to update your changes?");
XmString yes = XmStringCreateLocalized ("Yes");
XmString no = XmStringCreateLocalized ("No");
XtSetArg (args[n], XmNautoUnmanage, False); n++;
XtSetArg (args[n], XmNmessageString, m); n++;
XtSetArg (args[n], XmNokLabelString, yes); n++;
dialog = XmCreateQuestionDialog (w, "notice", args, n);
XtAddCallback (dialog, XmNokCallback, dlg_callback, NULL);
XtAddCallback (dialog, XmNcancelCallback, dlg_callback, NULL);
XtAddCallback (dialog, XmNhelpCallback, dlg_callback, NULL);
XmStringFree (m);
XmStringFree (yes);
no_button = XtVaCreateManagedWidget ("no",
xmPushButtonWidgetClass, dialog,
XmNlabelString, no,
NULL);
XtAddCallback (no_button, XmNactivateCallback, dlg_callback, NULL);
XtManageChild (dialog);
XtPopup (XtParent (dialog), XtGrabNone);
}
void
dlg_callback(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
8 Custom Dialogs 8 Custom Dialogs
166
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
switch (cbs−>reason) {
case XmCR_OK :
case XmCR_CANCEL :
XtPopdown (XtParent (w));
break;
case XmCR_ACTIVATE :
XtPopdown (XtParent (XtParent (w)));
break;
case XmCR_HELP :
puts ("Help selected");
}
}
The dialog box from the program is shown in the figure.
Output of question.c
The extra button is added to the dialog by creating a PushButton as a child of the dialog. We are treating the
MessageDialog just like any other manager widget. The MessageDialog inserts any additional PushButton children
into the action area after the OK button, which is why we added a No button. If you add more than one button, they
are all put after the OK button, in the order that you create them. We have also changed the label of the OK button so
that it is now the Yes button.
Since the No button is not part of the standard MessageDialog, we have to set the callback routine on its
XmNactivateCallback. For the rest of the buttons, we use the callbacks defined by the dialog. The dialog
callback routine, dlg_callback(), has to handle the various callbacks in different ways. By checking the
reason field of the callback structure, the routine can determine which button was selected. For the Yes and Cancel
buttons, the routine unposts the dialog by popping down the DialogShell parent of the dialog. For the No button, we
need to be a bit more careful about popping down the right widget. Since the widget in this case is the PushButton,
we need to call XtParent() twice to get the DialogShell.
With Motif 1.2, the MessageDialog also supports the addition of other children besides PushButtons. If you add a
MenuBar child, it is placed across the top of the dialog, although it is not clear why you would want a MenuBar in a
MessageDialog. Any other type of widget child is considered the work area. The work area is placed below the
message text if it exists. If there is a symbol, but no message, the work area is placed to the right of the symbol. The
MessageDialog only supports the addition of one work area; the layout of multiple work area children is undefined. In
Motif 1.1, only a single work area child can be added to a MessageDialog. This child is always placed below the
message text.
8 Custom Dialogs 8 Custom Dialogs
167
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.