In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: forked from: forked from: SiON 88 Key Keyboard

/**
 * Copyright ShutheSL ( http://wonderfl.net/user/ShutheSL )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/lbrm
 */

// forked from aobyrne's forked from: forked from: SiON 88 Key Keyboard
// forked from tkinjo's SiON 88 Key Keyboard
package 
{
    import com.bit101.components.HBox;
    import com.bit101.components.HUISlider;
    import com.bit101.components.PushButton;
    import flash.display.*;
    import flash.events.*;
    import flash.media.Sound;
    import org.si.sion.SiONDriver;
    import org.si.sion.SiONVoice;
    import org.si.sion.utils.SiONPresetVoice;
    
    [SWF(frameRate="60")] 
    /**
     * ...
     * @author tkinjo
     */
    public class SionPiano extends Sprite 
    {
        static public const STATE_STILL:String = "stateStill";
        static public const STATE_MOVING:String = "stateMoving";
        private var driver:SiONDriver = new SiONDriver();
        private var presetVoice:SiONPresetVoice = new SiONPresetVoice();
        private var voice:SiONVoice;
        
        private var keyboard:MusicalKeyboard;
        
        private var presetSelectPanel:PresetSelectPanel;
        static private var console:Console;
        private var counter:uint;
        private var counterPeriod:uint=15;
        private var scaleNum:uint = 60;
        private var isFirst:Boolean=true;
        private var index:uint;
        private var state:String;
        
        public function SionPiano():void 
        {
            stage.align = StageAlign.TOP;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            //addChild( settingPannel );
            console =          new Console(this);
            
            
            keyboard = new MusicalKeyboard( 8, 40 );
            addChild( keyboard );
            
            keyboard.addEventListener(MusicalKeyEvent.PRESS, keybaordPressHandler);
            //keyboard.addEventListener(MusicalKeyEvent.RELEASE, keybaordReleaseHandler);
            
            voice = presetVoice["sine"];
            driver.play();
            
            //stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
            addEventListener(Event.ENTER_FRAME, enterFrameHandler2);
            var hBox:HBox =          new HBox(this, 0, 370);
            new PushButton(hBox, 0, 0, 'stop', doStop);
            new PushButton(hBox, 0, 0, 'play', doContinue);
            var hUISlider:HUISlider = new HUISlider(hBox, 0, 0, "speed", doChangeSpeed);
            hUISlider.minimum = 1;
            hUISlider.maximum = 20;
            hUISlider.tick = 1;
            hUISlider.value = counterPeriod;
            
            
            presetSelectPanel = new PresetSelectPanel( presetVoice, this, 10, 10, 465 - 20, 360);
            presetSelectPanel.addEventListener(Event.CHANGE, presetChangeHandler);
            presetSelectPanel.signal.add(doChangeCategory);
            
            state = STATE_MOVING;
            switch (state) 
            {
                case STATE_MOVING:
                    keyboard.visible = false;
                break;
                default:
                    
                break;
            }
            
            presetSelectPanel.selectRandom();
        }
        
        private function doChangeSpeed(e:Event):void 
        {
            counterPeriod = HUISlider(e.target).value
        }
        
        private function doStop(e:Event):void 
        {
            state = STATE_STILL
            driver.stop();
            driver.play();
            keyboard.visible = true;
        }
        private function doContinue(e:Event):void 
        {
            state = STATE_MOVING;
            keyboard.visible = false;
        }
        
        private function doChangeCategory():void 
        {
            presetSelectPanel.selectedCategory++;
            cTrace( "presetSelectPanel.selectedCategory : " + presetSelectPanel.selectedCategory );
        }
        
        private function enterFrameHandler2(e:Event):void 
        {
            removeEventListener(Event.ENTER_FRAME, enterFrameHandler2);
            keyboard.paint();
            keyboard.x = ( 465 - keyboard.width ) / 2;
            keyboard.y = 465 - keyboard.x - keyboard.height;
            keyboard.scaleX = keyboard.scaleY = 2;
        }
        
        private function keybaordPressHandler( event:MusicalKeyEvent ):void {
            
            var keyType:MusicalKeyType = event.keyType;
            cTrace( "Trace.traceObject(keyType) : " + Trace.traceObject(keyType) );
            driver.noteOn( keyType.note, voice );
            cTrace( "keyType.note : ----->" + keyType.note );
        }
        
        /*
        private function keybaordReleaseHandler( event:MusicalKeyEvent ):void {
            
            var keyType:MusicalKeyType = event.keyType;
            driver.noteOff( keyType.note );
        }
        
        private function mouseUpHandler( event:MouseEvent ):void {
            
            for ( var i:uint = 0; i < 128; i++ )
                driver.noteOff( i );
        }
        //*/
        private function enterFrameHandler( event:Event ):void {
            
            var pressedKeyNotes:Vector.<Boolean> = keyboard.pressedKeyNotes;
            var pressedKeyNotesLength:int = pressedKeyNotes.length;
            
            switch (state) 
            {
                case STATE_STILL:
                    for ( var i:uint = 0; i < pressedKeyNotesLength; i++ )
                        if( !pressedKeyNotes[ i ] )
                            driver.noteOff( i );
                break;
                case STATE_MOVING:
                    if (counter%counterPeriod==0) 
                    {
                        index = scaleNum == 60?60 + 11: scaleNum - 1;
                        if (isFirst) 
                        {
                            isFirst = false;
                        }
                        else
                        {
                            doNoteOff();
                        }
                        driver.noteOn(scaleNum, voice);
                        scaleNum++;
                        if (scaleNum>60+11) 
                        {
                            scaleNum = 60;
                            presetSelectPanel.selectedVoiceIndex++;
                            cTrace( "presetSelectPanel.selectedVoiceIndex : " + presetSelectPanel.selectedVoiceIndex );
                        }
                    }
                    counter++
                break;
                default:
                    
                break;
            }
        }
        
        private function doNoteOff():void 
        {
            driver.noteOff(index);
        }
        
        
        private function presetChangeHandler( event:Event ):void {
            
            voice = presetSelectPanel.selectedVoice;
        }
        private function cTrace(msg:String):void 
        {
            traceIt(msg);
        }
        static public function traceIt(msg:String):void 
        {
            console.traceThis(msg)
            
        }
    }
}

