Since the InformationDialog is a child of the MessageDialog, if the MessageDialog is destroyed, the
InformationDialog is also destroyed. Similarly, if the MessageDialog is unmapped, so is the InformationDialog. In
general, when you display an InformationDialog, you should remove it if the user unmanages, destroys, or otherwise
disables the dialog from which it was posted because if the help dialog remains posted, it could confuse the user. By
making the InformationDialog the child of the original dialog, you can let the parent−child interaction handle this
behavior.
22.1.1 Multi−level Help
Developing a help systen may involve providing multiple levels of help information. If the user has already posted an
InformationDialog, it is possible to display an additional dialog if the user requests help in the original dialog.
However, multiple help windows can confuse the user, so they should be avoided. A better solution is to display the
new help text in the same InformationDialog, so that all of the help information is displayed in the same place. the
source code shows new help_callback() and help_done() routines that implement this technique.
XmStringCreateLocalized() is only available in Motif 1.2; XmStringCreateSimple() is the
corresponding function in Motif 1.1. XmFONTLIST_DEFAULT_TAG replaces XmSTRING_DEFAULT_CHARSET in
Motif 1.2.
#define MAX_HELP_STAGES 3
char *help_text[3][5] = {
{
"You have reached the first stage of the help system.",
"If you need additional help, select the 'More Help' button.",
"You may exit help at any time by pressing 'Done'.",
NULL,
},
{
"This is the second stage of the help system. There is",
"more help available. Press 'More Help' to see more.",
"Press 'Previous' to return to the previous help message,",
"or press 'Done' to exit the help system.",
NULL,
},
{
"This is the last help message you will see on this topic.",
"You may either press 'Previous' to return to the previous",
"help level, or press 'Done' to exit the help system.",
NULL,
}
};
/* help_callback() −− callback routine for the Help button in the
* original dialog box. The routine also serves as its own help
* callback for displaying multiple levels of help messages.
*/
void
help_callback(parent, client_data, call_data)
Widget parent;
XtPointer client_data;
XtPointer call_data;
{
static Widget dialog; /* prevent multiple help dialogs */
XmString text;
char buf[BUFSIZ], *p;
static int index;
int i;
void help_done();
22 Advanced Dialog Programming 22.1.1 Multi−level Help
603
int index_incr = (int) client_data;
if (dialog && index_incr == 0) {
/* user pressed Help button in MesageDialog again. We're
* already up, so just make sure we're visible and return. */
XtPopup (XtParent (dialog), XtGrabNone);
XMapRaised (XtDisplay (dialog), XtWindow (XtParent (dialog)));
return;
}
if (dialog)
index += index_incr; /* more/previous help; change index */
else {
/* We're not up, so create new Help Dialog */
Arg args[5];
int n;
/* Action area button labels. */
XmString done = XmStringCreateLocalized ("Done");
XmString cancel = XmStringCreateLocalized ("Previous");
XmString more = XmStringCreateLocalized ("More Help");
n = 0;
XtSetArg (args[n], XmNautoUnmanage, False); n++;
XtSetArg (args[n], XmNokLabelString, done); n++;
XtSetArg (args[n], XmNcancelLabelString, cancel); n++;
XtSetArg (args[n], XmNhelpLabelString, more); n++;
dialog = XmCreateInformationDialog (parent, "help", args, n);
/* pass help_done() the address of "dialog" so it can reset */
XtAddCallback (dialog, XmNokCallback, help_done, &dialog);
/* if more/previous help, recall ourselves with increment */
XtAddCallback (dialog, XmNcancelCallback, help_callback, −1);
XtAddCallback (dialog, XmNhelpCallback, help_callback, 1);
/* If our parent dies, we must reset "dialog" to NULL! */
XtAddCallback (dialog, XmNdestroyCallback, help_done, &dialog);
XmStringFree (done); /* once dialog is created, these */
XmStringFree (cancel); /* strings are no longer needed. */
XmStringFree (more);
index = 0; /* initialize index−−needed for each new help stuff */
}
/* concatenate help text into a single string with newlines */
for (p = buf, i = 0; help_text[index][i]; i++) {
p += strlen (strcpy (p, help_text[index][i]));
*p++ = '0;
*p = 0;
}
text = XmStringCreateLtoR (buf, XmFONTLIST_DEFAULT_TAG);
XtVaSetValues (dialog, XmNmessageString, text, NULL);
XmStringFree (text); /* after set−values, free unneeded memory */
/* If no previous help msg, set "Previous" to insensitive. */
XtSetSensitive (
XmMessageBoxGetChild (dialog,XmDIALOG_CANCEL_BUTTON), index > 0);
/* If no more help, set "More Help" insensitive. */
22 Advanced Dialog Programming 22.1.1 Multi−level Help
604
XtSetSensitive (XmMessageBoxGetChild (
dialog, XmDIALOG_HELP_BUTTON), index < MAX_HELP_STAGES−1);
/* display the dialog */
XtManageChild (dialog);
XtPopup (XtParent (dialog), XtGrabNone);
}
/* help_done () −− callback used to set the dialog pointer
* to NULL so it can't be referenced again by help_callback().
* This function is called from the Done button in the help dialog.
* It is also our XmNdestroyCallback, so reset our dialog_ptr to NULL.
*/
void
help_done(dialog, client_data, call_data)
Widget dialog;
XtPointer client_data;
XtPointer call_data;
{
Widget *dialog_ptr;
if (!client_data) { /* destroy original MessageDialog */
XtDestroyWidget (dialog);
return;
}
dialog_ptr = (Widget *) client_data;
if (!*dialog_ptr) /* prevent unnecessarily destroying twice */
return;
XtDestroyWidget (dialog); /* this might call ourselves.. */
*dialog_ptr = NULL;
}
In our help system, each level has a new help string that needs to be displayed. All of the help text is displayed in the
same InformationDialog. The dialog for the first level of help is shown in the figure.
Displaying multiple levels of help text
The help_callback routine addresses several problems that arise when dealing with the added complexity of a
multi−level help system. Since many dialogs may be trying to pop up the same InformationDialog, the routine uses a
static variable for the dialog to prevent multiple instances of the dialog. This variable allows the routine to keep track
of when the dialog is active and when it is dormant.
22 Advanced Dialog Programming 22.1.1 Multi−level Help
605
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.