ViewKit ObjectPak Dialog Base Class

This section describes the dialog management features provided by the abstract VkDialogManager base class. It describes how to post dialogs, unpost dialogs, set dialog titles, and set dialog button labels. Because all ViewKit ObjectPak dialog management classes are derived from VkDialogManager, the functions and techniques described in this section apply to all dialog management classes.

Posting Dialogs

This section describes the various methods of posting dialogs and provides some simple examples.

Methods of posting dialogs

The following table describes the four functions ViewKit ObjectPak offers for posting dialogs:

 

 

Function

Description

post()

Posts a non-blocking, non-modal dialog. The function immediately returns, and the application continues to process user input in all windows.

postModal()

Posts a non-blocking, full-application-modal dialog. The function immediately returns, but the user cannot interact with any application windows until after dismissing the dialog.

postBlocked()

Posts a blocking, full-application-modal dialog. The user cannot interact with any application windows until after dismissing the dialog. Furthermore, the function does not return until the user dismisses the dialog.

postAndWait()

Posts a blocking, full-application-modal dialog. The user cannot interact with any application windows until after dismissing the dialog. Furthermore, the function does not return until the user dismisses the dialog. postAndWait() is simpler to use than postBlocked(), but it does not allow as much programming flexibility.

 

 

post(), postModal(), and postBlocked() accept the same arguments, and are also overloaded identically to allow for almost any combination of arguments without resorting to using NULLs as placeholders. Consult the VkDialogManager(3) reference page for a complete listing of the overloaded versions of the post(), postModal(), and postBlocked() functions.

post () function

The following code shows the most general form of the post() function:

virtual Widget post ( const char *msg = NULL,
XtCallbackProc okCB = NULL,
XtCallbackProc cancelCB = NULL,
XtCallbackProc applyCB = NULL,
XtPointer clientData = NULL,
const char *helpString = NULL,
Widget *parent = NULL)

The arguments for these methods are:

msg The message to display in the dialog. This string is first treated as a resource name which is looked up relative to the dialog widget. If it exists, the resource value is used as the message. If the resource does not exist, or if the string contains spaces or newline characters, the string itself is used as the message.

Most dialogs are not useful if you do not provide a message argument: they display no text. VkFileDialog and VkPreferenceDialog are exceptions in that they provide their own complex interfaces.

okCB An Xt-style callback function executed when the user clicks on the OK button. (All dialogs except for the VkBusyDialog and VkInterruptDialog dialogs display an OK button by default.)

cancelCB An Xt-style callback function executed when the user clicks on the Cancel button. For many of the dialog classes, ViewKit ObjectPak does not display a Cancel button unless you provide this callback.

applyCB An Xt-style callback function executed when the user clicks on the Apply button. For many of the dialog classes, ObjectPak does not display an Apply button unless you provide this callback.

clientData Client data to pass to the button callback functions. Following ObjectPak conventions as described in "Using Xt Callbacks with Components" , you should normally pass the this pointer as client data so that the callback functions can retrieve the pointer, cast it to the expected component type, and call a corresponding member function.

helpString A help string to pass to the help system. See Appendix C-- Using a Help System for information on the help system. If you provide a string, the dialog displays a Help button.

parent The widget over which ViewKit ObjectPak should display the dialog. If you do not provide a widget, or if the given widget is hidden or iconified, ObjectPak posts the dialog over the main window if it is managed and not iconified. ("Managing Top-Level Windows" describes how the main window is determined.) If both the widget you specify and the main window are hidden or iconified, ObjectPak posts the dialog as a child of the hidden application shell created by the VkApp class. Also see the description of VkDialogManager::centerOnScreen() in "Dialog Access and Utility Functions" .

All versions of the post(), postModal(), and postBlocked() functions return the widget ID of the posted dialog. You should rarely need to use this value.


Note: The arguments that you provide apply only to the dialog posted by the current call to post(), postModal(), and postBlocked(); they have no effect on subsequent dialogs. For example, if you provide an apply callback function to a call to post(), it is used only for the dialog posted by that call. If you want to use that callback for subsequent dialogs, you must provide it as an argument every time you post a dialog.


postAndWait () function

postAndWait() provides a simpler method for posting blocking, application-modal dialogs than using postBlocked(). The most general form of the postAndWait() function is:

virtual VkDialogReason postAndWait ( const char *msg = NULL,
Boolean ok = TRUE,
Boolean cancel = TRUE,
Boolean apply = FALSE,
const char *helpString = NULL,
Widget *parent = NULL)

msg is the message to display in the dialog. As with the other posting functions, postAndWait() first treats the string as a resource name which it looks up relative to the dialog widget. If the resource exists, postAndWait() uses the resource value as the message. If postAndWait() finds no resource, or if the string contains spaces or newline characters, it uses the string itself as the message. The next three arguments determine which buttons the dialog should display. A TRUE value displays the button and a FALSE value hides the button. helpString and parent specify a help string and a parent window, just as with the other posting functions.


