Application Development


Chapter 15. Including Menus and Toolbars

Menu bars, popup menus, and toolbars are all instantiated from menus that you define through the menu bar editor and save to a binary resource file, or menu script. Because menu bars, popup menus, and toolbars are created from the same menu definition, runtime access to all three is provided through the same set of library functions. In this chapter, all references to menus apply equally to menu bars, popup menus, and toolbars, unless otherwise noted.

Menu definitions are saved in menu scripts. When you save a menu through the menu bar editor, the menu and its submenus are saved to a binary script. At runtime, Panther can load one or more scripts into memory; it can then install menus from these scripts at different levels of the application. Depending on how a menu is installed, it can display as a menu bar on a screen or be invoked as a popup from a screen or widget. If the menu is installed as a menu bar and one or more of its items have their MNI_DISPLAY_ON property set to DISPLAY_TOOL or DISPLAY_BOTH, Panther also displays a toolbar with the menu bar.

You can specify to load a menu script and install a menu from the Properties window of a screen or widget. Alternatively, you can use Panther runtime functions to load and display menus.

This chapter shows how to perform the following tasks:


Loading Menus into Memory

When you load a menu script, all of its menus are stored in memory and are available for installation and display. Panther applications have three levels of memory for loading menus:

A script can be loaded only once in each memory location—that is, a given script can be loaded only once into application memory, and once into the memory location of a screen or widget. So, if several screens have the same menu installed from a script in application memory, they display identical menus—if one menu changes, those changes are written to the same memory and immediately propagated to the other menus. Alternatively, if each screen has the same menu installed from its own memory—each screen has its own instance of the script loaded into screen memory—each instance of that menu is unique: changes to one are written only to its own memory and have no effect on the other screen menus. This chapter contains sections on "Installing Menus with Shared Content" and "Installing Menus with Unique Content".

You can load a menu script in two ways:

The first method loads the menu script into the screen or widget's memory and makes its menus available to that screen or widget. sm_mnscript_load can load the specified script into any memory location that is the same or higher than its caller, as shown in the following table:

sm_mnscript_load caller Valid memory locations

Application

Application

Screen

Current screen
Application

Widget

Current widget
Current screen
Application

For example, the application's startup routines in jmain.c can only load menu scripts into application memory, while a screen's entry procedure can load scripts into application memory and its own memory.


Installing Menus

After you load a menu script, you can install any of its menus for display. When a menu is installed, Panther finds it in the specified script and reads its definition. If the menu contains external references—the menu is defined in another script—Panther resolves these; it then makes the menu available for display.

Except for Motif versions, Panther applications can display only one menu bar and its corresponding toolbar at a time. For example, if an application contains multiple screens and each screen has its own menu, only the menu bar and toolbar of the active screen are displayed. Under Motif, an application menu and a screen menu can display simultaneously if you set the baseWindow and formMenus resources to true.

You can install a menu at four scopes:

You can install a menu in two ways:

When a screen opens, Panther looks at its Menu Name property and installs the menu specified there, if any, as that screen's menu bar. If any of the menu items have their Toolbar property set to Yes, Panther creates a toolbar from the images associated with those items and displays it below the menu bar.

If the screen's Popup Menu property specifies a menu, Panther also installs this menu at screen scope. Panther displays the screen's popup menu when the user invokes it from the screen. If no entry exists for Popup Menu, Panther also uses the Menu Name property for the screen's popup menu.

At screen open, Panther also checks the Menu Popup property of each widget; Panther installs each menu specified by a widget at field scope and displays it as a popup when invoked from that widget.

With sm_menu_install, you can install a menu at any scope that is the same or higher than the calling environment, from any memory location that is valid for that scope. Thus, a screen's entry procedure can install a menu for the current screen or for the application, while a widget's entry procedure can install a menu for the current widget, its screen, or the application. If another menu is already installed at the specified scope, it is removed. If the same menu is already installed from the same memory location, Panther does not try to reinstall it.

Installing Menus with Shared Content

Because a script can be loaded only once into a given memory location, all menus installed from that location are identical. Panther provides only one memory location at the application level. So, all scripts in application memory are unique, and all instances of a menu installed from application memory are the same: changes in one are immediately propagated to all others.

You can install the same menu from application memory for different screens and widgets; if you do, all instances of this menu are always the same. If you install the same menu for different widgets from screen memory, all popup menus of those widgets are identical.

For example, the following entry procedure in an application's startup screen loads a menu script into application memory; it then installs the menu scr_mn for the startup screen from application memory:

proc install_menu
if (sm_mnscript_load(MNL_APPLIC, "mnscript_myprog") == 0)
{
call sm_menu_install \
(MNS_SCREEN, MNL_APPLIC,"mnscript_myprog", "scr_mn")
}
else
{
msg emsg "No menu found for application. Goodbye"
call jm_exit
}
return