import com.bit101.components.Component;
import com.bit101.components.ListItem;
import com.bit101.components.Panel;
import com.bit101.components.PushButton;
import com.bit101.components.TextArea;
import com.bit101.components.VBox;
import com.bit101.components.VScrollBar;
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.text.TextField;
import flash.ui.Keyboard;
import flash.utils.describeType;
import idv.cjcat.signals.ISignal;
import idv.cjcat.signals.Signal;
import org.si.sion.*;
import org.si.sion.utils.*;

class PresetSelectPanel extends Panel {
    
    /**
     * ...
     * @eventType flash.events.Event.CHANGE
     */
    [Event(name = "change", type = "Event")] 
    
    private var _selectedVoice:SiONVoice;
    public function get selectedVoice():SiONVoice { return _selectedVoice; }
    
    private var voiceList:List;
    private var categoryList:List;
    private var presetVoice:SiONPresetVoice;
    public var signal:Signal;
    
    public function PresetSelectPanel( presetVoice:SiONPresetVoice, parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, width:Number = 100, height:Number = 100 ):void {
        
        super( parent, xpos, ypos );
        
        this.presetVoice = presetVoice;
        this.width = width;
        this.height = height;
        
        categoryList = new List( this, 10, 10 );
        categoryList.width = width / 2 - 15;
        categoryList.height = height - 20;
        for each ( var category:Array in presetVoice.categolies ) 
            categoryList.addItem( category[ "name" ] );
        
        categoryList.selectedIndex = 0;
        categoryList.addEventListener(Event.SELECT, categoryListSelectHandler);
        
        
        
        voiceList = new List( this, categoryList.width + 20, 10 );
        voiceList.width = categoryList.width;
        voiceList.height = categoryList.height;
        
        voiceListUpdate();
        
        voiceList.selectedIndex = 0;
        voiceList.addEventListener(Event.SELECT, voiceListSelectHandler);
        
        
        
        setSelectedVoice();
        signal = new Signal();
    }
    
    public function selectRandom():void 
    {
        categoryList.selectedIndex = int(categoryList.items.length * Math.random());
    }
    
    private function voiceListUpdate():void {
        
        voiceList.items = new Array();
        
        /*
        for each ( var voice:SiONVoice in presetVoice[ categoryList.selectedItem ] ) 
            voiceList.addItem( voice.name );
        //*/
        
        //*
        var voices:Array = presetVoice[ categoryList.selectedItem ];
        var voicesLength:uint = presetVoice[ categoryList.selectedItem ].length;
        for ( var i:uint = 0; i < voicesLength; i++ ) 
            voiceList.addItem( voices[ i ].name );
        //*/
    }
    
    private function categoryListSelectHandler( event:Event ):void {
        
        voiceListUpdate();
        
        voiceList.selectedIndex = 0;
        setSelectedVoice();
    }
    
    private function voiceListSelectHandler( event:Event ):void {
        
        setSelectedVoice();
    }
    
    private function setSelectedVoice():void {
        
        _selectedVoice = presetVoice[ categoryList.selectedItem ][ voiceList.selectedIndex ];
        dispatchEvent( new Event(Event.CHANGE) );
    }
    public function set selectedCategory(value:uint):void 
    {
        if (categoryList.items.length<value) 
        {
            return;
        }
        categoryList.selectedIndex = value;
        voiceList.selectedIndex = 0;
        voiceListUpdate();
    }
    public function get selectedCategory():uint { return categoryList.selectedIndex; }
    public function set selectedVoiceIndex(value:uint):void 
    {
        if (voiceList.items.length<=value) 
        {
            cTrace('---------');
            signal.dispatch();
            return;
        }
        voiceList.selectedIndex = value;
        
    }
    
    private function cTrace(arg1:String):void 
    {
        SionPiano.traceIt(arg1);
    }
    public function get selectedVoiceIndex():uint { return voiceList.selectedIndex; }
}

class MusicalKey extends Sprite {
    
