ViewKit Menu Base Class

This section describes the abstract VkMenu class, which provides the basic features of the ViewKit ObjectPak menu classes. It describes how to construct menus, manipulate items contained in the menus, and use the menu access functions. Because all ViewKit ObjectPak menu classes are derived from VkMenu, the functions and techniques described in this section apply to all menu classes.

Constructing Menus

The methods of constructing menus are the same for all types of menus (menu bars, options menus, etc.). The examples in this section use the VkMenuBar class, but the principles are similar for any of the ObjectPak menu classes.

You can build menus either by passing a static menu description to the class constructor for a menu, or by adding items dynamically through function calls. You can mix the two approaches, initially defining a static menu structure and then dynamically adding items as needed.

Constructing menus from a static description

To construct a menu from a static description, create a VkMenuDesc array that describes the contents of the menu and then pass that array as an argument to an appropriate menu constructor. This section describes the format of the VkMenuDesc structure and provides examples of its use.

VkMenuDesc structure

The definition for the VkMenuDesc structure is:

struct VkMenuDesc {
VkMenuItemType menuType;
char *name;
XtCallbackProc callback;
VkMenuDesc *submenu;
XtPointer clientData;
XtCallbackProc undoCallback;
};

VkMenuDesc fields

The following table describes the VkMenuDesc fields:

 

 

VkMenuDesc Field

Description

menuType

The type of menu item. The value of this field must be one of the enumerated constants listed in the following table.

name

The menu item's name, which is also used as the menu item's default label.

callback

An Xt-style callback procedure that is executed when this menu item is activated.

submenu

A pointer to an array of a VkMenuDesc structures that describes the contents of a submenu.

clientData

Data that is passed to the callback procedure when it is executed.

undoCallback

A callback procedure that can be executed to undo the effects of the actions of the activation callback. Implementation of support for undoing actions is described in "Undo Management" .

 

 

Menu type parameter values

The menu type parameter is an enumerated value of type VkMenuItemType. The following table describes the VkMenuType parameter values:

 

 

VkMenuItemType Value

Description

ACTION

A selectable menu item, implemented as a VkMenuAction object.

CONFIRMFIRSTACTION

A selectable menu item, implemented as a VkMenuConfirmFirstAction object, which performs an action that the user must confirm before it is executed.

TOGGLE

A two-state toggle button gadget, implemented as a VkMenuToggle object.

LABEL

Label implemented as a VkMenuLabel object.

SEPARATOR

A separator, implemented as a VkMenuSeparator object.

SUBMENU

A cascading submenu, implemented as a VkSubMenu object.

RADIOSUBMENU

A cascading submenu that acts as a radio-style pane, implemented as a VkRadioSubMenu object.

END

All menu descriptions must be terminated by this constant.

 

 

Menu item type fields

Not all fields are used for each menu item type. The following table summarizes the optional and required fields for each menu item type.

 

 

menuType

name

callback

submenu

clientData1

undoCallback

ACTION

R

O2

I

O

O

CONFIRMFIRSTACTION

R

Ob

I

O

I

TOGGLE

R

Ob

I

O

I

LABEL

R

I

I

I

I

SEPARATOR

I

I

I

I

I

SUBMENU

R

I

R

O3

I

RADIOSUBMENU

R

I

R

Oc

I

END

R

I

I

I

I

R = Required parameter

O = Optional parameter

I = Ignored parameter

1

The value you provide as default client data argument to the menu constructor is used for all menu items (unless you explicitly provide a client data parameter).

2

While this menu item is optional, the menu item is useless unless you provide a callback function.

3

The value you provide as a client data parameter is the default value for all menu items in the submenu.

 

Array definition example

For example, consider the following array definition:

class EditWindow: public VkWindow {
private:
static VkMenuDesc editMenu[];
// ...
};
VkMenuDesc EditWindow::editMenu[] = {
{ ACTION, "Cut", &EditWindow::cutCallback,
NULL, NULL, &EditWindow::undoCutCallback },
{ ACTION, "Copy", &EditWindow::copyCallback,
NULL, NULL, &EditWindow::undoCopyCallback },
{ ACTION, "Paste", &EditWindow::pasteCallback,
NULL, NULL, &EditWindow::undoPasteCallback },
{ ACTION, "Search" &EditWindow::searchCallback }
{ SEPARATOR },
{ CONFIRMFIRSTACTION, "Revert", &EditWindow::revertCallback },
{ END }
};

