7. Menus

This document contains the following sections:

7.1 Some menu notation
7.2 Usual menu behavior
7.3 Pull-down and pop-up menus
7.4 Menu bars
7.5 The menu editor
7.6 Getting rid of a menu bar
7.7 Specifying menu titles and shortcuts
7.8 Access keys
7.9 Working with the menu pane
7.10 More on the menu editor toolbar and some anomalies
7.11 The Menu Item group
7.12 How choosing a menu command causes something to happen
7.13 Some examples of getting menus to do something
7.14 Changing a menu or command (menu-item) programmatically
7.15 Doing something just before a menu is displayed

This is chapter 7 of the User Guide for the Allegro CL 6.0 Integrated Development Environment (IDE). The IDE is only supported on Windows machines.

The chapters of the IDE User Guide are:

Chapter 1: Introduction to the IDE
Chapter 2: The Allegro CL Development Environment (IDE)
Chapter 3: An example
Chapter 4: Projects
Chapter 5: Components
Chapter 6: Designing a user interface
Chapter 7: Menus (this chapter)
Chapter 8: Events

A menu is a pull-down or pop-up list of commands. Because menus can contain any (reasonable) number of commands and are displayed only by user action, they provide a convenient way to group related commands in a way that they are available at any time to users. There is further documentation on creating menus in doc\cg\menu\menu.htm.

7.1 Some menu notation

Menus contain commands. The object corresponding to a command is a menu-item. However, we use menu-item when describing the programmatic aspects of menu but command when discussing the appearance of menus in an application.

A user can point to a command while the menu is visible. The command pointed to is highlighted and if it names a submenu, the submenu is displayed.

You click a menu command not associated with a submenu to effect it (choose can be used in place of click). When a command is clicked, the menu disappears and the action associated with the command is performed.

A menu command may be associated with another menu (called a submenu). Pointing to (putting the mouse over) the menu command causes the submenu to be displayed and the user can point to or click on a command from the submenu just as with the main menu. (Submenus allow very many commands to be presented rather conveniently since most commands are not displayed at any one time.)

In this document, we specify a menu and command with the menu title followed by a horizontal bar (|) followed by the command name, all in bold. Thus File | Save is the Save command on the File menu. Commands from submenus are shown with additional |'s, thus View | Manage | Iconize is the Iconize command on the Manage submenu of the View menu. (We have been using this notation in other chapters of this document.)

7.2 Usual menu behavior

Clicking or choosing a command causes some action. Menus are rarely used simply to display information (although a command can cause an informative dialog to appear). Information can be conveyed incidentally, however. The fact that a command is unavailable (cannot be pointed to or chosen) can be informative. Some editors make the Save command on the File menu unavailable if there are no changes to save and Paste can be made unavailable when there is nothing on the clipboard.

A user can click on no command and cause the menu to disappear. Typically nothing happens when no item is selected and the state of the program is typically the same as if the menu had never been displayed. (We say typically twice in the last sentence because the application programmer can associate any action – displaying the menu or pointing to a command or whatever – with any effect. If you are programming a game, you might have a Hint menu and cause the game player to lose points if the Hint menu is looked at, whether or not a command is chosen. Or an application designed to study user interfaces may record how often menus are displayed and items chosen as a way of learning about user behavior, perhaps with an eye to improving the interface.)

7.3 Pull-down and pop-up menus

A pull-down menu is displayed on a menu bar. Menu bars are displayed only on a top-level window. The menu bar is typically always visible and the user can display a menu any time the mouse is available.

Pop-up menus are displayed by specific user action but have no specific location and no title. Pressing or clicking the right mouse button in various locations in the Allegro CL development environment displays a pop-up menu with context-related items. Another pop-up menu is the symbol completion menu displayed by choosing Search | Complete Symbol. While typing in the Debug window or in an editor window. For example, at a prompt in the Debug window, type

string>

and, leaving the cursor right after the >, choose Search | Complete Symbol. A pop-up menu appears with items string> and string>= (the two symbols whose names begin with string>).

This chapter is concerned with pull-down menus. For information on pop-up menus, see the online help topics pop-up-shortcut-menu and pop-up-lettered-menu.

7.4 Menu bars

To add a menubar to a form, select the form, and then either (1) click on Form | Add Menu Bar or (2) select the menu property in the Inspector, and click on the Extended Editor button:

This displays the menu editor.

To have a pull-down menu on a window, you must:

Do all that and you will have a working menu. Here are some more things that you can do:

Each one of these issues will be dealt with below. The basic tool for placing menu bars on top-level windows and creating pull-down menus is the Menu Editor, which we describe next.

