Application Development |
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. Application
Application
Screen
Current screen Widget
Current widget
For example, the application's startup routines in 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
Current screen
Application
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:
baseWindow
resource is set to true
. You can install an application menu only from application memory.
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 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.
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 Subsequently, other screens in the application can install their own instances of this menu with this call:
All screens that display 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:
Toolbar
property set to Yes
, Panther creates a toolbar from the images associated with those items and displays it below the menu bar.
Installing Menus with Shared Content
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 call sm_menu_install \
(MNS_SCREEN, MNL_APPLIC, "mnscript_myprog", "scr_mn")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
MNL_SCREEN
.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:
sm_mnscript_load
at widget entry with an argument of MNL_FIELD
.sm_menu_install
at widget entry with arguments of MNS_FIELD
and MNL_FIELD
.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 Display of individual items on a screen's menu bar and/or toolbar is determined by their 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.
MNI_DISPLAY_ON
property, which is set to one of these values:
DISPLAY_MENU
: Display the item only on the screen's menu bar (default).
DISPLAY_TOOL
: Display the item only on the toolbar.
DISPLAY_BOTH
: Display the item on both the menu bar and toolbar.
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 active
Motif, Windows
inactive
Motif
armed
Motif
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 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:
On Windows, the appearance of tooltip text is under MFC control.
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
MNI_INACT_PIXMAP
MNI_ARM_PIXMAP
MNI_HOT_PIXMAP
TOOLTIP_ON
(default) and TOOLTIP_OFF
, respectively.
Panther*toolbar*tooltip.fontList: *-helvetica-*-18-*
Changing Menus at Runtime |
Panther provides a set of library functions that let you change menus and their items at runtime. You can:
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_menu_bar_error lets you test error conditions generated by the aforementioned 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. For Panther for Windows, the following runtime application properties control the position and appearance of the toolbar in relation to the MDI frame:
Getting and Setting Properties
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
.
_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_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
PR_TOOLBAR_ALLOWED_SITES
|
|
|
|
|
PR_TOOLBAR_CURRENT_SITE
PV_TOOLBAR_FLOAT
, PV_TOOLBAR_TOP
(default), PV_TOOLBAR_BOTTOM
, PV_TOOLBAR_LEFT
, or PV_TOOLBAR_RIGHT
.
PR_TOOLBAR_HIDDEN
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
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:
MNI_INDICATOR
property—set to either PROP_ON
or PROP_OFF
MNI_INDICATOR
property to PROP_ON
or PROP_OFF
.
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.
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.
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.
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