    /**
     * ...
     * @eventType MusicalKeyEvent.PRESS
     */
    [Event(name = "press", type = "MusicalKeyEvent")] 
    
    /**
     * ...
     * @eventType MusicalKeyEvent.RELEASE
     */
    [Event(name = "release", type = "MusicalKeyEvent")] 
    
    private var _type:MusicalKeyType;
    public function get type():MusicalKeyType { return _type; }
    
    private var _width:Number = 0;
    override public function set width(value:Number):void 
    {
        _width = value;
        paint();
    }
    override public function get width():Number { return _width; }
    
    private var _height:Number = 0;
    override public function set height(value:Number):void 
    {
        _height = value;
        paint();
    }
    override public function get height():Number { return _height; }
    
    private var mouseOver:Boolean = false;
    private var mouseDown:Boolean = false;
    
    public function MusicalKey( type:MusicalKeyType, width:Number, height:Number ):void {
        
        _type = type;
        this.width = width;
        this.height = height;
        
        addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
        addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
        addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
    }
    
    private function paint():void {
        
        if ( !( width && height ) )
            return;
        
        graphics.clear();
        graphics.lineStyle( 1 );
        
        if ( mouseDown )
            graphics.beginFill( 0xffcccc );
        
        else if ( mouseOver )
            graphics.beginFill( 0xccccff );
        
        else if ( type.color == MusicalKeyType.COLOR_WHITE )
            graphics.beginFill( 0xffffff );
        
        else 
            graphics.beginFill( 0x666666 );
        
        graphics.drawRect( 0, 0, width, height );
        graphics.endFill();
    }
    
    private function mouseOverHandler( event:MouseEvent ):void {
        
        if ( event.buttonDown )
            mouseDown = true;
        
        mouseOver = true;
        paint();
        
        if( event.buttonDown ) 
            dispatchEvent( new MusicalKeyEvent( MusicalKeyEvent.PRESS, type ) );
    }
    
    private function mouseOutHandler( event:MouseEvent ):void {
        
        mouseOver = false;
        mouseDown = false;
        paint();
        
        if( event.buttonDown ) 
            dispatchEvent( new MusicalKeyEvent( MusicalKeyEvent.RELEASE, type ) );
    }
    
    private function mouseDownHandler( event:MouseEvent ):void {
        
        mouseDown = true;
        paint();
        
        dispatchEvent( new MusicalKeyEvent( MusicalKeyEvent.PRESS, type ) );
    }
    
    private function mouseUpHandler( event:MouseEvent ):void {
        
        mouseDown = false;
        paint();
        
        dispatchEvent( new MusicalKeyEvent( MusicalKeyEvent.RELEASE, type ) );
    }
}

class MusicalKeyEvent extends Event {
    
    public static const PRESS:String = "press";
    public static const RELEASE:String = "release";
    
    private var _keyType:MusicalKeyType;
    public function get keyType():MusicalKeyType { return _keyType; }
    
    public function MusicalKeyEvent( type:String, keyType:MusicalKeyType, bubbles:Boolean = false, cancelable:Boolean = false ):void {
        
        super( type, bubbles, cancelable );
        
        _keyType = keyType;
    }
}

class MusicalKeyboard extends Sprite {
    
    /**
     * ...
     * @eventType MusicalKeyEvent.PRESS
     */
    [Event(name = "press", type = "MusicalKeyEvent")] 
    
    /**
     * ...
     * @eventType MusicalKeyEvent.RELEASE
     */
    [Event(name = "release", type = "MusicalKeyEvent")] 
    
    private var numKey:uint;
    private var keyOffset:uint;
    
    private var keyWidth:uint;
    private var keyHeight:uint;

    private function get numWhiteKey():uint {
        
        var numWhiteKey:uint = 0;
        
        for ( var i:uint = 0; i < numKey; i++ )
            if ( MusicalKeyType.getKeyColor( ( i + keyOffset ) % 12 ) == MusicalKeyType.COLOR_WHITE )
                numWhiteKey++;
        
        return numWhiteKey;
    }
    
    private var _pressedKeyNotes:Vector.<Boolean> = new Vector.<Boolean>( 128 );
    public function get pressedKeyNotes():Vector.<Boolean> { return _pressedKeyNotes; }
    
    public function MusicalKeyboard( keyWidth:uint, keyHeight:uint, numKey:uint = 88, keyOffset:uint = 9 ):void 
    {
        cTrace( "MusicalKeyboard : " + MusicalKeyboard );
        this.numKey = numKey;
        this.keyOffset = keyOffset;
        
        this.keyWidth = keyWidth;
        if ( keyWidth % 2 )
            keyWidth--;
        
        this.keyHeight = keyHeight;
        if ( keyHeight % 2 )
            keyHeight--;
        //paint();
    }
    
