//////////////////////////////////////////////////////////////// // Code required to add an Application pane containing // a quit action to an existing menubar in an existing // window, using the Motif toolkit. ///////////////////////////////////////////////////////////////// // Add an application pane to the menu pane = XmCreatePulldownMenu(menubar, "application", NULL, 0); // Add a cascade button to the menu pane and attach the pulldown menu pane cascade = XtVaCreateManagedWidget("application", xmCascadeButtonWidgetClass, menubar, XmNsubMenuId, pane, NULL ); // Add a quit item to the pane quitB = XmCreatePushButton(pane, "quit", NULL, 0); XtManageWidget(quitB); // Add a callback to be invoked when the user issues the quit command XtAddCallback(quitB, XmNactivateCallback, safeQuitCallback, NULL); The menu pane and quit entry have now been created, but we still need to implement the safeQuitCallback() function and related facilities. A "safe quit" mechanism could be implemented as follows: ////////////////////////////////////////////////// // Popup a dialog to ask the user to confirm // a quit command before actually executing it. ////////////////////////////////////////////////// void safeQuitCallback(Widget w, XtPointer, XtPointer) { // Create a dialog Widget dialog = XmCreateQuestionDialog(w, "question", NULL, 0); // Create the message to be displayed XmString xmstr = XmStringCreateLocalized("Do you really want to quit?"); // Set the dialog to display the message XtVaSetValues(dialog, XmNmessageString, xmstr, XmNdialogStyle, XmDIALOG_APPLICATION_MODAL, NULL); // Free the compound string when it is no longer needed XmStringFree(xmstr); // Assign callbacks to be called when the user clicks on OK or Cancel XtAddCallback(dialog, XmNokCallback, reallyQuit, NULL); XtAddCallback(dialog, XmNcancelCallback, cancelCallback, NULL); // Handle the window manager close button Atom WM_DELETE_WINDOW = XInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", FALSE); XmAddWMProtocol(XtParent(dialog), WM_DELETE_WINDOW, cancelCallback, NULL); XtVaSetValues(XtParent(dialog), XmNdeleteResponce, XmDO_NOTHING, NULL); // Display the dialog XtManageChild(dialog); } // This function is called if the user confirms the action void reallyQuit(Widget, XtPointer, XtPointer) { exit(0); } // If the user cancels the action, simply destroy the dialog widget void cancelCallback(Widget w, XtPointer, XtPointer) { XtDestroyWidget(w); }
Programmers familiar with the Motif toolkit will recognize these code segments as typical of the level of detail they contend with every day. These code segments implement a single, trivial feature. Most applications support dozens, if not hundreds of such commands, and programmers who work with the Motif widget set or similar toolkits implement this type of feature over and over. The situation is actually worse than it appears, because the code segments shown here cut several corners that would not be acceptable for product-quality applications. For example, this code segment hard-codes the message "Do you really want to quit?" in English, preventing the application from being localized to some other language. The dialog positioning is not handled well, and there is also no provision for providing the same behavior for the quit command that the user can issue from the window manager menu. There is also no supported mechanism to allow other parts of the application to clean up before the program exists. The code simply exits.
The ViewKit framework improves programmers' productivity dramatically by providing support for such common operations. For example, the following complete program adds the same functionality described above to the ViewKit generic application, but this time taking advantage of just a few of the ViewKit facilities.
////////////////////////////////////////////////////////////// // Generic ViewKit application with a "safe quit" menu item ///////////////////////////////////////////////////////////// #include#include #include // Provide the function to be executed to really quit void quitCallback(Widget, XtPointer, XtPointer) { theApplication->terminate(0); // Clean shut down function } void main ( int argc, char **argv ) { VkApp *app = new VkApp("Generic", &argc, argv); VkWindow *win = new VkWindow("generic"); // Add a menu pane to the window's menu VkSubMenu *pane = win->addMenuPane("Application"); // Add an item to the pane. Action requires user confirmation first pane->addConfirmFirstAction("Quit", quitCallback, NULL); win->show(); // Display the window app->run(); // Run the application }
This is the complete application. The ViewKit implementation not only provides all the capabilities of the substantially lengthier Motif code shown earlier, it does so in a comprehensive, robust, and extensible way. For example, the message displayed in the confirmation dialog can be customized easily. The application can also be easily localized. And of course, like the earlier example, this program supports context-sensitive on-line help and other features automatically.
___________________________________________________________________