Custom context menu with keyboard shortcuts in Flash

I was very pleased that Strictly Sudoku was Adobe’s Site of the Day last Friday. In creating the site, the aim was to make the best sudoku site on the web and this award suggests I have gone some way towards that.

I wanted the sudoku game in this site to be as simple as possible to use and to that end I implemented a context menu (accessed via right-click in Windows and control-click in Mac OS) that contained most of the command options, along with keyboard shortcuts for many of these commands. This supplements any buttons that may be available.

The Flash Player already has a context menu, but this can be modified to remove some of the default options and to add your own options.

To modify the context menu you have to create a new ContextMenu object and modify that. I chose to extend the context menu with my own class and use that to modify the menu as follows.

class SudokuMenu extends ContextMenu
{
    public function SudokuMenu()
    {
        super( onSelect );
        hideBuiltInItems();

        customItems.length = 0;
        customItems.push( new MenuPen() );
        customItems.push( new MenuHowDoing() );
        customItems.push( new MenuPause() );
        customItems.push( new MenuPrint() );
        customItems.push( new MenuRestart() );
        customItems.push( new MenuShowSolution() );
        customItems.push( new MenuSpinner() );
        customItems.push( new MenuTimer() );
        customItems.push( new MenuErrorCells() );
        customItems.push( new MenuAbout() );
    }

    public function onSelect( obj:Object, menu:ContextMenu ):Void
    {
        for( var i:String in customItems )
        {
            customItems[i].Prepare();
        }
    }
}

First we call the parent constructor passing it the method to call when the user right-clicks to display the menu. This method will be used to prepare the menu items for display.

hideBuiltInItems() is used to clear out the default menu items. You can’t clear them all but this will clear most of them leaving just the Settings and About Flash Player items.

I then clear any custom items by setting the length of the customItems array to zero.

The customItems array holds any custom items we want in our menu so the next few lines push all the custom items into this array.

Finally, the onSelect method is called when the user right clicks in the flash movie – just before the menu is displayed. This lets us customise the menu for viewing. So, in the onSelect we call the Prepare method of each menu item.

Every custom menu item extends Flash’s ContextMenuItem class. The pause menu item looks like this.

class MenuPause extends ContextMenuItem
{
    public function MenuPause()
    {
        super( "Options    esc", onSelect );
        Key.addListener( this );
    }

    public function onSelect():Void
    {
        _global.sudokuManager.TogglePause();
    }

    public function Prepare():Void
    {
        if( _global.sudokuManager.IsPaused() )
        {
            caption = "Resume    esc";
        }
        else
        {
            caption = "Options    esc";
        }
    }

    public function onKeyDown():Void
    {
        if( Key.getCode() == Key.ESCAPE )
        {
            onSelect();
        }
    }
}

All items in the context menu must be ContextMenuItem objects, so my MenuPause class extends this class to add additional functionality.

The constructor calls it’s parent object’s constructor with the default menu caption and the method which should be called when the menu item is selected. The caption contains the keyboard shortcut code separated from the caption by a tab – this pushes the keyboard shortcut to align right in the menu display.

Also, in the constructor I add this object as a listener to the keyboard so I can catch the keyboard shortcut.

The onSelect function is called when the menu item is selected so this contains the necessary code to pause or unpause the game.

The prepare method is called from the SudokuMenu object above just before displayingteh menu. The pause item checks whether the game is currently paused and sets its caption to Options or Resume accordingly.

Finally, the onKeyDown method checks whether the keyboard shortcut for this option was pressed and if so it calls the onSelect method to do the appropriate action for this menu item.

And that’s it. All the other menu items are implemented in a similar manner. The result is a more flexible interface that can be seen on the Strictly Sudoku site.