    public function paint():void {
        
        graphics.lineStyle( 1 );
        
        var keyOffsetX:uint = getKeyOffsetX( keyOffset );
        
        var octaveNum:uint;
        var scaleNum:uint;
        var octaveX:Number
        var i:uint;
        var key:MusicalKey;
        for ( i = 0; i < numKey; i++ ) {
            
            scaleNum = ( i + keyOffset ) % 12;
            //cTrace( "scaleNum : " + scaleNum );
            if ( MusicalKeyType.getKeyColor( scaleNum ) != MusicalKeyType.COLOR_WHITE )
                continue;
            
            octaveNum = ( i + keyOffset ) / 12;
            //cTrace( "octaveNum : " + octaveNum );
            key = new MusicalKey( new MusicalKeyType( scaleNum, octaveNum ), keyWidth, keyHeight );
            
            
            octaveX = octaveNum * keyWidth * 7;
            
            key.x = octaveX + getWhiteKeyX( MusicalKeyType.getKeyColorNum( scaleNum ) ) - keyOffsetX;
            addChild( key );
            
            key.addEventListener(MusicalKeyEvent.PRESS, keyPressHandler);
            key.addEventListener(MusicalKeyEvent.RELEASE, keyReleaseHandler);
        }
        
        for ( i = 0; i < numKey; i++ ) {
            
            scaleNum = ( i + keyOffset ) % 12;
            
            if ( MusicalKeyType.getKeyColor( scaleNum ) != MusicalKeyType.COLOR_BLACK )
                continue;
            
            octaveNum = ( i + keyOffset ) / 12;
            key = new MusicalKey( new MusicalKeyType( scaleNum, octaveNum ), keyWidth, keyHeight / 2 );
            
            
            
            octaveX = octaveNum * keyWidth * 7;
            
            key.x = octaveX + getBlackKeyX( MusicalKeyType.getKeyColorNum( scaleNum ) ) - keyOffsetX;
            addChild( key );
            
            key.addEventListener(MusicalKeyEvent.PRESS, keyPressHandler);
            key.addEventListener(MusicalKeyEvent.RELEASE, keyReleaseHandler);
        }
    }
    
    private function getKeyOffsetX( offset:uint ):Number {
        
        var keyColorNum:uint = MusicalKeyType.getKeyColorNum( offset );
        return MusicalKeyType.getKeyColor( offset ) == MusicalKeyType.COLOR_WHITE ? getWhiteKeyX( keyColorNum ) : getBlackKeyX( keyColorNum );
    }
    
    protected function getWhiteKeyX( scaleNum:uint ):Number {
        
        return keyWidth * scaleNum;
    }
    
    protected function getBlackKeyX( scaleNum:uint ):Number {
        
        if( scaleNum <= 1 )
            return keyWidth * scaleNum + keyWidth / 2;
            
        return keyWidth * ( scaleNum + 1 ) + keyWidth / 2;
    }
    
    private function keyPressHandler( event:MusicalKeyEvent ):void {
        
        pressedKeyNotes[ event.keyType.note ] = true;
        dispatchEvent( new MusicalKeyEvent( event.type, event.keyType ) );
        cTrace( "event.keyType : " + event.keyType );
        cTrace( "event.type : " + event.type );
    }
    
    private function keyReleaseHandler( event:MusicalKeyEvent ):void {
        
        pressedKeyNotes[ event.keyType.note ] = false;
        dispatchEvent( new MusicalKeyEvent( event.type, event.keyType ) );
    }

    private function cTrace(type:String):void 
    {
        SionPiano.traceIt(type);
    }
    
    
}

class MusicalKeyType {
    
    public static const COLOR_WHITE:String = "white";
    public static const COLOR_BLACK:String = "black";
    
    public static const SCALE_C:String = "c";
    public static const SCALE_D:String = "b";
    public static const SCALE_E:String = "e";
    public static const SCALE_F:String = "f";
    public static const SCALE_G:String = "g";
    public static const SCALE_A:String = "a";
    public static const SCALE_B:String = "a";
    
    private var _scale:String;
    public function get scale():String { return _scale; }
    
    private var _scaleNum:uint;
    public function get scaleNum():uint { return _scaleNum; }
    
    private var _color:String;
    public function get color():String { return _color; }
    
    private var _keyColorNum:uint;
    public function get keyColorNum():uint { return _keyColorNum; }
    
    private var _octave:int;
    public function get octave():int { return _octave; }
    
    public function get note():uint { return octave * 12 + 12 + scaleNum; }
    
    public function MusicalKeyType( scaleNum:uint, octave:uint ):void {
        
        _scaleNum = scaleNum;
        _octave = octave;
        
        switch( scaleNum ) {
            
            case 0:
                _color = COLOR_WHITE;
                _scale = SCALE_C;
                _keyColorNum = 0;
                break;
            
            case 1:
                _color = COLOR_BLACK;
                _scale = SCALE_C;
                _keyColorNum = 0;
                break;
            
            case 2:
                _color = COLOR_WHITE;
                _scale = SCALE_D;
                _keyColorNum = 1;
                break;
            
            case 3:
                _color = COLOR_BLACK;
                _scale = SCALE_D;
                _keyColorNum = 1;
                break;
            
            case 4:
                _color = COLOR_WHITE;
                _scale = SCALE_E;
                _keyColorNum = 2;
                break;
            
            case 5:
                _color = COLOR_WHITE;
                _scale = SCALE_F;
                _keyColorNum = 3;
                break;
            
            case 6:
                _color = COLOR_BLACK;
                _scale = SCALE_F;
                _keyColorNum = 2;
                break;
            
            case 7:
                _color = COLOR_WHITE;
                _scale = SCALE_G;
                _keyColorNum = 4;
                break;
            
            case 8:
                _color = COLOR_BLACK;
                _scale = SCALE_G;
                _keyColorNum = 3;
                break;
            
            case 9:
                _color = COLOR_WHITE;
                _scale = SCALE_A;
                _keyColorNum = 5;
                break;
            
            case 10:
                _color = COLOR_BLACK;
                _scale = SCALE_A;
                _keyColorNum = 4;
                break;
            
            case 11:
                _color = COLOR_WHITE;
                _scale = SCALE_B;
                _keyColorNum = 6;
                break;
        }
    }
    