The editMenu array describes a simple menu for editing in an application. The menu consists of five actions and a separator. The menu's "Cut" item calls the cutCallback() function when it is activated with no client data passed to it. "Cut" also supports an undo action through the undoCutCallback() function. The "Copy" and "Paste" items work similarly.

Search action

The "Search" action does not support an undo action. Presumably, the action performed by this item is either too complex to undo or is meaningless to undo.

Revert item

The "Revert" item is implemented as a CONFIRMFIRSTACTION. When the user activates this item, the application posts a confirmation dialog to warn the user that the action cannot be undone.

Example

As a more complex example, consider a menu that contains two submenus, each of which contains two selectable items. You could describe this menu with definitions such as:

class TextWindow: public VkWindow {
private:
static VkMenuDesc menu[];
static VkMenuDesc applicationPane[];
static VkMenuDesc editPane[];
// ...
};
VkMenuDesc TextWindow::applicationPane[] = {
{ ACTION, "Open", &TextWindow::openCallback },
{ ACTION, "Save", &TextWindow::saveCallback },
{ END }
};
VkMenuDesc TextWindow::editPane[] = {
{ ACTION, "Cut", &TextWindow::cutCallback },
{ ACTION, "Paste", &TextWindow::pasteCallback },
{ END }
};
VkMenuDesc TextWindow::menu[] = {
{ SUBMENU, "Application", NULL, applicationPane },
{ SUBMENU, "Edit", NULL, editPane },
{ END }
};

After constructing a static menu description, you create it by passing it as an argument to a menu constructor. For example, to implement the menus defined above as a menu bar, you could execute:

VkMenuBar *menubar = new VkMenuBar(menu);

You can implement the same menu as a popup menu simply by passing the definition to a popup menu constructor:

VkPopupMenu *popup = new VkPopupMenu(menu);

Considerations
for Xt Callback client data

When using Xt-style callbacks in ObjectPak (as described in "Using Xt Callbacks with Components" ), pass the this pointer as client data to all Xt callback functions. Callback functions retrieve this pointer, cast it to the expected component type, and call a corresponding member function.

However, you cannot use the this pointer when defining a static data member. As a workaround, menu constructors accept a defaultClientData argument. If you provide a value for this argument, any menu item that does not provide a client data argument uses this argument instead. This allows you to specify menus statically, while allowing you to use an instance pointer with Xt callbacks. Example 23. illustrates this technique.

Example 23. Providing Default Client Data Static Menu Descriptions

Code

class SampleWindow: public VkWindow {
private:
static void oneCallback(Widget, XtPointer, XtPointer);
static void twoCallback(Widget, XtPointer, XtPointer);
static void cutCallback(Widget, XtPointer, XtPointer);
static void pasteCallback(Widget, XtPointer, XtPointer);
static VkMenuDesc applicationPane[];
static VkMenuDesc editPane[];
static VkMenuDesc menu[];
public:
SampleWindow(const char *name);
// Other members
};
SampleWindow::SampleWindow(char *name) : VkWindow(name)
{
setMenuBar(new VkMenuBar(menu, (XtPointer) this));
// Other actions
}

Note: VkWindow::addMenuPane(), VkWindow::addRadioMenuPane(), and the form of the VkWindow::setMenuBar() function that accepts a VkMenuDesc array as an argument all automatically use the this pointer as default client data for the menu bars and menu panes that they create.


Creating a Menubar Using a Static Description

Example 24. Illustrates using a static description of a menu tree to create a menu bar. The program creates its main window using MyWindow, a subclass of VkWindow. The menu description and all menu callbacks are contained within the MyWindow subclass definition.

Example 24. Creating a Menu Bar Using a Static Description

Code

