hide random home http://www.sgi.com/tech/tech_c++9.html (Silicon Surf Promotional CD, 01/1995)

Improving Productivity with the ViewKit Framework

The ViewKit library provides many commonly-needed facilities as higher-level services. Without the ViewKit framework, these services would have to be implemented using the lower-level facilities of the Motif widget set, usually with much more difficulty, and a corresponding loss of productivity. Applications built using only a low-level library like the Motif widget set also tend to exhibit a lack of consistency, as well, because common features must be re-implemented for each application. For example, let's examine the steps necessary to add a quit command to a pane in the menu bar in the generic application described earlier. The quit command should first display a dialog that asks the user to confirm the command before actually exiting the application. Using the Motif toolkit, the following code segments would be required:


////////////////////////////////////////////////////////////////
// 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.

___________________________________________________________________