    public static function getKeyColor( scaleNum:uint ):String {
        
        switch( scaleNum ) {
            
            case 0:
            case 2:
            case 4:
            case 5:
            case 7:
            case 9:
            case 11:
                return COLOR_WHITE;
        }
        
        return COLOR_BLACK;
    }
    
    
    
    public static function getKeyColorNum( scaleNum:uint ):uint {
        
        switch( scaleNum ) {
            
            case 0:
                return 0;
            
            case 1:
                return 0;
            
            case 2:
                return 1;
            
            case 3:
                return 1;
            
            case 4:
                return 2;
            
            case 5:
                return 3;
            
            case 6:
                return 2;
            
            case 7:
                return 4;
            
            case 8:
                return 3;
            
            case 9:
                return 5;
            
            case 10:
                return 4;
            
            case 11:
                return 6;
        }
        
        return null;
    }
}

class Console extends VBox
{
    private var _textField:TextField;
    private var _msprite:Sprite;
    public function Console(msprite:Sprite) 
    {
        super();
        _msprite = msprite;
        _msprite.addChild(this);
        addChildAt(new PushButton(null, 0, 0, "clear", doClear), numChildren);;
        var textArea:TextArea = TextArea(addChildAt(new TextArea(), numChildren));
        _textField = textArea.textField
        x = 465;
        stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownHandler);
        textArea.setSize(465, 350);
        var sCKeyBoard:SCKeyBoard = new SCKeyBoard(stage);
        sCKeyBoard.keyAndFunction =
        {
            Q:setDebuggerVisibility,
            A:setDebuggerAlpha,
            C:clear
        }
    }
    
    private function clear():void 
    {
        _textField.text = "";
    }
    
    private function setDebuggerAlpha():void 
    {
        const debuggerAlpha:Number = 0.5;
        alpha = alpha == debuggerAlpha?1:debuggerAlpha;
    }
    
    private function setDebuggerVisibility():void 
    {
        visible = !visible;
    }
    
    private function onKeyDownHandler(e:KeyboardEvent):void 
    {
        switch (e.keyCode) 
        {
            case Keyboard.UP:
                _textField.scrollV -= 10;
            break;
            case Keyboard.DOWN:
                _textField.scrollV += 10;
            break;
            default:
                
            break;
        }
    }
    
    private function doClear(e:Event):void 
    {
        _textField.text = "";
    }
    
    public function get textField():TextField 
    {
        return _textField;
    }
    
    public function set textField(value:TextField):void 
    {
        _textField = value;
    }
    
    public function traceThis(msg:String):void 
    {
        _textField.appendText(msg + "\n");
        _textField.scrollV = textField.maxScrollV;
        
    }
}
class SCKeyBoard
{
    private var _stage:Stage;
    private var object:Object;
    public var keyAndFunction:Object;
    
    public function SCKeyBoard(stageArg:Stage) 
    {
        _stage = stageArg;
        _stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
    }
    
    public function removeKey(key:String):void 
    {
        var k:Object = keyAndFunction;
        for (var name:String in k) 
        {
            if (name==key) 
            {
                trace( "(name==key) : " + (name==key) );
                k[name] = null;
                break;
            }
        }
    }
    
    public function addKeyAndFunction(key:String,callBack:Function):void 
    {
        keyAndFunction[key] = callBack;
    }
    
    private function keyDownHandler(e:KeyboardEvent):void 
    {
        if (!keyAndFunction) 
        {
            throw new Error("keyAndFunction should be defined");
        }
        var callBack:Function;
        if (keyAndFunction[String.fromCharCode(e.keyCode)]) 
        {
            trace( "keyAndFunction[String.fromCharCode(e.keyCode)] : " + keyAndFunction[String.fromCharCode(e.keyCode)] );
            callBack = keyAndFunction[String.fromCharCode(e.keyCode)]
            callBack();
        }
    }
    
    
}
class Trace 
{
    static private const SEPARATOR:String = "\n";
    static private const VALUE_SEPARATOR:String = ":";
    
    public function Trace() 
    {
        
    }
    
