package com.avila.ui { import flash.display.InteractiveObject; import flash.events.EventDispatcher; import flash.events.KeyboardEvent; import flash.utils.Dictionary; import com.avila.events.KeyComboEvent; /** * Given an interactive object a key combo dispatcher will listen to all * key events that pass through it, and dispatch KeyComboEvent events for * every combination of keys successfully pressed which have been set using addKeyCombo() * * @author Michael Avila */ public class KeyComboDispatcher extends EventDispatcher { private var _owner:InteractiveObject; public function get owner():InteractiveObject { return _owner; } private var keyCombinations:Dictionary; private var keyCombinationMap:Dictionary; private var keysPressed:Array; /** * Creates a new KeyComboDispatcher. * * @param The interactive object witch owns this dispatcher. */ public function KeyComboDispatcher( owner:InteractiveObject ) { _owner = owner; configureListeners(); keyCombinations = new Dictionary(); keyCombinationMap = new Dictionary(); keysPressed = new Array(); } /** * Sets a key combination which can trigger a KeyComboEvent. * * @param name The name given to the combination. * @param keyCodes An array of the key codes in the order which they need to be pressed in order to trigger a KeyComboEvent. */ public function addKeyCombo( name:String, ... keyCodes ):void { if ( keyCombinationMap[ name ] != null ) { throw new Error( "A keycombo already exists with that name." ); return; } keyCombinationMap[ name ] = keyCodes; // store the array of keycodes in the map under the name of the combo keyCombinations[ keyCodes.join( "" ) ] = name; // store the name of the keycodes in the combinations as the keys joined (ie 165745) } /** * Removes the key combination with the given name. * * @param name The name of the key combination which you'd like to remove. */ public function removeKeyCombo( name:String ):void { // grab the key code list from the map using the name var keyCodes:Array = keyCombinationMap[ name ]; // nulllllify the combination keyCombinations[ keyCodes.join( "" ) ] = null; keyCombinationMap[ name ] = null; } // check to see if we have marked private function checkForCombination():void { var comboName:String = keyCombinations[ keysPressed.join( "" ) ]; if ( comboName != null ) { dispatchEvent( new KeyComboEvent( KeyComboEvent.KEY_COMBO, comboName, keysPressed.slice(0) ) ); } } // When a key is pressed add it onto the keys pressed array private function onKeyDown( event:KeyboardEvent ):void { // store and check the index, this is to prevent holding the key // and it continuously getting added var index:int = keysPressed.indexOf( event.keyCode ); if ( index == -1 ) { keysPressed.push( event.keyCode ); // check to see if this results in a combination being dispatched checkForCombination(); } } // When a key is released remove it and everything that was pressed // after it from the keys pressed array private function onKeyUp( event:KeyboardEvent ):void { var index:int = keysPressed.indexOf( event.keyCode ); keysPressed.splice( index, keysPressed.length - index ); } // listen for keyUp, keyDown events private function configureListeners():void { owner.addEventListener( KeyboardEvent.KEY_DOWN, onKeyDown ); owner.addEventListener( KeyboardEvent.KEY_UP, onKeyUp ); } } }