<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:res="com.dougmccune.containers.*"    
    layout="vertical" backgroundColor="#343434"
    horizontalAlign="left" verticalAlign="top"
    creationComplete="init(event)" 
    viewSourceURL="srcview/index.html">
    <mx:Style>
    global
    {
        font-size: 12;
    }
    .Title
    {
        font-size: 18;
        font-weight: normal;
        color: #f0f0f0;
    }
    ToolTip
    {
        font-size: 12;
    }
    Label, CheckBox
    {
        text-roll-over-color: #ffffff;
        text-selected-color: #ffffff;
        color: #ffffff;    
    }                    
    LinkButton
    {
        font-weight: normal;
        text-roll-over-color: #000000;
        text-selected-color: #000000;
        text-decoration: underline;
        color: #ffffff;    
    }
    </mx:Style>
    <mx:Script>
        <![CDATA[
        
            import flash.display.Bitmap;
            import flash.display.BitmapData;
            import flash.display.BitmapDataChannel;
            import flash.utils.Timer;
            import flash.events.TimerEvent;
            import flash.media.*; 
            import mx.events.ResizeEvent;            
        
            [Embed(source="assets/noSignal.mp3")]
            [Bindable]
            public var noSignalSoundClass:Class;
            private var noSignalSound:Sound = new noSignalSoundClass() as Sound;
            private var soundChannel:SoundChannel;                        
            private var image:Bitmap;
            private var timer:Timer;
            
            /**
            * Application initialization handler.
            */
            private function init(event:Event):void 
            {
                // Create and start timer for animation
                timer = new Timer(30);
                timer.addEventListener(TimerEvent.TIMER, refresh);
                timer.start();
                
                // Add resize handler
                addEventListener(ResizeEvent.RESIZE, resize, false, 0, true);
            }
            
            /**
            * Refresh event handler to trigger animation.
            */
            private function refresh(timerEvent:TimerEvent):void
            {
                timerEvent.updateAfterEvent();                
                animate();
            }
            
            /**
            * Updates noise canvas on resize event.
            */
            private function resize():void
            {
                update();
            }
            
            /**
            * Sets timer delay for animation.
            */
            private function resetTimer():void
            {
                timer.delay = timerIntervalSlider.value;
            }
            
            /**
            * Resets noise parameters to initial state.
            */        
            private function reset():void
            {
                randomSeedSlider.value = 1;
                lowSlider.value = 0;
                highSlider.value = 255;
                redCheck.selected = true;
                greenCheck.selected = true;
                blueCheck.selected = true;
                alphaCheck.selected = false;
                grayScaleCheck.selected = false;
                update();
            }    
                        
            /**
            * Updates noise effect canvas.
            */
            private function update():void 
            {
                var seed:int = int(randomSeedSlider.value);
                var low:uint = lowSlider.value;
                var high:uint = highSlider.value;
                var grayScale:Boolean = grayScaleCheck.selected;                
                var channel:uint = 0;
                if (redCheck.selected)
                {
                    channel = BitmapDataChannel.RED;
                }
                if (greenCheck.selected)
                {
                    channel = channel | BitmapDataChannel.GREEN;
                }
                if (blueCheck.selected)
                {
                    channel = channel | BitmapDataChannel.BLUE;
                }
                if (alphaCheck.selected)
                {
                    channel = channel | BitmapDataChannel.ALPHA;
                }
                
                // Add bitmap for drawing
                var width:uint = resizer.width;
                var height:uint = resizer.height;
                var bitmapData:BitmapData = new BitmapData(width, height, true, 0xffffffff);
                 bitmapData.noise(seed, low, high, channel, grayScale);
                        
                canvas.graphics.clear();
                canvas.graphics.beginBitmapFill(bitmapData);
                canvas.graphics.drawRect(0, 0, width, height);
                canvas.graphics.endFill();
                                
                // Update source text
                sourceText.text = "noise(" + seed +
                    ", " + lowSlider.value + ", " + highSlider.value + 
                    ", " + channel + ", " + grayScaleCheck.selected + ")";
            }
            
            /**
            * Plays "no signal" sound.
            */
            private function playSound():void
            {
                // create new sound channel
                soundChannel = noSignalSound.play(0, 1000);
                soundChannel.addEventListener(Event.SOUND_COMPLETE, playSound);                
            }
            
            /**
            * Stops playing scene sound.
            */
            private function stopSound():void
            {
                if (soundChannel != null)
                {
                    soundChannel.stop();
                    SoundMixer.stopAll();
                    soundChannel = null;
                }                
            }
            
            /**
            * Creates animated noise with random param values.
            */
            private function animate():void
            {
                if (animateButton.selected == false)
                {
                    // turn off
                    stopSound();
                    return;
                }
                if (soundChannel == null )
                {
                    playSound();
                }
                
                // Get parameter name and min/max random value
                var paramName:String = randomParameterName.selectedItem.data;
                var minRandomValue:uint = randomValueRangeSlider.values[0];                
                var maxRandomValue:uint = randomValueRangeSlider.values[1];
                var randomValue:uint = Math.random()*(maxRandomValue-minRandomValue) + minRandomValue;
                if (paramName == "low")
                {
                    lowSlider.value = randomValue;
                }
                else if (paramName == "high")
                {
                    highSlider.value = randomValue;
                }
                else    // randomSeed
                {
                    randomSeedSlider.value = randomValue;
                }
                
                // Update display
                update();
            }
        ]]>
    </mx:Script>
    
    <mx:ApplicationControlBar dock="true" width="700">
        <mx:Label styleName="Title" text="BitmapData Noise Explorer" />
    </mx:ApplicationControlBar>
    
    <mx:VBox>
    
        <mx:ApplicationControlBar>
            <mx:LinkButton label="bitmapData.noise(randomSeed:int, low:uint = 0, high:uint = 255, channelOptions:uint = 7, grayScale:Boolean = false)"
                toolTip="Fills an image with pixels representing random noise. Click on this link to see livedocs. Click Animate to see it in action."
                click="navigateToURL(new URLRequest('http://livedocs.adobe.com/flex/3/langref/flash/display/BitmapData.html#noise()'));"/>        
        </mx:ApplicationControlBar>

        <mx:HBox width="100%">
        
            <mx:VBox width="280" height="100%" 
                horizontalAlign="right" verticalGap="5" paddingTop="7">
            
            <mx:HBox>
                <mx:Label text="randomSeed:"/>
                    <mx:HSlider id="randomSeedSlider" change="update();"
                         value="1" minimum="0" maximum="255"
                         tickInterval="1" snapInterval="1" liveDragging="true"
                         showDataTip="true" dataTipPlacement="right" 
                         showTrackHighlight="true"
                        toolTip="The random seed number to use. If you keep all other parameters the same, you can generate different pseudo-random results by varying the random seed value. The noise function is a mapping function, not a true random-number generation function, so it creates the same results each time from the same random seed."/>                                                    
            </mx:HBox>
            
            <mx:HBox>
                <mx:Label text="low:"/>
                <mx:HSlider id="lowSlider" change="update();"
                     value="0" minimum="0" maximum="255" 
                     tickInterval="1" snapInterval="1" liveDragging="true"
                     showDataTip="true" dataTipPlacement="right" 
                     showTrackHighlight="true"/>                                    
            </mx:HBox>
            
            <mx:HBox>
                <mx:Label text="high:"/>
                <mx:HSlider id="highSlider" change="update();"
                    value="255" minimum="0" maximum="255" 
                    tickInterval="1" snapInterval="1" liveDragging="true"
                     showDataTip="true" dataTipPlacement="right"
                     showTrackHighlight="true"/>                                    
            </mx:HBox>
            
            <mx:Label text="channelOptions:" 
                toolTip="A number that can be a combination of any of the four color channel values (BitmapDataChannel.RED, BitmapDataChannel.BLUE, BitmapDataChannel.GREEN, and BitmapDataChannel.ALPHA)."/>
            <mx:HBox>
                <mx:CheckBox id="redCheck" selected="true" 
                    label="Red" change="update();"
                    toolTip="Red color channel"/>
                <mx:CheckBox id="greenCheck" selected="true" 
                    label="Green" change="update();"
                    toolTip="Green color channel"/>
                <mx:CheckBox id="blueCheck" selected="true" 
                    label="Blue " change="update();"
                    toolTip="Blue color channel"/>
            </mx:HBox>
            
            <mx:CheckBox id="alphaCheck" selected="false" label="Alpha" change="update();"
                    toolTip="Alpha (transparency) color channel"/>            
            
            <mx:HBox>
                <mx:CheckBox id="grayScaleCheck" label="grayScale:" labelPlacement="left" change="update();"
                    toolTip="If checked, a grayscale image is created by setting all of the color channels to the same value. The Alpha channel selection is not affected by this setting."/>                
            </mx:HBox>
            
            <mx:Button label="Reset" click="reset();" toolTip="Resets all settings"/>
            
        </mx:VBox>

        <mx:VBox horizontalAlign="center">
        
            <mx:ApplicationControlBar width="100%" paddingBottom="10">
                <mx:TextInput id="sourceText" width="100%"/>        
            </mx:ApplicationControlBar>                    
            
            <res:ResizableWrapper id="resizer" 
                width="200" height="200" resize="update();"  >
                <mx:VBox id="displayBox" backgroundColor="#333333">                
                    <mx:Canvas id="canvas" creationComplete="update();">
                    </mx:Canvas>        
                </mx:VBox>
            </res:ResizableWrapper>
            
        </mx:VBox>
        
        <mx:VBox>
        
            <mx:ColorPicker id="colorPicker" selectedColor="#333333" 
                change="displayBox.setStyle('backgroundColor', colorPicker.selectedColor);"
                toolTip="Sample image backgound color. Visible only if Alpha (transparency) color channel is selected."    />                                                                
        
            <mx:Label text="Randomize Parameter:"/>
            <mx:ComboBox id="randomParameterName" change="animate();"
                toolTip="Select the noise parameter to randomize">
                <mx:ArrayCollection>
         <mx:Object label="randomSeed" data="randomSeed"/>
         <mx:Object label="low" data="low"/>
         <mx:Object label="high" data="high"/>
          </mx:ArrayCollection>            
            </mx:ComboBox>
        
            <mx:Label text="Random Value Range:"/>
            <mx:HSlider id="randomValueRangeSlider" change="animate();"
                 thumbCount="2" values="[100,150]"
                 minimum="0" maximum="255"
                 tickInterval="1" snapInterval="1" liveDragging="true"
                 showDataTip="true" dataTipPlacement="right"
                 showTrackHighlight="true"/>
        
            <mx:Label text="Animation Timer Interval (msec):"/>
            <mx:HSlider id="timerIntervalSlider" change="resetTimer();"
                 value="50" minimum="50" maximum="200"
                 tickInterval="10" snapInterval="10" liveDragging="true"
                 showDataTip="true" dataTipPlacement="right"
                 showTrackHighlight="true"/>                    
        
            <mx:Button id="animateButton" toggle="true" useHandCursor="true" 
                label="Animate" click="animate();"
                toolTip="Click to Animate"/>
                                                     
        </mx:VBox>
                        
        </mx:HBox>
    
        <mx:ApplicationControlBar width="100%">
            <mx:LinkButton label="Created by Taras Novak"
                click="navigateToURL(new URLRequest('http://www.tarasnovak.com/blog'));"/>
            <mx:Spacer width="100%"/>
            <mx:LinkButton label="Inspired by bit-101 NoiseExplorer"
                click="navigateToURL(new URLRequest(' http://www.bit-101.com/explorers/NoiseExplorer.swf'));"/>
        </mx:ApplicationControlBar>    
                
    </mx:VBox>

</mx:Application>