    /**
     * http://www.learnosity.com/techblog/index.cfm/2008/2/6/AS3--Looping-over-properties-of-a-class
     * @param    objArg
     * @return
     */
    public static function traceObject(objArg:Object,separator:String="",valueSeparator:String=""):String 
    {
        separator = separator == ""?SEPARATOR:separator;
        valueSeparator = valueSeparator == ""?VALUE_SEPARATOR:valueSeparator;
        //trace( "objArg : " + objArg );
        var def : XML = describeType(objArg);
        //trace( "def : " + def );
        var output:String = "";
        //Crazy:::::
        var properties : XMLList = def..variable.@name + def..accessor.@name;
        var number:int = 0;
        //trace("accesors and variables:");
        var p:String;
        for each ( var property : String in properties ) 
        {
            p = property + valueSeparator+" " + objArg[property];
            //trace(++number + "." + p);
            output += separator + p;
        }
        
        return output;
    }
    
    public static function traceMethods(objArg:Object):void 
    {
        var v:XMLList = describeType(objArg)..method;
        var name:String;
        var returnType:String;
        trace("methods:");
        var method:Function;
        var value:*;
        for (var j:int = 0; j < v.length(); j++) 
        {
            name = v[j].@name;
            returnType = v[j].@returnType;
            method = objArg[name];
            if (returnType!='void') 
            {
                
                value = method();
            }
            else
            {
                value = "void";
            }
            
            trace((j+1)+"."+name +" : " + value);
            
        }
    }
    
}
/**
 * List.as
 * Keith Peters
 * version 0.9.10
 * 
 * A scrolling list of selectable items. 
 * 
 * Copyright (c) 2011 Keith Peters
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

    import flash.display.DisplayObjectContainer;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    [Event(name="select", type="flash.events.Event")]
    class List extends Component
    {
        protected var _items:Array;
        protected var _itemHolder:Sprite;
        protected var _panel:Panel;
        protected var _listItemHeight:Number = 20;
        protected var _listItemClass:Class =ListItem;
        protected var _scrollbar:VScrollBar;
        protected var _selectedIndex:int = -1;
        protected var _defaultColor:uint = Style.LIST_DEFAULT;
        protected var _alternateColor:uint = Style.LIST_ALTERNATE;
        protected var _selectedColor:uint = Style.LIST_SELECTED;
        protected var _rolloverColor:uint = Style.LIST_ROLLOVER;
        protected var _alternateRows:Boolean = false;
        
        /**
         * Constructor
         * @param parent The parent DisplayObjectContainer on which to add this List.
         * @param xpos The x position to place this component.
         * @param ypos The y position to place this component.
         * @param items An array of items to display in the list. Either strings or objects with label property.
         */
        public function List(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, items:Array=null)
        {
            if(items != null)
            {
                _items = items;
            }
            else
            {
                _items = new Array();
            }
            super(parent, xpos, ypos);
        }
        
        /**
         * Initilizes the component.
         */
        protected override function init() : void
        {
            super.init();
            setSize(100, 100);
            addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
            addEventListener(Event.RESIZE, onResize);
            makeListItems();
            fillItems();
        }
        
        /**
         * Creates and adds the child display objects of this component.
         */
        protected override function addChildren() : void
        {
            super.addChildren();
            _panel = new Panel(this, 0, 0);
            _panel.color = _defaultColor;
            _itemHolder = new Sprite();
            _panel.content.addChild(_itemHolder);
            _scrollbar = new VScrollBar(this, 0, 0, onScroll);
            _scrollbar.setSliderParams(0, 0, 0);
        }
        
        /**
         * Creates all the list items based on data.
         */
        protected function makeListItems():void
        {
            var item:ListItem;
            while(_itemHolder.numChildren > 0)
            {
                item = ListItem(_itemHolder.getChildAt(0));
                item.removeEventListener(MouseEvent.CLICK, onSelect);
                _itemHolder.removeChildAt(0);
            }

            var numItems:int = Math.ceil(_height / _listItemHeight);
            numItems = Math.min(numItems, _items.length);
            numItems = Math.max(numItems, 1);
            for(var i:int = 0; i < numItems; i++)
            {

                item = new _listItemClass(_itemHolder, 0, i * _listItemHeight);
                item.setSize(width, _listItemHeight);
                item.defaultColor = _defaultColor;

                item.selectedColor = _selectedColor;
                item.rolloverColor = _rolloverColor;
                item.addEventListener(MouseEvent.CLICK, onSelect);
            }
        }

        protected function fillItems():void
        {
            var offset:int = _scrollbar.value;
            var numItems:int = Math.ceil(_height / _listItemHeight);
            numItems = Math.min(numItems, _items.length);
            for(var i:int = 0; i < numItems; i++)
            {
                var item:ListItem = _itemHolder.getChildAt(i) as ListItem;
                if(offset + i < _items.length)
                {
                    item.data = _items[offset + i];
                }
                else
                {
                    item.data = "";
                }
                if(_alternateRows)
                {
                    item.defaultColor = ((offset + i) % 2 == 0) ? _defaultColor : _alternateColor;
                }
                else
                {
                    item.defaultColor = _defaultColor;
                }
                if(offset + i == _selectedIndex)
                {
                    item.selected = true;
                }
                else
                {
                    item.selected = false;
                }
            }
        }
        
        /**
         * If the selected item is not in view, scrolls the list to make the selected item appear in the view.
         */
        protected function scrollToSelection():void
        {
            var numItems:int = Math.ceil(_height / _listItemHeight);
            if(_selectedIndex != -1)
            {
                if(_scrollbar.value > _selectedIndex)
                {
//                    _scrollbar.value = _selectedIndex;
                }
                else if(_scrollbar.value + numItems < _selectedIndex)
                {
                    _scrollbar.value = _selectedIndex - numItems + 1;
                }
            }
            else
            {
                _scrollbar.value = 0;
            }
            fillItems();
        }
        
        
        
        ///////////////////////////////////
        // public methods
        ///////////////////////////////////
        
        /**
         * Draws the visual ui of the component.
         */
        public override function draw() : void
        {
            super.draw();
            
            _selectedIndex = Math.min(_selectedIndex, _items.length - 1);


            // panel
            _panel.setSize(_width, _height);
            _panel.color = _defaultColor;
            _panel.draw();
            
            // scrollbar
            _scrollbar.x = _width - 10;
            var contentHeight:Number = _items.length * _listItemHeight;
            _scrollbar.setThumbPercent(_height / contentHeight); 
            var pageSize:Number = Math.floor(_height / _listItemHeight);
            _scrollbar.maximum = Math.max(0, _items.length - pageSize);
            _scrollbar.pageSize = pageSize;
            _scrollbar.height = _height;
            _scrollbar.draw();
            scrollToSelection();
        }
        
        /**
         * Adds an item to the list.
         * @param item The item to add. Can be a string or an object containing a string property named label.
         */
        public function addItem(item:Object):void
        {
            _items.push(item);
            invalidate();
            makeListItems();
            fillItems();
        }
        
        /**
         * Adds an item to the list at the specified index.
         * @param item The item to add. Can be a string or an object containing a string property named label.
         * @param index The index at which to add the item.
         */
        public function addItemAt(item:Object, index:int):void
        {
            index = Math.max(0, index);
            index = Math.min(_items.length, index);
            _items.splice(index, 0, item);
            invalidate();
            fillItems();
        }
        
        /**
         * Removes the referenced item from the list.
         * @param item The item to remove. If a string, must match the item containing that string. If an object, must be a reference to the exact same object.
         */
        public function removeItem(item:Object):void
        {
            var index:int = _items.indexOf(item);
            removeItemAt(index);
        }
        
        /**
         * Removes the item from the list at the specified index
         * @param index The index of the item to remove.
         */
        public function removeItemAt(index:int):void
        {
            if(index < 0 || index >= _items.length) return;
            _items.splice(index, 1);
            invalidate();
            fillItems();
        }
        
        /**
         * Removes all items from the list.
         */
        public function removeAll():void
        {
            _items.length = 0;
            invalidate();
            fillItems();
        }
        
        
        
        
        
        ///////////////////////////////////
        // event handlers
        ///////////////////////////////////
        
        /**
         * Called when a user selects an item in the list.
         */
        protected function onSelect(event:Event):void
        {
            if(! (event.target is ListItem)) return;
            
            var offset:int = _scrollbar.value;
            
            for(var i:int = 0; i < _itemHolder.numChildren; i++)
            {
                if(_itemHolder.getChildAt(i) == event.target) _selectedIndex = i + offset;
                ListItem(_itemHolder.getChildAt(i)).selected = false;
            }
            ListItem(event.target).selected = true;
            dispatchEvent(new Event(Event.SELECT));
        }
        
        /**
         * Called when the user scrolls the scroll bar.
         */
        protected function onScroll(event:Event):void
        {
            fillItems();
        }
        
        /**
         * Called when the mouse wheel is scrolled over the component.
         */
        protected function onMouseWheel(event:MouseEvent):void
        {
            _scrollbar.value -= event.delta;
            fillItems();
        }

        protected function onResize(event:Event):void
        {
            makeListItems();
            fillItems();
        }
        ///////////////////////////////////
        // getter/setters
        ///////////////////////////////////
        
        /**
         * Sets / gets the index of the selected list item.
         */
        public function set selectedIndex(value:int):void
        {
            if(value >= 0 && value < _items.length)
            {
                _selectedIndex = value;
//                _scrollbar.value = _selectedIndex;
            }
            else
            {
                _selectedIndex = -1;
            }
            invalidate();
            dispatchEvent(new Event(Event.SELECT));
        }
        public function get selectedIndex():int
        {
            return _selectedIndex;
        }
        
        /**
         * Sets / gets the item in the list, if it exists.
         */
        public function set selectedItem(item:Object):void
        {
            var index:int = _items.indexOf(item);
//            if(index != -1)
//            {
                selectedIndex = index;
                invalidate();
                dispatchEvent(new Event(Event.SELECT));
//            }
        }
        public function get selectedItem():Object
        {
            if(_selectedIndex >= 0 && _selectedIndex < _items.length)
            {
                return _items[_selectedIndex];
            }
            return null;
        }

        /**
         * Sets/gets the default background color of list items.
         */
        public function set defaultColor(value:uint):void
        {
            _defaultColor = value;
            invalidate();
        }
        public function get defaultColor():uint
        {
            return _defaultColor;
        }

        /**
         * Sets/gets the selected background color of list items.
         */
        public function set selectedColor(value:uint):void
        {
            _selectedColor = value;
            invalidate();
        }
        public function get selectedColor():uint
        {
            return _selectedColor;
        }

        /**
         * Sets/gets the rollover background color of list items.
         */
        public function set rolloverColor(value:uint):void
        {
            _rolloverColor = value;
            invalidate();
        }
        public function get rolloverColor():uint
        {
            return _rolloverColor;
        }

        /**
         * Sets the height of each list item.
         */
        public function set listItemHeight(value:Number):void
        {
            _listItemHeight = value;
            makeListItems();
            invalidate();
        }
        public function get listItemHeight():Number
        {
            return _listItemHeight;
        }

        /**
         * Sets / gets the list of items to be shown.
         */
        public function set items(value:Array):void
        {
            _items = value;
            invalidate();
        }
        public function get items():Array
        {
            return _items;
        }

        /**
         * Sets / gets the class used to render list items. Must extend ListItem.
         */
        public function set listItemClass(value:Class):void
        {
            _listItemClass = value;
            makeListItems();
            invalidate();
        }
        public function get listItemClass():Class
        {
            return _listItemClass;
        }

        /**
         * Sets / gets the color for alternate rows if alternateRows is set to true.
         */
        public function set alternateColor(value:uint):void
        {
            _alternateColor = value;
            invalidate();
        }
        public function get alternateColor():uint
        {
            return _alternateColor;
        }
        
        /**
         * Sets / gets whether or not every other row will be colored with the alternate color.
         */
        public function set alternateRows(value:Boolean):void
        {
            _alternateRows = value;
            invalidate();
        }
        public function get alternateRows():Boolean
        {
            return _alternateRows;
        }

        /**
         * Sets / gets whether the scrollbar will auto hide when there is nothing to scroll.
         */
        public function set autoHideScrollBar(value:Boolean):void
        {
            _scrollbar.autoHide = value;
        }
        public function get autoHideScrollBar():Boolean
        {
            return _scrollbar.autoHide;
        }

    }