#include <Vk/VkApp.h>
#include <Vk/VkWindow.h>
#include <Vk/VkMenu.h>
#include <iostream.h>
#include <Xm/Label.h>
class MyWindow: public VkWindow {
private:
static void sampleCallback( Widget, XtPointer , XtPointer);
static void quitCallback( Widget, XtPointer , XtPointer);
void quit();
void sample();
static VkMenuDesc subMenu[];
static VkMenuDesc sampleMenuPane[];
static VkMenuDesc appMenuPane[];
static VkMenuDesc mainMenuPane[];
public:
MyWindow( const char *name);
~MyWindow();
virtual const char* className();
};
MyWindow::MyWindow( const char *name) : VkWindow( name)
{
Widget label = XmCreateLabel(mainWindowWidget(), "a menu",
NULL, 0);
setMenuBar(mainMenuPane);
addView(label);
}
MyWindow::~MyWindow()
{
// Empty
}
const char* MyWindow::className()
{
return "MyWindow";
}
// The menu bar is essentially a set of cascading menu panes, so the
// top level of the menu tree is always defined as a list of submenus
VkMenuDesc MyWindow::mainMenuPane[] = {
{ SUBMENU, "Application", NULL, MyWindow::appMenuPane },
{ SUBMENU, "Sample", NULL, MyWindow::sampleMenuPane },
{ END }
};
VkMenuDesc MyWindow::appMenuPane[] = {
{ ACTION, "One", &MyWindow::sampleCallback },
{ ACTION, "Two", &MyWindow::sampleCallback },
{ ACTION, "Three", &MyWindow::sampleCallback },
{ SEPARATOR },
{ ACTION, "Quit", &MyWindow::quitCallback },
{ END },
};
VkMenuDesc MyWindow::sampleMenuPane[] = {
{ LABEL, "Test Label" },
{ SEPARATOR },
{ ACTION, "An Action", &MyWindow::sampleCallback },
{ ACTION, "Another Action", &MyWindow::sampleCallback },
{ SUBMENU, "A Submenu", NULL, MyWindow::subMenu },
{ END },
};
VkMenuDesc MyWindow::subMenu[] = {
{ ACTION, "foo", &MyWindow::sampleCallback },
{ ACTION, "bar", &MyWindow::sampleCallback },
{ ACTION, "baz", &MyWindow::sampleCallback },
{ END },
};
void MyWindow::sample()
{
cout << "sample callback" << "\n" << flush;
}
void MyWindow::sampleCallback(Widget, XtPointer clientData, XtPointer)
{
MyWindow *obj = (MyWindow *) clientData;
obj->sample();
}
void MyWindow::quitCallback ( Widget, XtPointer, XtPointer )
{
theApplication->quitYourself();
}
void main(int argc, char **argv)
{
VkApp *myApp = new VkApp("Menudemo", &argc, argv);
MyWindow *menuWin = new MyWindow("MenuWindow");
menuWin->show();
myApp->run();
}

When you run this program, you see the window shown in Figure 17..

Figure 17. Main Window with Menu Bar Created by Static Description

The first pane, shown in Figure 18., contains three selectable entries (actions), followed by a separator, followed by a fourth action. The first three menu items invoke a stub function when selected. The fourth item calls quitCallback(), which exits the application.

Figure 18. A Menu Pane Created by a Static Description

The second menu pane, shown in Figure 19., demonstrates a non-selectable label, a separator, and a cascading submenu.

Figure 19. A Menu Pane Containing a Label and a Submenu

In addition to these application-defined menu panes, ObjectPak can automatically add a Help menu to a menu bar, which provides a user interface to a help system. "ViewKit Help Menu" describes the Help menu. Appendix C-- Using a Help System describes how to interface an external help system to a ViewKit ObjectPak application.

Constructing menus dynamically

In addition to the static description approach demonstrated in the previous section, ObjectPak allows applications to construct menus and menu items dynamically using functions defined in VkMenu. This section describes the menu-creation functions and provides examples of their use.

Functions for dynamically creating menus

The VkMenu class provides a number of member functions for creating menus. Each function adds a single menu item to a given menu. You can use these functions at any time in your program. Even if you created a menu using a static definition, you can use these functions to add items to the menu.

VkMenu::addAction() adds to a menu a selectable menu action, implemented as a VkMenuAction object:

