10 June 2010
General experience building HTML-based applications is suggested. For more details on getting started with this Quick Start, refer to Building the Quick Start sample applications with HTML.
Additional Requirements
Intermediate
Operating systems provide built-in (or native) facilities for creating menus. The AIR NativeMenu classes provide an interface for creating and modifying native operating system menus as well as for adding event listeners to handle menu events.
The AIRMenus example application, shown in Figure 1, illustrates how to create the various kinds of native menus supported by AIR.
Note: This is an example application provided, as is, for instructional purposes.
This sample application includes the following files:
If you use Flex 3.0.2 or Flex SDK 3.2 or later to build this Quick Start, you must change the XML namespace in the second line of the AIRMenusFlex-app.xml file, to this:
xmlns="http://ns.adobe.com/air/application/1.5"
Adobe AIR supports the following types of menus:
air.NativeApplication.nativeApplication.menu property. Use the air.NativeApplication.supportsMenu property to test whether your application is running in an environment with application menu support.NativeWindow.supportsMenu property to test whether your application is running in an environment with window menu support. Window menus can only be used with windows that have system chrome.NativeMenu.display() method, or you can create a DHTML menu.display() method of any NativeMenu object.The AIR Menus sample application creates a native menu containing example File, Edit, and Help submenus, and uses it in each of the supported menu locations. When a menu command is chosen, its label is printed to the window by a menu event handler.
To test the application, download and launch the installer (AIRMenus.air). Open a menu through one of the following methods:
Any time you select a menu command it is listed on the window.
For more information about using AIR classes, see the Adobe AIR API Reference for HTML Developers.
To create a menu, you start with a new NativeMenu object and add commands, submenus and separators to it. The top, or root, level menu of application and window menus is the menu bar and should only contain submenus. Command and separator items in the root level menu are not displayed at all on Mac OS X. On Windows, the item appears, but it does not open a submenu, which will probably confuse users.
The AIR Menus example uses a function to create the root menu, which is called for each type of menu supported by AIR. The function creates three example submenus, labeled File, Edit, and Help. The NativeMenu objects for these submenus are, in turn, created by other functions:
function createRootMenu(){
var menu = new air.NativeMenu();
menu.addSubmenu(createFileMenu(),"File");
menu.addSubmenu(createEditMenu(),"Edit");
menu.addSubmenu(createHelpMenu(),"Help");
return menu;
}
The functions that create the submenus use the addItem() method to add commands and separators. Each menu object contains an items array. Since all of the events dispatched when a menu is selected are handled by the same function, the items array is used to attach the listener to all the items. The following function creates the File menu:
function createFileMenu(menuType){
var temp;
var menu = new air.NativeMenu();
temp = menu.addItem(new air.NativeMenuItem("New"));
temp.keyEquivalent = 'n';
temp.data = menuType;
temp = menu.addItem(new air.NativeMenuItem("Open"));
temp.keyEquivalent = 'o';
temp.data = menuType;
temp = menu.addItem(new air.NativeMenuItem("Save"));
temp.keyEquivalent = 's';
temp.data = menuType;
menu.addItem(new air.NativeMenuItem("",true));//separator
temp = menu.addItem(new air.NativeMenuItem(quitLabel));
temp.keyEquivalent = 'q';
temp.data = menuType;
for (var item = 0; item < menu.items.length; item++){
menu.items[item].addEventListener(air.Event.SELECT,itemSelected);
}
return menu;
}
The function creates a temporary item for each menu for the purpose of assigning properties. A keyboard shortcut can be assigned by setting the item’s keyEquivalent property. AIR automatically adds a standard modifier key to the keyboard shortcut. On Mac OS X, the modifier is the command key, on Windows, it is the control key. In addition, if you set keyEquivalent with an uppercase letter, the shift key is also added to the key modifier array. To use a shortcut with no modifiers, use a lowercase letter and set the keyEquivalentModifiers property to an empty array, as follows:
item.keyEquivalentModifiers = [];
Note: Key equivalents can only be used to select commands in application or window menus. Although they can be assigned, and may even be displayed, in other types of menus, pressing the key combination has no effect. Showing the shortcut in a context or pop-up menu is not necessarily a problem when there is also a window or application menu to handle the shortcut, but otherwise the display of a non-functional shortcut could confuse your application users.
The createFileMenu() function also sets the data property of each menu item. The data property is a convenient place to reference an object relevant to a menu command. In this case, the data property is set to a string describing the parent menu. This string is used in the itemSelected() event handler to report the menu to which a selected command belongs.
When AIR supports application menus on an operating system, the static air.NativeApplication.supportsMenu property is true. The Mac OS X operating system provides a default application menu. You have the option of using the provided menu (most of the commands do nothing unless you add event listeners), perhaps adding new items and submenus, or replacing the menu entirely. The AIR Menus example takes the second approach.
if(air.NativeApplication.supportsMenu){
air.NativeApplication.nativeApplication.menu = createRootMenu();
}
When AIR supports dock icons on an operating system, the static air.NativeApplication.supportsDockIcon is true. The dock icon is represented by the air.NativeApplication.nativeApplication.icon property. The icon object is created automatically.
Mac OS X provides a default menu for the dock icon. You can add additional items to the dock menu by adding the items to a NativeMenu object and assigning it to the icon.menu property.
if(air.NativeApplication.supportsDockIcon){
air.NativeApplication.nativeApplication.icon.menu = createRootMenu();
var dockIconLoader = new runtime.flash.display.Loader();
dockIconLoader.contentLoaderInfo.addEventListener(air.Event.COMPLETE, iconLoadComplete);
dockIconLoader.load(new air.URLRequest("icons/AIRApp_128.png"));
}
To load the images for the icon, use the air.Loader class. This class loads the image given an air.URLRequest object containing the URL string of the image. Because the loader is asynchronous, an event listener must be added to the contentLoaderInfo property of the loader object to detect when the image file has completed loading. The handler for the event assigns the loaded image to the icon by setting the icon.bitmaps property.
var iconLoadComplete = function(event){
air.NativeApplication.nativeApplication.icon.bitmaps = new runtime.Array(event.target.content.bitmapData);
}
There is no direct way to get a BitmapData object from an image loaded by an HTML page. You can, however, use the src attribute of an img element to reload the image using the air.Loader class.
When AIR supports window menus on an operating system, the static NativeWindow.supportsMenu property is true. No default window menu is provided by the Windows operating system, so you must assign a new menu object to the native window menu property:
if(air.NativeWindow.supportsMenu){
window.nativeWindow.menu = createRootMenu();
}
When AIR supports system tray icons on an operating system, the static air.NativeApplication.supportsSystemTrayIcon is true. The system tray icon is represented by the air.NativeApplication.nativeApplication.icon> property. The icon object is created automatically. To show the icon in the notification area of the taskbar, you only need to assign an array containing the icon image to the icon bitmaps property. To remove the icon from the taskbar, set bitmaps to an empty array.
Add a menu to the system tray icon by assigning a NativeMenu object to the icon.menu property.
if(air.NativeApplication.supportsSystemTrayIcon){
air.NativeApplication.nativeApplication.icon.tooltip = "AIR Menus";
air.NativeApplication.nativeApplication.icon.menu = createRootMenu();
var systrayIconLoader = new runtime.flash.display.Loader();
systrayIconLoader.contentLoaderInfo.addEventListener(air.Event.COMPLETE, iconLoadComplete);
systrayIconLoader.load(new air.URLRequest("icons/AIRApp_16.png"));
}
Be careful about using SystemTrayIcon properties on the wrong operating system. On Mac OS X, for example, the air.NativeApplication.nativeApplication.icon object is of type, DockIcon. Attempting to set the tooltip would generate a runtime error.
The icon image for the system tray icon is set by the iconLoadComplete() function in the same way as a dock icon.
Menus can be displayed anywhere over a window by calling the display() method of the NativeMenu object. The stage parameter must be set to the stage property of the nativeWindow which displays the menu (which will almost always be the window displaying the HTML page). The position parameters specify where, relative to the top-left-hand corner of the window, to display the menu. The clientX and clientY properties of a mouse event are a convenient place to get the coordinates of the mouse when opening a menu in response to a mouse event.
function popUpMenu(event){
popUp.display(window.nativeWindow.stage, event.clientX, event.clientY);
}
A pop-up menu can have commands, submenus, and separators in the root menu.
You can display a context menu for an HTML element by responding to the oncontextmenu event.
<div oncontextmenu="showContextMenu(event)" style="-khtml-user-select:auto;">
You can display a native menu with the display() method of the menu object, or you can use a DHTML menu.
Images and text selections have a default context menu in AIR. If you display your own context menus, you should call the preventDefault() method of the oncontextmenu event to stop the default menu from popping up. The AIR Menus example has two paragraphs which have context menus. One displays the default menu; the other the custom menu. The rest of the page elements disallow text selections by setting the style, -khtml-user-select:none; so a context menu cannot be opened.
The custom context menu is displayed with the following function:
function showContextMenu(event){
event.preventDefault();
window.htmlLoader.contextMenu.display(window.nativeWindow.stage, event.clientX, event.clientY);
}
Menu items dispatch a select event when they are selected by the user. The AIR Menus example uses the same event handler for every item. To add an event listener, call the addEventListener() method of the item:
item.addEventListener(air.Event.SELECT,itemSelected);
Select events also bubble up through the menu hierarchy. Each parent menu in the chain also dispatches a select event. The target property of the event object is the NativeMenuItem object of the selected command; the currentTarget property is the NativeMenu object of the current menu.
This example responds to each select event by adding a line describing the event to the eventLog section of the page.
function itemSelected(event){
var message = "Selected item: \"" + event.target.label + "\" in " + event.target.data + ".";
air.trace(message);
newEntry = document.createElement('p');
newEntry.appendChild(document.createTextNode(message));
eventLog.appendChild(newEntry);
}
Also available, but not used in this example are menu displaying events. A displaying event is dispatched by a menu just before it is shown. You can use displaying events to update the items in the menu to reflect the current state of the application. For example, if your application used a menu to let users open recently viewed documents, you could update the menu to reflect the current list of documents.