Note: The arguments that you provide apply only to the dialog posted by the current call to postAndWait() and have no effect on subsequent dialogs.


When you call postAndWait(), ObjectPak posts the dialog, enters a secondary event loop, and does not return until the user dismisses the dialog. Unlike postBlocked(), postAndWait() handles all callbacks internally and simply returns an enumerated value of type VkDialogReason indicating which button the user selected. The possible return values are VkDialogManager::OK, VkDialogManager::CANCEL, or VkDialogManager::APPLY. postAndWait() is useful for cases in which it is necessary or convenient not to go on to the next line of code until the user dismisses the dialog. For example:

if ( theFileSectionDialog->postAndWait() == VkDialogManager::OK )
int fd = open( theFileSelectionDialog->fileName(), O_RDONLY);

Note: postAndWait() posts dialogs as full-application modal dialogs to minimize potential problems that can be caused by the secondary event loop, but you should be aware that the second event loop is used and be sure that no non-re-entrant code can be called.


As with the other functions for posting a dialog, postAndWait() is overloaded to allow for almost any combination of arguments without resorting to using NULLs as placeholders. Consult the VkDialogManager reference page for a complete listing of the overloaded versions of postAndWait().

Examples of posting dialogs

The following line posts a simple non-modal, non-blocking information dialog over the application's main window:

theInfoDialog->post("You have new mail in your system mailbox");

Figure 23. shows the appearance of this dialog when posted. Because the call did not provide any callback for the OK button, when the user clicks on the button, ObjectPak simply dismisses the dialog.

Figure 23. Example Information Dialog

You could also specify the message as an X resource. In the above example, you could name the resource something such as newMailMessage and set it in a resource file with the line:

*newMailMessage: You have new mail in your system mailbox

Then you could use the following line to post the information dialog:

theInfoDialog->post("newMailMessage");

Displaying a question dialog

The following line displays a non-modal, non-blocking question dialog over the application's main window:

void MailWindow::newMail()
{
// ...
theQuestionDialog->post("Read new mail?",
&MailWindow::readMailCallback,
(XtPointer) this);
// ...
}

Figure 24. shows the appearance of this dialog when posted. If the user clicks on the OK button, the program dismisses the dialog and executes the MailWindow::readMailCallback() function. Following ObjectPak conventions as described in "Using Xt Callbacks with Components" , the client data argument is set to the value of the this pointer so that MailWindow::readMailCallback() can retrieve the pointer, cast it to the expected component type, and call a corresponding member function.

Figure 24. Example Question Dialog

Because the call to post() did not provide any callback for the Cancel button, when the user clicks on the button, ObjectPak simply dismisses the dialog. If instead you needed to perform some type of cleanup operation when the user clicks on the Cancel button, you would need to provide a callback for the Cancel button:

void MailWindow::newMail()
{
// ...
theQuestionDialog->post("Read new mail?",
&MailWindow::readMailCallback,
&MailWindow::cleanupMailCallback,
(XtPointer) this);
// ...
}

In general, try to encapsulate all dialog callbacks and related information in the subclass of the object with which they are associated. For example, for dialogs that are associated with a specific window, you include all the code related to those dialogs in the subclass definition for that window.

This technique is illustrated in Example 32., which shows a simple example of using the VkWarningDialog class to post a warning dialog.

Example 32. Posting a Dialog

Code

#include <Vk/VkApp.h>
#include <Vk/VkSimpleWindow.h>
#include <Vk/VkWarningDialog.h>
#include <Xm/PushB.h>
class MyWindow: public VkSimpleWindow {
protected:
static void postCallback(Widget, XtPointer, XtPointer);
public:
MyWindow (const char *name);
~MyWindow ( );
virtual const char* className();
};
MyWindow::MyWindow (const char *name) : VkSimpleWindow (name)
{
Widget button = XmCreatePushButton (mainWindowWidget(), "Push Me",
NULL, 0);
XtAddCallback(button, XmNactivateCallback,
&MyWindow::postCallback,
(XtPointer) this);
addView(button);
}
const char* MyWindow::className() { return "MyWindow"; }
MyWindow::~MyWindow()
{
// Empty
}
void MyWindow::postCallback(Widget, XtPointer clientData, XtPointer)
{
theWarningDialog->post("Watch Out!!!", NULL,
(MyWindow *) clientData);
}
void main ( int argc, char **argv )
{
VkApp *app = new VkApp("Dialog", &argc, argv);
MyWindow *win = new MyWindow("Dialog");
win->show();
app->run();
}

Unposting Dialogs

After posting a dialog, you might encounter situations in which you want to unpost it even though the user has not acknowledged and dismissed it. For example, your application might post an information dialog that the user doesn't bother to acknowledge. At some later point, the information presented in the dialog might no longer be valid, in which case the application should unpost the dialog.

Removing the dialog

In situations such as these, you can use the VkDialogManager::unpost() function to remove the dialog:

void unpost()
void unpost(Widget w)

If you provide the widget ID of a specific dialog, unpost() dismisses that dialog. Otherwise, unpost() dismisses the most recent dialog of that class posted.