7.5 The menu editor

The menu editor looks like this:

You are given a default starter menu bar. You can make changes and accept the menu bar by clicking on the OK button. As you work in the menu editor, you will see the menu bar update on your form. If you click the Cancel button, the editor is closed and the menu property is left unchanged (meaning no menu bar if it was nil before, the previous menubar if there was one before). The starter menu bar has a File menu and an Edit menu containing some Windows-standard commands.

7.6 Getting rid of a menu bar

If a form has a menu bar and you decide you do not want one on that form, you can get rid of it by clicking Form | Remove Menu Bar while the form is selected. You can also do it by selecting the contents of the menu property when the form is being inspected and replacing those contents with nil (by typing n i l).

The menubar will also not be displayed if you

7.7 Specifying menu titles and shortcuts

The menu titles, command names, and shortcuts are displayed in the Menu group in the center of the menu editor. The display is an outline control, with leaves (terminal entries with no subentries) corresponding to commands and nodes (entries with subentries) corresponding to menus or submenus. The title of a menu appears in the menu bar or, if the menu is a submenu, as an item in the parent menu. The title is not a command. Clicking on it displays the menu whose title it is.

A shortcut is a key combination which when pressed has the same effect as choosing the menu command. The shortcuts are shown in the second column. Menus do not have shortcuts, only commands, shown as leaves in the display.

7.8 Access keys

An access key in combination with the Alt key lets you display a menu and choose a command from the keyboard. A tilde (~) is a non-displaying character in a menu title or command name which marks the next character as the one to press when the Alt key is down to display a menu or submenu (in a menu or submenu title) or choose a command. Thus, Alt-F displays the File menu (whose title is ~File). Pressing Alt and keeping it down while pressing F (displays the File menu) and N (chooses the New command) is the same as choosing New from the File menu. The character after the tilde is underlined when the menu is displayed. If no tilde appears, the command cannot be selected using Alt and other keys. Note: because of an apparent Windows bug, access keys do not work when running a project with a form that has a menubar but no other controls. To see access keys working, add any control (e.g., a button) to the form. Also, if you run a form rather than the whole project, the IDE menu bar pre-empts the running form's menu bar. Thus Alt-F will display the IDE's File menu, not the running form's File menu.

7.9 Working with the menu pane

The Menu group is the portion of the menu editor labeled Menu Name:

You cannot type in the Menu group. (You make changes that require typing – changing a title of a command name, adding or removing a tilde, etc. – in the Menu Item pane described below.) When a line is selected (as the ~File line is in the illustration), its details are displayed in the Menu Item group described below and the toolbar buttons will effect it as follows:

7.10 More on the menu editor toolbar and some anomalies

If you add an entry (by clicking on the Add button -- with a +), the new entry has the same indentation as the currently selected entry and becomes the selected entry.

If you delete all entries, the menu bar ceases to be visible but still exists. (Make the menu property nil if you want no menubar.)

7.11 The Menu Item group

The Menu Item pane, at the bottom of the Menu Editor, allows you to specify the details of the entries in the Menu group. The details of the selected entry in the Menu Pane are displayed in the Menu Item pane and changes affect that entry only. Only one entry can be selected at a time. Here is the Menu Item pane from the default menus (i.e. the File and Edit menus displayed when the Menu Editor first appears) with the third (~Open) entry selected:

The elements of this pane are:

If you want a tilde displayed, enter two tildes. Thus, if the title is ~~Open, it will display as ~Open and it cannot be chosen using the Alt key.

7.12 How choosing a menu command causes something to happen

When you click on a menu command, the system knows what you have done: it knows which window contained the menu bar, it knows which menu contained the command, and it knows which command was chosen. But it doesn't know what to do with this information other than pass it to the application owning the window, so that is what it does. In an Allegro CL application, every menu has an on-click function. When a menu command is clicked, the menu on-click function is called with three arguments: the menu object, the menu-item corresponding to the command clicked on, and the window owning the menubar.

You can specify the menu on-click function in the On Click field of the menu-item group. This field is only active when a menu or submenu (rather than a command) is selected.

The default selection function for the default menus is funcall-menu-item-with-window. This function examines the menu-item, extracts the menu-item value (which in this case is a symbol naming a function of one argument, a window), and funcalls that function with the window (owning the menu bar) as the argument.

It is common to have the menu-item value contain the information about what should be done when the user clicks on a menu command. Menu-item values can be any Lisp object but symbols naming functions are common choices. Since you define the function, you have great flexibility about what it does. The menu on-click function is then just a function which funcalls the menu-item value with whatever arguments you want, often no arguments or just the owning window as an argument.