VkMenuAction *addAction(const char *name,
XtCallbackProc actionCallback = NULL,
XtPointer clientData = NULL,
int position = -1)
VkMenuAction *addAction(const char *name,
XtCallbackProc actionCallback,
XtCallbackProc undoCallback,
XtPointer clientData,
int position = -1)

addAction() creates a VkMenuAction object named name and adds it to the menu. By default, addAction() adds the item to the end of the menu; if you specify a value for position, addAction() adds the item at that position. actionCallback is the callback function that performs the item's action and undoCallback is the callback function that undoes the action. If you do not provide an undo callback, the action cannot be undone and does not participate in the ViewKit undo mechanism as described in Chapter 6--Undo Management and Command Classes. Client data is client data passed to the callback functions. Following ObjectPak conventions as described in "Using Xt Callbacks with Components" , you should 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.

VkMenu::addConfirmFirstAction() adds to a menu a selectable menu action, implemented as a VkMenuConfirmFirstAction object:

VkMenuConfirmFirstAction *
addConfirmFirstAction(const char *name,
XtCallbackProc actionCallback = NULL,
XtPointer clientData = NULL,
int position = -1)

addConfirmFirstAction() creates a VkMenuConfirmFirstAction object named name and adds it to the menu. By default, addConfirmFirstAction() adds the item to the end of the menu; if you specify a value for position, addConfirmFirstAction() adds the item at that position. actionCallback is the callback function that performs the item's action and clientData is client data passed to the callback function. As described above, you should pass the this pointer as client data.

VkMenu::addToggle() adds to a menu a selectable menu toggle, implemented as a VkMenuToggle object:

VkMenuToggle *addToggle(const char *name,
XtCallbackProc actionCallback = NULL,
XtPointer clientData = NULL,
int state = -1)
int position = -1)

addToggle() creates a VkMenuToggle object named name and adds it to the menu. By default, addToggle() adds the item to the end of the menu; if you specify a value for position, addToggle() adds the item at that position. If you provide a state argument, addToggle() sets the initial state of the toggle to that value. actionCallback is the callback function that performs the item's action and clientData is client data passed to the callback function. As described above, you should pass the this pointer as client data.

VkMenu::addLabel() adds to a menu a non-selectable menu label, implemented as a VkMenuLabel object:

VkMenuLabel *addLabel(const char *name,
int position = -1)

addLabel() creates a VkMenuLabel object named name and adds it to the menu. By default, addLabel() adds the item to the end of the menu; if you specify a value for position, addLabel() adds the item at that position.

VkMenu::addSeparator() adds to a menu a non-selectable menu separator, implemented as a VkMenuSeparator object:

VkMenuSeparator *addSeparator(const char *name,
int position = -1)

addSeparator() creates a VkMenuSeparator object named name and adds it to the menu. By default, addSeparator() adds the item to the end of the menu; if you specify a value for position, addSeparator() adds the item at that position.

VkMenu::addSubmenu() adds to a menu a submenu, implemented as a VkSubMenu object:

VkSubMenu *addSubmenu(VkSubMenu *submenu,
int position = -1)
VkSubMenu *addSubmenu(const char *name,
int position = -1)
VkSubMenu *addSubmenu(const char *name,
VkMenuDesc *menuDesc)
XtPointer *defaultClientData = NULL)
int position = -1)

addSubmenu() is overloaded so that you can: 1) add an existing VkSubMenu object; 2) create and add a VkSubMenu object containing no items; or 3) create and add a VkSubMenu object from the static menu description, menuDesc. If you create and add the submenu using the static menu description, you can also provide a defaultClientData value that is used as the default client data for all items contained by the submenu. By default, addSubmenu() adds the item to the end of the menu; if you specify a value for position, addSubmenu() adds the item at that position.


Note: The "m" in addSubmenu() is lower case, whereas the "M" in VkSubMenu is in upper case.


VkMenu::addRadioSubmenu() adds to a menu a submenu that enforces radio-style behavior on the toggle items it contains:

VkRadioSubMenu *addRadioSubmenu(VkRadioSubMenu *submenu,
int position = -1)
VkRadioSubMenu *addRadioSubmenu(const char *name,
int position = -1)
VkRadioSubMenu *addRadioSubmenu(const char *name,
VkMenuDesc *menuDesc)
XtPointer *defaultClientData = NULL)
int position = -1)