Dismissing all dialogs

If you want to dismiss all dialogs of a given class, you can call the VkDialogManager::unpostAll() function:

void unpostAll()

For example, the following dismisses all information dialogs currently posted:

theInformationDialog->unpostAll();

Setting the Dialog Title

By default, ViewKit ObjectPak sets the title of a dialog (displayed in the window manager title bar for the dialog) to the name of the application; however, you have the ability to set dialog titles on both a per-class and per-dialog basis.

If you want all dialogs of a certain class to have a title other than the default, you can specify the title with an X resource. For example, you could set the title of all warning dialogs in an application to "Warning" by including the following line in a resource file:

*warningDialog.dialogTitle: Warning

Using setTitle ()

You can use the VkDialogManager::setTitle() function to set the title for the next dialog of that class that you post:

void setTitle(const char *nextTitle = NULL)

setTitle() accepts as an argument a character string. setTitle() first treats the string as a resource name which it looks up relative to the dialog widget. If the resource exists, setTitle() uses the resource value as the dialog title. If setTitle() finds no resource, or if the string contains spaces or newline characters, it uses the string itself as the dialog title.

setTitle() affects only the next dialog posted; subsequent dialogs revert to the default title for that class.

For example, imagine an editor that uses the question dialog to post two dialogs, one that asks "Do you really want to replace the current buffer?" and one that asks "Do you really want to exit?" If you want different titles for each dialog, you could define resources for each:

*replaceTitle: Dangerous Replacement Dialog
*exitTitle: Last Chance Before Exit Dialog

Then to post the question dialog for replacing the buffer, call:

theQuestionDialog->setTitle("replaceTitle");
theQuestionDialog->post("Do you really want to replace the current buffer?",
&EditWindow::replaceBufferCallback,
XtPointer) this);

Figure 25. shows the resulting dialog.

Figure 25. Example of Setting the Dialog Title

Posting the exit question

To post the exit question dialog as a modal dialog, call:

theQuestionDialog->setTitle("exitTitle");
theQuestionDialog->postModal("Do you really want to exit?",
&EditWindow::replaceBufferCallback,
(XtPointer) this);

Figure 26. shows the resulting dialog.

Figure 26. Another Example of Setting the Dialog Title

Setting the Button Labels

The button labels (the text that appears on the buttons) used for a dialog are controlled by the XmNokLabelString, XmNcancelLabelString, and XmNapplyLabelString resources. The default values of these resources are respectively "OK", "Cancel", and "Apply".

You can use the VkDialogManager::setButtonLabels() function to set the button labels for the next dialog that you post:

void setButtonLabels(const char *ok = NULL,
const char *cancel = NULL,
const char *apply = NULL)

setButtonLabels() accepts as arguments up to three character strings: the first string controls the label for the OK button, the second the label for the Cancel button, and the third the label for the Apply button. If you pass NULL as an argument for any of these strings, the corresponding button uses the default label. setTitle() first treats each string as a resource name which it looks up relative to the dialog widget. If the resource exists, setTitle() uses the resource value as the button label. If setTitle() finds no resource, or if the string contains spaces or newline characters, it uses the string itself as the button label.

setButtonLabels() affects only the next dialog posted; subsequent dialogs revert to the default button labels.

Dialog Access and Utility Functions

The VkDialogManager class also provides some access and utility functions to help manipulate dialogs.

The VkDialogManager::centerOnScreen() function controls the algorithm that ObjectPak uses to determine where on the screen to post a dialog:

void centerOnScreen(Boolean flag)

True flag

If flag is TRUE, ObjectPak uses the following algorithm:

  1. If you provide a parent window argument when you call one of the posting functions, and that window is visible and not iconified, ObjectPak posts the dialog over that window.
  2. If you provide a parent window argument but the window is hidden or iconified.
  3. If you do not provide a parent window argument, ObjectPak creates the dialog as a child of the hidden application shell created by the VkApp class and posts the dialog over that shell. Unless you, or the user, explicitly sets the geometry for the application, ObjectPak centers the application shell on the screen, so the dialog appears centered on the screen.

False flag

If flag is FALSE, ObjectPak uses the following algorithm, the default algorithm:

  1. If you provide a parent window argument when you call one of the posting functions, and that window is visible and not iconified, ObjectPak posts the dialog over that window.
  2. If a) you provide a parent window argument but the window is hidden or iconified, or b) you do not provide a parent window argument, ObjectPak attempts to create the dialog as a child of the application's main window and post the dialog over that window. ("Managing Top-Level Windows" describes how the main window is determined.)
  3. If the main window is hidden or iconified, ObjectPak creates the dialog as a child of the hidden application shell created by the VkApp class and posts the dialog over that shell. Unless you or the user explicitly sets the geometry for the application, ObjectPak centers the application shell on the screen, so the dialog appears centered on the screen.

The VkDialogManager::lastPosted() returns the widget ID of the last dialog posted of that class:

Widget lastPosted()