Adobe Flex 3 Help

Specifying menu item keyboard equivalents

You can specify a key equivalent (sometimes called an accelerator) for a menu command. When the key or key combination is pressed the FlexNativeMenu dispatches an itemClick event, as though the user had selected the menu item. The key equivalent string is automatically displayed beside the menu item name in the menu. The format depends on the user's operating system and system preferences. In order for the command to be invoked, the menu containing the command must be part of the application menu (OS X) or the window menu of the active window (Windows).

Note: Key equivalents are only triggered for application and window menus. If you add a key equivalent to a context or pop-up menu, the key equivalent is displayed in the menu label but the associated menu command is never invoked.

Contents

About key equivalents

A key equivalent consists of two parts:

Primary key 

A string containing the character that serves as the key equivalent. If a data provider object has a keyEquivalent field, the DefaultDataDescriptor automatically uses that value as the key equivalent. You can specify an alternative data provider field by setting the FlexNativeMenu component's keyEquivalentField property. You can specify a function to use to determine the key equivalent by setting the FlexNativeMenu component's keyEquivalentFunction property.



Modifier keys 

One or more modifier keys that are also part of the key equivalent combination, such as the control key, shift key, command key, and so forth. If a data provider item includes an altKey, cmdKey, ctrlKey, or shiftKey object field or XML attribute set to true, the specified key or keys become part of the key equivalent combination, and the entire key combination must be pressed to trigger the command. Alternatively, you can specify a function for the FlexNativeMenu component's keyEquivalentModifiersFunction, and that function is called to determine the key equivalent modifiers for each data provider item.



If you specify more than one key equivalent modifier, all the specified modifiers must be pressed in order to trigger the command. For instance, for the menu item generated from the following XML the key equivalent combination is Control+Shift+A (rather than Control+A OR Shift+A):

<menuitem label="Select All" keyEquivalent="a" ctrlKey="true" shiftKey="true"/>

Note that this can result in impossible key combinations, if the menu item specifies multiple modifiers that are only available on one operating system. For example, the following item results in a menu item with the key equivalent Command-Shift-G:

<menuitem label="Ungroup" keyEquivalent="g" cmdKey="true" shiftKey="true"/>

On OS X this command works as expected. On Windows the key equivalent Shift+G is displayed in the menu. However, pressing Shift+G does not trigger the command because the Command key is still considered a required part of the command, even though that key doesn't exist in Windows.

To use different key combinations for the same menu item on different platforms, you can specify a keyEquivalentModifiersFunction function for the FlexNativeMenu instance. This function can provide alternative logic for processing the menu item data. For an example using the keyEquivalentModifiersFunction, see Example: Using custom logic for multi-platform key equivalent menu commands.

Example: FlexNativeMenu key equivalent commands

The following example uses a FlexNativeMenu to define a menu that includes keyboard equivalents for the menu commands. Note that, while this example only uses keys and modifier keys that are available on Windows and Mac OS X, it uses the Control key as a modifier on both platforms. However, the Command key would be more in line with the common convention on Mac OS X. For an example that uses the keyEquivalentModifiersFunction property to create menus that use the common cross-platform conventions, see Example: Using custom logic for multi-platform key equivalent menu commands.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:menu>
        <mx:FlexNativeMenu dataProvider="{menuData}" 
            labelField="@label" 
            keyEquivalentField="@keyEquivalent" 
            showRoot="false" 
            itemClick="trace('click:', event.label);"/>
    </mx:menu>
    <mx:XML format="e4x" id="menuData">
        <root>
            <menuitem label="File">
                <menuitem label="New" keyEquivalent="n" ctrlKey="true"/>
                <menuitem label="Open" keyEquivalent="o" ctrlKey="true"/>
                <menuitem label="Save" keyEquivalent="s" ctrlKey="true"/>
                <menuitem label="Save As..." keyEquivalent="s" ctrlKey="true" shiftKey="true"/>
                <menuitem label="Close" keyEquivalent="w" ctrlKey="true"/>
            </menuitem>
            <menuitem label="Edit">
                <menuitem label="Cut" keyEquivalent="x" ctrlKey="true"/>
                <menuitem label="Copy" keyEquivalent="c" ctrlKey="true"/>
                <menuitem label="Paste" keyEquivalent="v" ctrlKey="true"/>
            </menuitem>
        </root>
    </mx:XML>