addRadioSubmenu() is overloaded so that you can: 1) add an existing VkRadioSubMenu object; 2) create and add a VkRadioSubMenu object containing no items; or 3) create and add a VkRadioSubMenu object from the static menu description, menuDesc. If you create and add the submenu using the static menu description, you can also provide a defaultClientData value that is used as the default client data for all items contained by the submenu. By default, addSubmenu() adds the item to the end of the menu; if you specify a value for position, addSubmenu() adds the item at that position.


Note: The "m" in addRadioSubmenu() is lower case, whereas the "M" in VkRadioSubMenu is in upper case.


VkMenu::add() adds an existing menu item to a menu:

void add(VkMenuItem *item, int position = -1)

By default, add() adds the item to the end of the menu; if you specify a value for position, add() adds the item at that position. Though you can use add() to add any type of menu item to a menu, you typically need it to add only the ViewKit ObjectPak 5undo manager and VkMenuActionObject objects. "Undo Management" describes the ViewKit ObjectPak undo manager and "Command Classes" describes the VkMenuActionObject class.

Example 25., functionally equivalent to Example 24., constructs a menu by adding items one at a time to the window's menu bar and to individual menu panes.

Example 25. Creating a Menu Bar Dynamically

Code

#include <Vk/VkApp.h>
#include <Vk/VkWindow.h>
#include <Vk/VkSubMenu.h>
#include <Vk/VkMenu.h>
#include <Xm/Label.h>
#include <iostream.h>
class MyWindow: public VkWindow {
private:
static void sampleCallback( Widget, XtPointer, XtPointer);
static void quitCallback( Widget, XtPointer, XtPointer);
protected:
void sample();
public:
MyWindow( const char *name);
~MyWindow();
virtual const char* className();
};
MyWindow::MyWindow( const char *name) : VkWindow( name)
{
Widget label = XmCreateLabel(mainWindowWidget(), "a menu", NULL, 0);
// Add a menu pane
VkSubMenu *appMenuPane = addMenuPane("Application");
appMenuPane->addAction("One", &MyWindow::sampleCallback,
(XtPointer) this);
appMenuPane->addAction("Two", &MyWindow::sampleCallback,
(XtPointer) this);
appMenuPane->addAction("Three", &MyWindow::sampleCallback,
(XtPointer) this);
appMenuPane->addSeparator();
appMenuPane->addAction("Quit", &MyWindow::quitCallback,
(XtPointer) this);
// Add a menu second pane
VkSubMenu *sampleMenuPane = addMenuPane("Sample");
sampleMenuPane->addLabel("Test Label");
sampleMenuPane->addSeparator();
sampleMenuPane->addAction("An Action",
&MyWindow::sampleCallback,
(XtPointer) this);
sampleMenuPane->addAction("Another Action",
&MyWindow::sampleCallback,
(XtPointer) this);
// Create a cascading submenu
VkSubMenu *subMenu = sampleMenuPane->addSubmenu("A Submenu");
subMenu->addAction("foo", &MyWindow::sampleCallback,
(XtPointer) this);
subMenu->addAction("bar", &MyWindow::sampleCallback,
(XtPointer) this);
subMenu->addAction("baz", &MyWindow::sampleCallback,
(XtPointer) this);
addView(label);
}
MyWindow::~MyWindow()
{
// Empty
}
const char* MyWindow::className() { return "MyWindow";}
void MyWindow::sampleCallback(Widget, XtPointer clientData, XtPointer)
{
MyWindow *obj = (MyWindow *) clientData;
obj->sample();
}
void MyWindow::sample()
{
cout << "sample callback" << "\n" << flush;
}
void MyWindow::quitCallback ( Widget, XtPointer, XtPointer )
{
theApplication->quitYourself();
}
void main(int argc, char **argv)
{
VkApp *myApp = new VkApp("Menu", &argc, argv);
MyWindow *w1 = new MyWindow("menuWindow");
w1->show();
myApp->run();
}

Manipulating Items in Menu

