Flex Menu Accelerators
An experiment in placing accelerators into a Flex MenuBar, and dynamically generating key handlers to trigger the menu events.
Flex MenuBars are lacking several features that are standard on most other platforms. The most glaring of these is that lack of support for displaying accelerators (shortcut key combos like Ctrl+N for opening a new file). After hunting around on the internet a bit, I came across some sample code by Campbell Anderson which uses the Menu's icon to display an accelerator. This is a step in the right direction, but the icons in a Flex Menu show up on the left side which is opposite of both Windows and Mac standards. I wrote my own class which overrides some of MenuItemRenderer's layout logic in order to place the icon on the right. (Scroll to the bottom for the source.) Now we can write a menu dataProvider that looks like this:

... and get a menu that looks like this:

It's a good start, but I wanted to take it a step further. Once you put together a bunch of accelerators, your key handler that listens to all of the accelerators is going to become a giant mess. Wouldn't it be nice if your app automatically listened for all accelerator events and utilized the same handler function that you already wrote for your menu?
Enter: the Accelerator class
My solution was to create a class that encapsulates an accelerator (e.g. control key plus the letter 'Z') and generate a list of all accelerators directly from the Menu's dataProvider. Notice that I am also storing the 'data' attribute from the menu xml... we'll be needing that later.

Under the hood, the Accelerator class basically splits the string by '+' and pulls out each component. It also has a handy little method called test() which accepts a KeyboardEvent, and checks to see if the event matches the accelerator.
Finally, I added a KEY_UP listener to the application that tests each accelerator, and if there is a match -- we can use that 'data' variable that we stored earlier to call the SAME handler that would have been called if the user clicked that menu item!

But - here's the down side...
Some browsers may trap certain key combos before they ever reach the Flash player. This means that - as far as I know - combos like Ctrl-N and Ctrl-S are out. You may have better luck in a standalone or projector player, but I haven't tested it. Also - It seems that you have to click on the movie to give it focus before it begins capturing key events. This is a bit disappointing, but there seem to be quite a few options still available. Maybe use Shift in place of Ctrl?
So, was this a failure? You be the judge... a nice by-product of this experiment though was the KeyUtils class which does conversions between strings and keyCodes - similar to what you can do with String.fromCharCode() and String.charCodeAt().
Check it out:
In this application, clicking on menu items just displays a message indicating which item was clicked. Try hitting some of the accelerator combos - you should get the same message you got when you clicked the item (its calling the same function.) Remember that you have to click on the app to give it focus first. Notice that the accelerators are compatible with 'check' and 'radio' types, and also items that branch. The only feature that you can't use is the icon, since it is getting used to display the accelerator.
Update:
In response to Steve's question below - here is an example which underlines characters in the menu item's label. An ampersand preceding the character indicates that it should be underlined, and because this is XML we have to XML encode the ampersand.

About this entry
You’re currently reading “Flex Menu Accelerators,” an entry by Ryan Phelan
- Published:
- 03.17.08 / 1am
- Category:
- Flex






22 Comments
Jump to comment form | comments rss [?] | trackback uri [?]