/**
 * Style.as
 * Keith Peters
 * version 0.9.10
 * 
 * A collection of style variables used by the components.
 * If you want to customize the colors of your components, change these values BEFORE instantiating any components.
 * 
 * Copyright (c) 2011 Keith Peters
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
 

    class Style
    {
        public static var TEXT_BACKGROUND:uint = 0xFFFFFF;
        public static var BACKGROUND:uint = 0xCCCCCC;
        public static var BUTTON_FACE:uint = 0xFFFFFF;
        public static var BUTTON_DOWN:uint = 0xEEEEEE;
        public static var INPUT_TEXT:uint = 0x333333;
        public static var LABEL_TEXT:uint = 0x666666;
        public static var DROPSHADOW:uint = 0x000000;
        public static var PANEL:uint = 0xF3F3F3;
        public static var PROGRESS_BAR:uint = 0xFFFFFF;
        public static var LIST_DEFAULT:uint = 0xFFFFFF;
        public static var LIST_ALTERNATE:uint = 0xF3F3F3;
        public static var LIST_SELECTED:uint = 0xCCCCCC;
        public static var LIST_ROLLOVER:uint = 0XDDDDDD;
        
        public static var embedFonts:Boolean = true;
        public static var fontName:String = "PF Ronda Seven";
        public static var fontSize:Number = 8;
        
        public static const DARK:String = "dark";
        public static const LIGHT:String = "light";
        
        /**
         * Applies a preset style as a list of color values. Should be called before creating any components.
         */
        public static function setStyle(style:String):void
        {
            switch(style)
            {
                case DARK:
                    Style.BACKGROUND = 0x444444;
                    Style.BUTTON_FACE = 0x666666;
                    Style.BUTTON_DOWN = 0x222222;
                    Style.INPUT_TEXT = 0xBBBBBB;
                    Style.LABEL_TEXT = 0xCCCCCC;
                    Style.PANEL = 0x666666;
                    Style.PROGRESS_BAR = 0x666666;
                    Style.TEXT_BACKGROUND = 0x555555;
                    Style.LIST_DEFAULT = 0x444444;
                    Style.LIST_ALTERNATE = 0x393939;
                    Style.LIST_SELECTED = 0x666666;
                    Style.LIST_ROLLOVER = 0x777777;
                    break;
                case LIGHT:
                default:
                    Style.BACKGROUND = 0xCCCCCC;
                    Style.BUTTON_FACE = 0xFFFFFF;
                    Style.BUTTON_DOWN = 0xEEEEEE;
                    Style.INPUT_TEXT = 0x333333;
                    Style.LABEL_TEXT = 0x666666;
                    Style.PANEL = 0xF3F3F3;
                    Style.PROGRESS_BAR = 0xFFFFFF;
                    Style.TEXT_BACKGROUND = 0xFFFFFF;
                    Style.LIST_DEFAULT = 0xFFFFFF;
                    Style.LIST_ALTERNATE = 0xF3F3F3;
                    Style.LIST_SELECTED = 0xCCCCCC;
                    Style.LIST_ROLLOVER = 0xDDDDDD;
                    break;
            }
        }
    }