Subsequently, other screens in the application can install their own instances of this menu with this call:

call sm_menu_install \
(MNS_SCREEN, MNL_APPLIC, "mnscript_myprog", "scr_mn")

All screens that display scr_mn as a menu bar and toolbar display the same menu and toolbar. Thus, if one screen makes a menu item inactive, that item is inactive on the other screens.

Installing Menus with Unique Content

You can install multiple copies of the same menu for screens and widgets, where each copy is unique. Because screens and widgets can load menu scripts into their private memory locations, each location can maintain its own copy of a menu; changes to one have no effect on the others.

To install unique copies of the same menu for several screens, repeat these steps for each screen:

  1. Load the menu script into screen memory—specify the script in the screen's Menu Script File property; or call sm_mnscript_load at screen entry with an argument of MNL_SCREEN.
  2. Install the menu from screen memory—specify the menu in the screen's Menu Name property or Popup Menu property; or call sm_menu_install at screen entry with arguments of MNS_SCREEN (for a menu bar) or MNS_SCRN_POPUP (for a popup menu), and MNL_SCREEN.

Similarly, you can make sure that widgets have unique copies of the same popup menu. Repeat these steps for each widget:

  1. Load the menu script into field memory for the widget—specify the script in the widget's Menu Script File property; or call sm_mnscript_load at widget entry with an argument of MNL_FIELD.
  2. Install the menu from the widget's memory—specify the menu in the widget's Menu Name property; or call sm_menu_install at widget entry with arguments of MNS_FIELD and MNL_FIELD.

Referencing External Menus

A menu definition can specify submenus whose contents are defined outside the current script—that is, the submenu's External property is set to Yes. For maximum flexibility, the external flag contains no information about this menu's script name. Consequently, when you install a menu, Panther resolves external references by searching first among scripts in the same memory location, then among scripts in the next highest memory location, and so on.

For example, given a menu installed from screen memory, Panther tries to resolve each of its external references first by searching among other scripts in screen memory; if no match is found in screen memory, Panther continues the search among the scripts loaded into application memory. If no menu is found in either memory location, Panther displays an empty submenu.


Displaying Toolbars

A screen can display a toolbar alongside or in place of a menu bar. Both the toolbar and menu bar are instantiations of the same menu: any item that can be displayed on the screen's menu bar can also be displayed on its toolbar, and vice versa.

Display of a toolbar depends on two conditions being true:

You enable toolbar display through the setup variable TOOLBAR_DISPLAY, which can be set to TOOLBAR_ON (the default) or TOOLBAR_OFF. This variable can be changed at runtime by calling sm_option to toggle toolbar display for the entire application.

Display of individual items on a screen's menu bar and/or toolbar is determined by their MNI_DISPLAY_ON property, which is set to one of these values:

You can set a menu item's initial display in the menu bar editor and change it at runtime.

Panther for Windows can dock the current toolbar to the MDI frame. Runtime application properties control the position and appearance of the toolbar; refer to "Dockable Toolbar Properties."

If a menu item is set to display on a toolbar, you should set its pixmap properties to determine the item's display in its different states. You must also set pixmap properties for all toolbar items.

Panther for Windows uses MFC to control toolbar display, which sets the item's inactive and armed display from the MNI_ACT_PIXMAP (active) property and the display for MouseOver events from the MNI_HOT_PIXMAP (hot) property.

Pixmap property Platform availability

MNI_ACT_PIXMAP

active

Motif, Windows

MNI_INACT_PIXMAP

inactive

Motif

MNI_ARM_PIXMAP

armed

Motif

MNI_HOT_PIXMAP

hot

Windows

For more information about setting pixmap properties, refer to "Displaying Pictures on Toolbar Items" in Using the Editors.

You can set an item's tooltip text, which displays when the cursor remains above that item; tooltip display is enabled or disabled for the entire application through the setup variable TOOLTIP_DISPLAY. You can toggle tooltip display on and off by using sm_option to set it to TOOLTIP_ON (default) and TOOLTIP_OFF, respectively.

You can control the font type and size for tooltips in Motif applications through the Panther resource file. For example, this statement sets tooltip text to 18 point Helvetica:

Panther*toolbar*tooltip.fontList:											*-helvetica-*-18-*

On Windows, the appearance of tooltip text is under MFC control.


Changing Menus at Runtime

Panther provides a set of library functions that let you change menus and their items at runtime. You can:

Getting and Setting Properties

All properties that are available through the menu bar editor also are accessible and modifiable through Panther library functions.