One of the advantages of the ViewKit ObjectPak menu system is the ability to manipulate the items in a menu after the menu has been created. The ObjectPak menu system allows menu items to be manipulated by sending messages to any menu item. Menu items can also be found and manipulated by name.

Finding items in a menu

The VkMenu::findNamedItem() function allows you to find an item in a menu given its component name:

VkMenuItem *findNamedItem(const char *name,
Boolean caseless = FALSE)

findNamedItem() finds and returns a pointer to a menu item of the specified name belonging to the menu object or any submenus of the menu object. You can also pass an optional Boolean argument specifying whether or not the search is case-sensitive. If findNamedItem() finds no menu item with the given name, it returns NULL. If multiple instances of the same name exist, findNamedItem() returns the first name found in a depth-first search.


Note: Remember that you need to cast the return value if you need to access a member function provided by a VkMenuItem subclass. For example, if you search for a toggle item, remember to cast the return value to VkMenuToggle before calling a member function such as VkMenuToggle::setVisualState().


Activating and deactivating items in a menu

The VkMenu::activateItem() function makes a menu item sensitive so that it accepts user input (that is, a user can select the item):

VkMenuItem *activateItem(const char *name)

You provide as an argument to activateItem() the name of the menu item to activate. This is the same name that you gave the menu item when you created it. activateItem() returns a VkMenuItem pointer to the item activated (or NULL if you did not provide a valid menu item name). By default, all menu items are activated (sensitive) when they are created.

The VkMenu::deactivateItem() function makes a menu item insensitive so that it does not accept user input (that is, a user cannot select the item):

VkMenuItem *deactivateItem(const char *name)

You provide as an argument to deactivateItem() the name of the menu item to deactivate. This is the same name that you gave the menu item when you created it. deactivateItem() returns a VkMenuItem pointer to the item deactivated (or NULL if you did not provide a valid menu item name).When insensitive, the menu item appears "grayed out" when you display the menu. To reactivate a menu item, call deactivateItem() on that item.

Note that instead of using VkMenu::activateItem() and VkMenu::deactivateItem() to activate and deactivate menu items, you could retain pointers to all of your menu items and use VkMenuItem::activate() and VkMenuItem::deactivate() 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 menu items" describes VkMenuItem::activate() and VkMenuItem::deactivate().

Removing items from a menu

If you want to remove a menu item from a menu, you can call VkMenu::removeItem():

VkMenuItem *removeItem(const char *name)

You provide as an argument to removeItem() the name of the menu item to remove from the menu. This is the same name that you gave the menu item when you created it. removeItem() returns a VkMenuItem pointer to the item removed. removeItem() does not destroy a menu item, it simply removes the item from the menu hierarchy.


Note: Iinstead of using VkMenu::removeItem(), you could retain pointers to all of your menu items and use VkMenuItem::remove(). The effect is the same no matter which functions you use, though typically you will find it easier to use the VkMenu functions. "Common Features of Menu Items" on page 125 describes VkMenuItem::remove().


Replacing Items in a Menu

You can replace an item in a menu with another menu item using VkMenu::replace():

VkMenuItem *replace(const char *name, VkMenuItem *newItem)

replace() first uses VkMenu::findNamedItem to find the item specified by name. Then it removes that item from the menu and adds the menu item specified by newItem in its place. replace() returns a pointer to the menu item that you replaced.

Example of Manipulating Menu Items

The program in Example 26. allows users to dynamically add and remove items from a menu, and also to activate and deactivate items.

Example 26. Manipulating Menu Items

Code