</mx:WindowedApplication>

Example: Using custom logic for multi-platform key equivalent menu commands

The following example creates the same menu structure as the previous example. However, instead of using the same keyboard combination (for example, Control-O) regardless of the user's operating system, in this example a keyEquivalentModifiersFunction function is defined for the FlexNativeMenu. The function is used to create keyboard equivalents that follow platform conventions by using the Control key on Windows but substituting the Command key on Mac OS X. In the data provider data, the ctrlKey="true" attribute is still used. The function that determines the key equivalent modifiers uses the value of the ctrlKey field or XML attribute to specify the Control key on Windows and the Command key on OS X, and if the ctrlKey attribute is false (or not specified) then neither modifier is applied.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" 
    initialize="init();">
    
    <mx:menu>
        <mx:FlexNativeMenu dataProvider="{menuData}" 
            labelField="@label" 
            keyEquivalentField="@keyEquivalent" 
            keyEquivalentModifiersFunction="keyEquivalentModifiers" 
            showRoot="false" 
            itemClick="trace('click:', event.label);"/>
    </mx:menu>
    <mx:Script>
        <![CDATA[
            import flash.system.Capabilities;
            import flash.ui.Keyboard;
            
            private var isWin:Boolean;
            private var isMac:Boolean;
            
            private function init():void
            {
                isWin = (Capabilities.os.indexOf("Windows") >= 0);
                isMac = (Capabilities.os.indexOf("Mac OS") >= 0);
            }
                
            private function keyEquivalentModifiers(item:Object):Array
            {
                var result:Array = new Array();
                
                var keyEquivField:String = menu.keyEquivalentField;
                var altKeyField:String;
                var ctrlKeyField:String;
                var shiftKeyField:String;
                if (item is XML)
                {
                    altKeyField = "@altKey";
                    ctrlKeyField = "@ctrlKey";
                    shiftKeyField = "@shiftKey";
                }
                else if (item is Object)
                {
                    altKeyField = "altKey";
                    ctrlKeyField = "ctrlKey";
                    shiftKeyField = "shiftKey";
                }
                
                if (item[keyEquivField] == null || item[keyEquivField].length == 0)
                {
                    return result;
                }
                
                if (item[altKeyField] != null && item[altKeyField] == true)
                {
                    if (isWin)
                    {
                        result.push(Keyboard.ALTERNATE);
                    }
                }
                
                if (item[ctrlKeyField] != null && item[ctrlKeyField] == true)
                {
                    if (isWin)
                    {
                        result.push(Keyboard.CONTROL);
                    }
                    else if (isMac)
                    {
                        result.push(Keyboard.COMMAND);
                    }
                }
                
                if (item[shiftKeyField] != null && item[shiftKeyField] == true)
                {
                    result.push(Keyboard.SHIFT);
                }
                
                return result;
            }
        ]]>
    </mx:Script>
    <mx:XML format="e4x" id="menuData">
        <root>
            <menuitem label="File">
                <menuitem label="New" keyEquivalent="n" ctrlKey="true"/>
                <menuitem label="Open" keyEquivalent="o" ctrlKey="true"/>
                <menuitem label="Save" keyEquivalent="s" ctrlKey="true"/>
                <menuitem label="Save As..." 
                    keyEquivalent="s" 
                    ctrlKey="true" 
                    shiftKey="true"/>
                <menuitem label="Close" keyEquivalent="w" ctrlKey="true"/>
            </menuitem>
            <menuitem label="Edit">
                <menuitem label="Cut" keyEquivalent="x" ctrlKey="true"/>
                <menuitem label="Copy" keyEquivalent="c" ctrlKey="true"/>
                <menuitem label="Paste" keyEquivalent="v" ctrlKey="true"/>
            </menuitem>
        </root>
    </mx:XML>
</mx:WindowedApplication>