You can get the current setting of a menu property by calling either sm_menu_get_int or sm_menu_get_str. To get a menu item's property setting, call either sm_mnitem_get_int or sm_mnitem_get_str. Use the _int variant for those properties that have an integer value—for example, MN_TEAR or MNI_ACTIVE; use the _str variant for properties that take string values, such as MN_TITLE and MNI_CONTROL.

sm_menu_bar_error lets you test error conditions generated by the aforementioned _get functions. These functions return the value of the specified property when successful; otherwise, they return -1 for failure of the _get_int variants and NULL for the _get_str variants. sm_menu_bar_error returns the error code generated by the last call to one of these variants.

sm_menu_change and sm_mnitem_change set menu and menu item properties, respectively. These properties are derived from a memory-resident script. Because these functions change the specified script, all instances of menus installed from this script get the requested property change.sm_mnitem_change and its variant sm_n_mnitem_change cannot be called directly from JPL; consequently, a number of wrapper functions are declared and installed, which you can use to modify menu items in JPL modules.

Dockable Toolbar Properties

For Panther for Windows, the following runtime application properties control the position and appearance of the toolbar in relation to the MDI frame:

PR_TOOLBAR_ALLOWED_SITES
Set the frame placements allowed for the toolbar using one or more of the following bit flags:

PV_TOOLBAR_FLOAT

PV_TOOLBAR_TOP

PV_TOOLBAR_BOTTOM

PV_TOOLBAR_LEFT

PV_TOOLBAR_RIGHT

PR_TOOLBAR_CURRENT_SITE
Set the current placement of the toolbar using one of the defined bit flags: PV_TOOLBAR_FLOAT, PV_TOOLBAR_TOP (default), PV_TOOLBAR_BOTTOM, PV_TOOLBAR_LEFT, or PV_TOOLBAR_RIGHT.

PR_TOOLBAR_HIDDEN
Set whether the toolbar is currently displayed using PV_YES and PV_NO. Users can hide the toolbar by clicking on the X in the upper-right corner of the menu.

PR_TOOLBAR_X_POSITION and PR_TOOLBAR_Y_POSITION
Specify the screen coordinates of the upper-left corner of the floating toolbar. Double clicking on a floating toolbar at runtime docks the toolbar to the frame.

Changing the State of Toggle Items

Toggle items—on a menu and a toolbar—are initially set to the state specified in the menu script. Toggle items alternatively show or hide a system-specific indicator to show whether the item's state is on or off. If the toggle item is included in the toolbar, Panther uses its MNI_ARM_PIXMAP or MNI_ACT_PIXMAP property to show whether its state is on or off.

The function that you associate with a toggle item through its control string property should perform these tasks:

For example, the following code examines the state of menu item tgl2 and changes its MNI_INDICATOR property accordingly.

vars ind, ret
ind = sm_n_mnitem_get_int \
(MNL_SCREEN, "toggle", "sub1", "tgl2", MNI_INDICATOR)
if (ind_state == PROP_ON)
{
ret = tgl2_proc(PROP_ON)
if ret > 0
{
call sm_n_mnitem_change_i_screen \
("toggle", "sub1", "tgl2", MNI_INDICATOR, PROP_OFF)
}
}
else if (ind_state == PROP_OFF)
{
ret = tgl2_proc(PROP_OFF)
if ret > 0
{
call = sm_n_mnitem_change_i_screen \
("toggle", "sub1", "tgl2", MNI_INDICATOR, PROP_ON)
}
}

Creating and Deleting Menus

Inserting and Deleting Menu Items


Uninstalling and Unloading Menus

Menus and their scripts remain in memory until Panther frees their memory location—for example, when a screen with its own menu is removed from the form or window stack. Panther automatically removes all menus and frees their memory when the application exits.

You can explicitly remove a menu from display by calling sm_menu_remove. This function takes a single argument that specifies the scope from which to remove the current menu. Because the menu script remains in memory, subsequent changes to the menu's properties become visible when you reinstall it. This function has no effect on other instances of the menu that are installed from the same memory location.

You can remove a script from memory with sm_mnscript_unload. This function takes two arguments—the script's name and memory location. Panther removes the script from the specified memory location and destroys all menus that are installed from it. If any of those menus are currently displayed, Panther removes them immediately. If a menu is referenced as an external menu, Panther displays an empty menu in its place.


Invoking Popup Menus

Panther displays a popup menu when the user presses the right mouse button or when sm_popup_at_cur is called. Panther uses one of the following two algorithms for finding and displaying a popup menu:

You can let users invoke popup menus from the keyboard with sm_popup_at_cur. For example, the following control string assignment lets the user invoke a popup menu by pressing the PF1 key:

PF1 = ^sm_popup_at_cur

Calling Menu Functions From JPL

All menu functions that can be prototyped are installed and can be called from a JPL procedure. However, three functions cannot be prototyped because their parameter lists do not conform to current requirements. These are:

Wrapper functions for these routines are provided and installed in funclist.c; you can call these from JPL to change menu and menu item properties and to create menu items.


Outputting Menu Definitions to ASCII

You can save menu definitions to ASCII format through the m2asc utility. ASCII menu definitions define a menu as a hierarchy, where the top-level menu and its items are defined first along with global menu properties, followed by submenus and their items. You can edit the ASCII file using a text editor, and then convert it to binary format using the same utility. Refer to m2asc for an example of a menu file's ASCII output.

Keywords

Each component of a menu definition is identified by a keyword (refer to Table A-1 and, optionally, a unique name. In some cases, Panther uses these names to resolve references—for example, given a submenu item that sets its SUBMENU property to myEditSub, at runtime, Panther looks for a MENU:myEditSub item in the same script to build that submenu. In all cases, you can use these identifiers to get and set item properties at runtime.

Menu Properties

Each menu and menu item definition has properties; these properties are specified immediately below the component's identifier in the ASCII output. For example, the following statements define a submenu item myoption: its label is Options with a keyboard mnemonic of O; it invokes the menu myoptionsub; and it is initially available for selection (ACTIVE=YES):

SUBMENU:myoption
LABEL=&Options
SUBMENU=myoptionsub
ACTIVE=YES

Table 15-1 lists all menu property mnemonics and their valid values. For additional information about the properties, refer to Chapter 25, "Menu Bar Editor," in Using the Editors.

Table 15-1 Menu properties and valid assignments

Property Values

ACCEL

Accelerator string that specifies the keyboard equivalent for selecting this menu item.

ACCEL-ACTIVE

Specifies whether the menu item accelerator is active (PROP_ON) or inactive (PROP_OFF).

ACTIVE

Allows (YES) or disallows (NO) user access to this menu item. If ACTIVE=NO, the menu item is greyed out.

ACTIVE_PIXMAP*

Name of image file whose contents are shown for active toolbar item—that is, accessible but not pressed. Refer to "Image File Types" on page 25-15 in Using the Editors for valid file types, and for information about path and extension options.

ARM-PIXMAP*

Name of image file whose contents are shown for armed toolbar item—that is, in its pressed state. If the property is blank, Motif uses the MNI_ACT_PIXMAP property for the item's armed state; Windows uses a modified version of the Active Pixmap property to display a toolbar item's armed state and ignores this property.

CONTROL

Control string that specifies the action that occurs when the item is selected.

DISPLAY-ON

Specifies whether to display the menu item on the menu and/or the tool bar. Supply one of these arguments:

EXTERNAL

Specifies whether to find this menu's definition in another menu script (YES), or not (NO). External references are resolved at runtime only.

EXT-HELP-TAG

String expression that specifies the help text to invoke for this item.

HOT-PIXMAP*

In Windows, name of image file whose contents are shown when a mouse passes over the item.

INACTIVE-PIXMAP*

Name of image file whose contents are shown for an in active or unavailable (grayed) item. If blank, Motif displays an empty toolbar item; Windows uses a grayed version of the Active Pixmap property to display the item's inactive state and ignores this property.

INDICATOR

Specifies whether to show (YES) or hide (NO) the toggle indicator.

IS-HELP

Specifies whether to display (YES) this item as the right most item on the menu bar, or not (NO).

LABEL

String expression to display as menu item's label. To specify a keyboard mnemonic for a menu item, place an ampersand (&) in front of the desired character.

MEMO

String expression for the Memo Text property.

MNI_ORDER*

Order in which the item appears on the toolbar. Enter any value between 0 and 200 (default is 100), inclusive. If all toolbar items have the same value, they appear in the same order as they do in the menu.

SEP-STYLE

Style used by item separators, one of the following:

SINGLE
DOUBLE
DOUBLE-DASHED
SINGLE-DASHED
ETCHED-IN
ETCHED-OUT
ETCHED-IN-DASHED
ETCHED-OUT-DASHED
NOLINE
MENUBREAK

SHOW-ACCEL

Specifies whether the menu item displays (YES) or does not display (NO) the accelerator key next to the label.

STAT-TEXT

String expression to display on status line for this item.

SUBMENU

Name of submenu to invoke when the item is selected.

TEAR

Enables (YES) or disables (NO) the submenu as a tear-off menu.

TITLE

Title to display with tear-off submenus.

TM-CLASS

Transaction manager property. Refer to "Setting Classes for Menu Items and Push Buttons" on page 23-7 in Using the Editors for valid arguments.

TOOL-TIP*

Balloon help to display when the cursor remains over the toolbar item.

* Ignored in character-mode.

A subset of these properties is valid for each menu component except WINOP and WINLIST. Figure 15-1 shows which properties are valid for each component:

Figure 15-1 Menu components and their properties