OSF/Motif provides the components for building menus (buttons, menu shells, and so on) but does little to make menu construction easy. ViewKit ObjectPak provides a set of classes that facilitate common operations on menus, including creating menu bars, menu panes, popup menus, option menus, and cascading menu panes. The ObjectPak menu package also provides an object-oriented interface for activating and deactivating menu items, dynamically adding, removing, or replacing menus items or menu panes, and performing other operations.
The basis for all ViewKit ObjectPak menu classes is the abstract class VkMenuItem, which is derived from VkComponent. There are two types of classes derived from VkMenuItem. The first serve as containers and correspond to the menu types supported by OSF/Motif: popup menus, pulldown menu panes, menu bars, and option menus. The second type of derived classes are individual menu items: actions, toggles, labels, and separators.
The classes derived from VkMenuItem correspond closely with OSF/Motif widgets and gadgets. For example, an action implemented as a VkMenuAction object represents a XmPushButton gadget along with an associated callback. However, the ObjectPak menus offer several advantages over directly using OSF/Motif widgets and gadgets. You can manipulate the menu objects more easily than widgets. You can display, activate, and deactivate items with a single function call. You can also easily move or replace items.
Caution: ObjectPak implements menu items as gadgets rather than widgets. This causes a problem in callbacks and other situations if you try to use certain Xt functions (such as XtDisplay(3), XtScreen(3), and XtWindow(3)) that expect widgets as arguments. Therefore, you should use the more general functions (such as XtDisplayofObject(3), XtScreenofObject(3), and XtWindowofObject(3)) when you need to obtain this information for ObjectPak menu items.
VkMenu, derived from VkMenuItem, is the abstract base class that implements the functionality needed to create and manipulate menus. It provides support for creating menus and adding, removing, replacing, finding, activating, and deactivating menu items.
Subclasses of VkMenu
Separate subclasses of VkMenu implement the various types of menus supported by ObjectPak:
Subclasses derived from VkMenuItem
Individual menu items are implemented as subclasses derived from VkMenuItem, as shown in the following table:
This section describes the features of the ObjectPak menu item classes. First it describes the features implemented by VkMenuItem, which are common to all the menu item classes. Then it describes the unique features of each individual menu item class.
Note: The header file <Vk/VkMenuItem.h> contains the declarations for all menu item classes.
Common Features of Menu Items
VkMenuItem provides a standard set of functions for accessing and manipulating menu items. Individual menu items are implemented as subclasses derived from VkMenuItem. Unlike many ObjectPak classes, you should never need to directly instantiate a menu item class. ObjectPak automatically instantiates menu item objects when you create menus (refer to "Constructing Menus" for more detailed information). This guide does not describe the menu item constructors and destructors.
ViewKit implements menu items as gadgets rather than widgets. If you want to directly access menu item gadgets, use Xt functions that accept gadgets, as well as widgets, as arguments.
Displaying and hiding menu items
The VkMenuItem::show() function makes a menu item visible when you display the menu to which it belongs:
By default, all menu items are visible when created (that is, they appear when you display the menu to which they belong). An explicit call to a menu item's show() function is not necessary to display it. You can call show() to display a menu item after you have hidden it with hide().
The VkMenuItem::hide() function makes a menu item invisible when you display the menu to which it belongs:
hide() does not remove the menu item from the menu, but unmanages the widget or gadget associated with a menu item. You can display a hidden menu item by calling its show() function.
To remove a menu item from a menu, call VkMenuItem::remove():
remove() does not destroy a menu item, but removes the item from the menu hierarchy.
Note: Instead of retaining pointers to all your menu items and using VkMenuItem::remove() to remove menu items, use VkMenu::removeItem(). The effect is the same regardless of the function you use. Typically, using the VkMenu function is easier. Refer to "Manipulating Items in Menu" on page 146 for a more detailed description of VkMenu::removeItem().
Activating and deactivating menu items
The VkMenuItem::activate() function makes a menu item sensitive so that it accepts user input (that is, a user can select the item):
By default, all menu items are activated (sensitive) when they are created.
The VkMenuItem::deactivate() function makes a menu item insensitive so that it does not accept user input (that is, a user cannot select the item):
When insensitive, the menu item appears "grayed out" when you display the menu to which it belongs. You can re-activate a menu item by calling its activate() function.
Note: Instead of retaining pointers to all of your menu items and using VkMenuItem::activate() and VkMenuItem::deactivate() to activate and deactivate menu items, you can instead use VkMenu::activateItem() and VkMenu::deactivateItem() respectively. The effect is the same no matter which functions you use, though typically you will find it easier to use the VkMenu functions. "Activating and deactivating items in a menu" on page 147 describes VkMenuItem::activate() and VkMenuItem::deactivate().
Setting menu item labels
Generally, you should set the label for a menu item by setting a value in the resource database for that item's XmNlabelString resource. For example, if you have a menu item named "addPage", you could set the label for that item by including a resource specification such as:
*addPage.labelString: Add Page
If you do not set the menu item's XmNlabelString resource, ObjectPak uses the item's name.
In some cases, you might need to set the label of an item programmatically. For example, in a page layout system you might want to change the labels for the items in an Edit menu to reflect the type of object the user has currently selected. You can change a menu item's label programmatically with the setLabel() function:
virtual void setLabel(const char * str)
The string is treated first as a resource name that setLabel() looks up relative to the menu item's widget. If the resource exists, its value is used as the item's label. If the resource does not exist, or if the string contains spaces or newline characters, setLabel() uses the string itself as the item's label. This allows applications to dynamically set and change menu item labels without hard-coding the exact label strings in the application code.
Setting the position of menu items
By default, ObjectPak inserts items into a menu in the order you specify them. Therefore, the easiest way to set the positions of menu items is to add them to the menu in the order that you want them to appear.
Occasionally you might need to explicitly set the position of a menu item. To do so, use VkMenuItem::setPosition():
void setPosition(int position)
setPosition() sets the item's position in the menu. You can specify any integer value from zero to the number of items in the menu; a value of zero specifies the first position in the menu. setPosition() ignores invalid values.
Note: setPosition() is effective only before ObjectPak realizes the menu to which the menu item belongs. If you call setPosition() after realizing a menu, it has no effect. For example, if you create a menu bar in a window's constructor, you can use setPosition() to position menu items; however, after calling the window's show() function, setPosition() has no effect.
Menu items utility functions
You can use MenuItem::menuType() to determine the specific menu item type when given a pointer to a VkMenuItem object:
virtual VkMenuItemType menuType()
menuType() returns one of the following enumerated values of type VkMenuItem::VkMenuItemType:
A VkMenuAction object
A VkMenuConfirmFirstAction object
A VkMenuToggle object
A VkMenuLabel object
A VkMenuSeparator object
A VkSubMenu object
A VkRadioSubMenu object
A VkMenuBar object
A VkOptionMenu object
A VkPopupMenu object
A user-defined subclass of
You can also determine when an object pointed to by a VkMenuItem pointer is a menu by calling MenuItem::isContainer():
virtual Boolean isContainer()
isContainer() returns TRUE if the VkMenuItem object is an item that can "contain" other menu items (in other words, a menu).
VkMenuAction class provides a selectable menu item that performs an action. A VkMenuAction object is implemented as a PushButtonGadget.
A VkMenuAction object is associated with a callback function that performs an operation and, optionally, a callback function that "undoes" the operation. You specify these callback functions when you add the item to a menu using one of the methods described in "Constructing Menus" . Consult the section for information on using VkMenuAction objects in a menu. VkMenuAction provides public functions in addition to those implemented by VkMenuItem.
You can determine whether an action has an undo callback associated with it by calling VkMenuAction::hasUndo():
hasUndo() returns TRUE if the object has an associated undo callback function.
Calling an undo callback function
If an object has an undo callback function, you can call it programmatically using VkMenuAction::undo():
virtual void undo()
Typically, you will not need to call undo() explicitly. ObjectPak provides automatic undo handling for your application using the VkUndoManager class, as described in Chapter 6--Undo Management and Command Classes. All you have to do is provide undo callback functions for your VkMenuAction objects and create an instance of VkUndoManager as described Chapter 6--Undo Management and Command Classes.
Confirmable Menu Actions
The VkMenuConfirmFirstAction class, derived from VkMenuAction, provides a selectable menu item that performs an action. When the user selects this type of menu item, the application posts a question dialog asking the user for confirmation. The application performs the action only if the user confirms it.
The VkMenuConfirmFirstAction class is intended for irrecoverable actions (for example, deleting a file), VkMenuConfirmFirstAction objects do not support undo callback functions.
The VkMenuConfirmFirstAction class uses a PushButtonGadget to implement the menu choice and the VkQuestionDialog(3) to implement the question dialog. (See "Question Dialog" for more information on the VkQuestionDialog class.)
The question displayed in the confirmation dialog is determined by the value of the "noUndoQuestion" resource, which ObjectPak looks up relative to the menu item's widget. For example, if you have a menu item named "quit", you can set the question text for that item by including a resource specification such as:
*quit.noUndoQuestion: Do you really want to quit?
If you do not provide a value for this resource, ObjectPak uses the default question: "This action cannot be undone. Do you want to proceed anyway?"
The VkMenuToggle class, which is derived from VkMenuAction, provides a two-state toggle as a menu item. To enforce radio behavior on a group of toggles, you must add them to a VkRadioSubMenu object; otherwise, VkMenuToggle object exhibit simple checkbox-style behavior. A VkMenuToggle object is implemented as a ToggleButtonGadget.
In addition to the public functions provided by VkMenuItem, VkMenuToggle provides functions for setting and retrieving the toggle state.
Setting the visual state of a toggle
You can set the visual state of a VkMenuToggle object, without activating its associated callback, using VkMenuToggle::setVisualState():
void setVisualState(Boolean state)
setVisualState() selects the toggle if state is TRUE and deselects the toggle if state is FALSE.
You can set the visual state of a VkMenuToggle object and activate its associated callback with VkMenuToggle::setStateAndNotify():
void setStateAndNotify(Boolean state)
Retrieving the current value of a toggle
Call VkMenuToggle::getState() to retrieve the current value of a VkMenuToggle object:
getState() returns TRUE if the toggle is currently selected and FALSE if it is currently deselected.
The VkMenuLabel class provides a non-selectable label as a menu item. A VkMenuLabel object is implemented as a LabelGadget.
The VkMenuLabel class does not provide any public functions other than those implemented by VkMenuItem.
The VkMenuSeparator class provides a non-selectable separator as a menu item. A VkMenuSeparator object is implemented as a SeparatorGadget.
The VkMenuSeparator class does not provide any public functions other than those implemented by VkMenuItem.