The menu-item value is specified in the menu-item group when a menu item is selected.

We have already mentioned the predefined function funcall-menu-item-with-window. Another useful predefined selection function is funcall-menu-item, which funcalls the menu-item value with no arguments.

7.13 Some examples of getting menus to do something

The function pop-up-message-dialog takes arguments stream, title, text, icon, button-label. We are going to construct a menu whose command pops-up a message using that function where the title and text say what command you chose. Now, of course, this is likely not very useful in a real application but if you can get a menu command to pop-up a message like this, you can probably get it to do many other things by emulation.

Our menu will be called Messages and have two commands: Hello and Goodbye. The menu on-click function will be funcall-menu-item and the menu-item-values will be the symbols hello-function and goodbye-function, which are defined as follows:

(defun hello-function ()
  (pop-up-message-dialog (screen *system*) "Hello" 
                         "Clicked Hello Command!!!" warning-icon "OK"))
 (defun goodbye-function ()
 (pop-up-message-dialog (screen *system*) "Goodbye" 
 "Clicked Goodbye Command!!!" warning-icon "OK"))

We define these to the system (by, for example, evaluating them in the debug window). (screen *system*) is the screen (meaning the dialog can pop-up anywhere), warning-icon is a picture of a yellow triangle with an exclamation point, and OK is the label for the button. Our menu editor after we have defined the new menu (and deleted the default File and Edit menus) looks like this:

Note that the On Click field when Messages is selected is funcall-menu-item. The On Click field for Messages will only be available after you have added and indented the Hello and Goodbye items, and when it is available, its value starts as funcall-menu-item-with-window. You must edit that to be funcall-menu-item for this example to work.

If we run the form and click on the Hello command in the Messages menu, we see:

If we click on Goodbye, we see:

There is not in this example much information in the menu-items. We could define a selection function that extracts information from the menu-item but processes it itself rather than having the menu-item value do the work. This can be useful when you define menu commands on the fly, based on runtime information. In this case, the menu-item values are strings "Hello" and "Goodbye". The menu-selection function is the following:

(defun my-menu-on-click-function 
    (menu menu-item window)
  (declare (ignore menu window))
  (let ((title (value menu-item))
        (message (concatenate 'string 
                   "You clicked " 
                   (value menu-item)
                   "!!!!")))
    (pop-up-message-dialog 
     (screen *system*) 
     title message warning-icon "OK"))) 

The behavior is the same as before.

7.14 Changing a menu or command (menu-item) programmatically

Commands are what appear on menus. On our example menus, the commands are Hello and Goodbye. However, the programmatic object associated with a command is a menu-item, which is an instance of class menu-item and has various properties. One is the available property. If mi-var is a variable whose value is a menu item,

(available mi-var)

returns true or false as the menu-item is or is not available. You can use setf with available to change (or set) the availability of a menu-item. Evaluating the following makes the menu-item mi-var unavailable:

(setf (available mi-var) nil)

So, the only issue is how to find a menu-item programatically. There are various ways to do this, but one of the easiest is to give the object a name and get it using find-named-object and that name. Here is the menu editor again with our Messages menu. We have given the Hello menu-item the name :hello-item (illustrated) and the Goodbye menu-item the name :goodbye-item (not shown):

Assuming that mywin is the window with the Messages menu,

(find-named-object :hello-item mywin)

will return the Hello menu-item,

(available (find-named-object :hello-item mywin))

returns true or false as the Hello item is or is not available, and

(setf (available 
       (find-named-object :hello-item mywin)) 
  nil)

makes it unavailable.

Now the problem is reduced to getting a handle on the form or window. When developing, click on Get Component on the Tools menu and then click on the form (or window, if you are running the form) and then in the debug window, enter

(setq mywin *)

Programmatically, you can use find-window.

7.15 Doing something just before a menu is displayed

The system calls about-to-show-menu with arguments the window and the menu when user action should cause a menu to appear (user action being, e.g., clicking on the menu title on a menu bar or pressing Alt and the underlined letter of the menu title). about-to-show-menu is a generic function. You can write a before method that will run before the system call to the function (making items unavailable, registering the fact that the menu was looked at, or whatever). If you do this, it is best to make your own class of windows and specialize the method on that class. This avoids paying the overhead every time any menu is displayed anywhere within Allegro CL or your application.

Go to chapter 8. Go to the beginning of this chapter.

Copyright (c) 1998-2000 by Franz Inc. All rights reserved.