Draft 1.6
Written by Chris Saari
Last Modified: 2/23/99
This document is the engineering details behind the Menu Requirements document. It supplements that document with examples and a comprehensive listing of attributes and parent/child relationships.
From the Requirements Document:
A menu item is a line item in a visible UI menu. It has text (displayed visually) and may contain a shortcut key (cmd-Q for example). A menu item can be enabled or disabled separately from the other items around it. A special kind of menu item, called a separator, is visually represented as a disabled horizontal line with no text.A menu list corresponds to an entire UI menu, and is a sequential ordered list of menu items. A menu list may be hierarchical and have sub-menu lists hanging off of items.
A menu bar is an ordered collection of menu lists. Menu bars are used to present several menus, usually in a non-transient way. Context menus, for example, would not use a menu bar since they are only displaying a single transient menu.
Tag |
Allowed Children |
Attributes |
Description |
menubar |
menu |
none |
The root tag for a menu bar. |
menu |
menuitem, separator, |
name, enabled, icon |
Child of <menubar>. A menu list has a name that will be displayed in the menu bar. The menu list can be enabled and disabled. The menu list can have an icon to be displayed in the menu bar. |
menuitem |
none |
name, enabled, checked, cmd |
Child of <menu>. A menu item has a name to be displayed, can be enabled or disabled, and can be checked or unchecked. |
separator |
none |
none |
A separator line |
While the idea of having style sheets for a menu is intriguing, it presents significant problems when menus are rendering via native OS calls, which may or may not respond to all styles. The current plan is for menus to not obey styles.
<menubar> <menu name="File"> <menu name="New"> <menuitem name="Navigator" cmd="commandid:newnavigator" /> <menuitem name="Message" cmd="commandid:newmessage" /> <menuitem name="Blank Page" cmd="commandid:newblankpage" /> <separator/> <menuitem name="Blank Page From Template..." cmd="commandid:blankpagefromtemplate" /> </menu> <menuitem name="Open" cmd="commandid:open" /> <separator/> <menuitem name="Close" cmd="commandid:close"/> <menuitem name="Save As..." cmd="commandid:saveas"/> <separator/> <menuitem name="Quit" cmd="commandid:quit"/> </menu> <menu name="Edit"> etc... </menu> </menubar>
The implementation of the menu facilities will be native code on each platform with cross platform interfaces, primarily consisting of the DOM interfaces. Some interfaces may only have meaning on one platform however. For example, the interface to set the default menu bar may only make sense on MacOS where menu bars are not always associated with a window.
Because of the uniqueness of menu events not having an associated visible component inside the window frame on all platforms, the events will be captured via custom mechanism inside of Gecko and sent to the listening nsMenuBars for dispatch. This means menus cannot be scripted directly, but the Command Nodes associated with a menuitem will still be scriptable. In other words, if you execute a command via a Command Node with a script, the menu item will not flash accordingly, but the command will be executed.
As for the frames vs. widget question, it is the author's current opinion that nsIWidget is the correct interface for XPToolkit menu facilities. Note: saying that a menu is a widget is in some sense a lie. The nsIWidget interface is a convenient for fitting into the XPToolkit object model. Menus are not proper widgets.
Menus construction sequence:
After all of this, there is a complete menubar, ready for action.
If a widget wishes to place menus in the menu bar, or menu items in a menu, it may do so by making a request to the host application. A request includes the desired menu position in the menu bar (if a menu is being merged) or the position of the menu item in the menu list (if a menu item is being merged), and a reference to the menuitem widget's AOM node, which should have been set up during a XUL load to have a reference to a Command Node. This seems an elegant way to do merging that meshes well with the proposed command architecture.
A merge request will usually happen when a widget gets focus. When the widget looses focus, it should remove the merged items that it does not wish to be persistent across focus changes. It was debated that the menu facilities manager should automatically undo the merge for the widget upon focus loss, but that requires the manager to be aware of focus changed events, which it is not currently.
It has been requested that a "widget" have the capability to do a menu merge, even before a widget is instantiated. It is the author's belief that the intended effect can be achieved via a Command Node and a XUL modification. Simply add a new menu item to the XUL with a Command that can fulfill the desired behavior. This is a general purpose approach that is actually not related to widgets at all.
(read as: not a requirement, but would be nice)
MacOS support for Frontier's Shared Menus