#include <Vk/VkApp.h>
#include <Vk/VkWindow.h>
#include <Vk/VkMenu.h>
#include <Vk/VkSubMenu.h>
#include <Xm/Label.h>
#include <stream.h>
#include <stdlib.h>
class MyWindow: public VkWindow {
private:
static void addOneCallback (Widget, XtPointer, XtPointer);
static void removeOneCallback (Widget, XtPointer, XtPointer);
static void activateOneCallback (Widget, XtPointer, XtPointer);
static void deactivateOneCallback(Widget, XtPointer, XtPointer);
static void sampleCallback (Widget, XtPointer, XtPointer);
static void quitCallback (Widget, XtPointer, XtPointer);
protected:
VkSubMenu *_appMenuPane;
VkSubMenu *_menuPaneTwo;
void addOne();
void removeOne();
void activateOne();
void deactivateOne();
void sample();
public:
MyWindow( const char *name);
~MyWindow();
virtual const char* className();
};
MyWindow::~MyWindow()
{
// Empty
}
const char* MyWindow::className() { return "MyWindow";}
void MyWindow::sampleCallback(Widget, XtPointer clientData, XtPointer)
{
MyWindow *obj = ( MyWindow * ) clientData;
obj->sample();
}
void MyWindow::sample()
{
cout << "sample callback" << "\n" << flush;
}
void MyWindow::addOneCallback(Widget, XtPointer clientData, XtPointer)
{
MyWindow *obj = ( MyWindow * ) clientData;
obj->addOne();
}
void MyWindow::addOne()
{
_menuPaneTwo->addAction("A New Action", &MyWindow::sampleCallback,
(XtPointer) this);
}
void MyWindow::removeOneCallback(Widget, XtPointer clientData,
XtPointer)
{
MyWindow *obj = (MyWindow *) clientData;
obj->removeOne();
}
void MyWindow::removeOne()
{
_menuPaneTwo->removeItem("A New Action");
}
void MyWindow::activateOneCallback(Widget, XtPointer clientData,
XtPointer)
{
MyWindow *obj = (MyWindow *) clientData;
obj->activateOne();
}
void MyWindow::activateOne()
{
_menuPaneTwo->activateItem("A New Action");
}
void MyWindow::deactivateOneCallback(Widget, XtPointer clientData,
XtPointer)
{
MyWindow *obj = (MyWindow *) clientData;
obj->deactivateOne();
}
void MyWindow::deactivateOne()
{
_menuPaneTwo->deactivateItem("A New Action");
}
void MyWindow::quitCallback (Widget, XtPointer, XtPointer)
{
theApplication->quitYourself();
}
MyWindow::MyWindow( const char *name) : VkWindow( name)
{
Widget label = XmCreateLabel(mainWindowWidget(), "a menu",
NULL, 0);
// Add a menu pane
_appMenuPane = addMenuPane("Application");
_appMenuPane->addAction("Add One",
&MyWindow::addOneCallback,
(XtPointer) this);
_appMenuPane->addAction("Remove One",
&MyWindow::removeOneCallback,
(XtPointer) this);
_appMenuPane->addAction("Activate One",
&MyWindow::activateOneCallback,
(XtPointer) this);
_appMenuPane->addAction("Deactivate One",
&MyWindow::deactivateOneCallback,
(XtPointer) this);
_appMenuPane->addSeparator();
_appMenuPane->addAction("Quit",
&MyWindow::quitCallback,
(XtPointer) this );
// Add a menu second pane
_menuPaneTwo = addMenuPane("PaneTwo");
addView(label);
}
void main(int argc, char **argv)
{
VkApp *myApp = new VkApp("Menudemo3", &argc, argv);
MyWindow *menuWin = new MyWindow("menuWindow");
menuWin->show();
myApp->run();
}

Menu Access Functions

The VkMenu class also provides some access functions to help manipulate menu items.

Determining number of items

To determine the number of items currently associated with a menu, use VkMenu::numItems():

int numItems() const

Determining position of an item

To determine an item's position in a menu, use VkMenu::getItemPosition():

int getItemPosition(VkMenuItem * item)
int getItemPosition(char *name)
int getItemPosition(Widget w)

You can specify the menu item by pointer, name, or widget. getItemPosition() returns the position of the item within the menu, with zero representing the first position in the menu.

As a convenience, you can also access items in a menu using standard array subscript notation:

VkMenuItem * operator[] (int index) const

For example, you can use VkMenu::numItems() with the array subscript notation to loop through an entire menu and perform some operation on all of the items it contains. For example, if menubar is a menu, the following code prints the name and class of each item in the menubar menu:

for ( i=0; i < menubar->numItems(); i++ )
cout << "Name: " << menubar[i]->name() << "\t"
<< "Class: " << menubar[i]->className() << "\n";