<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx ="http://www.adobe.com/2006/mxml"
                layout ="absolute" 
                applicationComplete ="init()" 
                backgroundColor ="0x444444"
                name ="SplineAlignedImage"
                viewSourceURL ="srcview/index.html"> 
    
    <!-- by Petri Leskinen, Espoo, Finland, May 2011  -->
    
    <mx:Script>
        <![CDATA[ 
            
            import filter.SplineFilter;
            
            import flash.display.Bitmap;
            import flash.display.BitmapData;
            import flash.display.Sprite;
            import flash.events.Event;
            
            import mx.controls.HSlider;
            import mx.controls.Label;
            import mx.controls.Spacer;
            import mx.controls.TextArea;
            import mx.controls.sliderClasses.Slider;
            
            import mx.core.UIComponent;
            import mx.events.SliderEvent;
            
            import net.*;
            
            
            /**    the shader class */
            [Bindable("change")]
            protected var tiling:SplineFilter = new SplineFilter(null,null);
            
            
            
            /** Embedded images */
            [Embed( '../assets/chessboard.jpg')]
            protected var Picture1:Class;
            
            [Embed( '../assets/grid02.png')]
            protected var Picture3:Class;
            
            [Embed( '../assets/Barbwire.png')]
            protected var Picture2:Class;
            
            [Embed( '../assets/Thorns.png')]
            protected var Picture4:Class;
            
            [Embed('../assets/Telephonecord.png')]
            protected var Picture5:Class;
            
            [Embed('../assets/Chain.png')]
            protected var Picture6:Class;
            
            [Embed('../assets/maisema.jpg')]
            protected var Picture7:Class;
            
            [Embed('../assets/yellowrose.png')]
            protected var Picture8:Class;
            
            
            private var 
                grips:Array,
                bground:Shape;
            
            protected function init():void {
                
                //    bground holds the background color and preview as line art
                bground = new Shape();
                emptyShape();
                UIRef.addChild(bground);
                
                tiling.output    = new BitmapData(600, 400, true, 0);
                UIRef.addChild(new Bitmap(tiling.output));
                
                
                //    array of grips on stage
                grips = [ 
                    tiling.startpoint=    new GripBox(50, 200),
                    tiling.control1=    new GripBox(200,100),
                    tiling.control2=     new GripBox(400,300),
                    tiling.endpoint=     new GripBox(550,200)
                    ];
                    
                for each (var g:GripBox in grips) {
                    g.addEventListener(GripBox.RELEASED, gripReleased);
                    g.addEventListener(GripBox.EDITED, gripEdited);
                    
                    UIRef.addChild(g);
                }
                
                
                initImage();    
            }
            
            
            /**    initializes the application and
             *     change to the image selected in ComboBox 
             * */
            protected function initImage():void {
                var c:Class;
                switch (imageCombo.selectedLabel) {
                    case "Telephone Cord":
                        c =Picture5;
                        break;
                    
                    case "Chain":
                        c =Picture6;
                        break;
                    
                    case "Grid":
                        c =Picture3;
                        break;
                    
                    case "Chessboard": 
                        c =Picture1;
                        break;
                    
                    case "Barbwire":
                        c =Picture2;
                        break;
                    
                    case "Thorns":
                        c =Picture4;
                        break;
                
                    case "Landscape":
                        c =Picture7;
                        break;
                    
                    case "Yellow Rose":
                        c =Picture8;
                        break;
                    
                    case "... Browse":
                        uploadImage();
                        return;
                        
                    case "Gradient":
                        var bmd:BitmapData = new BitmapData(1,5,true,0);
                        bmd.setVector(bmd.rect, Vector.<uint>([0xFFFFFFFF,0xC0FFFFFF,0x80FFFFFF,0x40FFFFFF, 0]));
                        var bmd2:BitmapData = new BitmapData(200,200,true,0);
                        bmd2.draw(bmd, new Matrix(bmd2.width/bmd.width,0,0,bmd2.height/bmd.height), null,null,null,true);
                        initSource(bmd2);
                        return;
                    
                }
                initSource(Bitmap(new c).bitmapData);
            }
            
            
            //    leave some empty area as image borders
            private var padding:int=1;
            
            /**    change the source image */
            protected function initSource(source:BitmapData):void {
                padding = (tiling.repeat ? 0 : 1);
                var bmd:BitmapData = new BitmapData(source.width+2*padding,source.height+2, true,0);
                bmd.draw(source, new Matrix(1,0,0,1,padding,1));
                
                //    set filter input and output
                tiling.input    = bmd;
                this.dispatchEvent(new Event(Event.CHANGE,true));
                
                //    update preview thumbnail on controls
                sourcePreview.source = new Bitmap(source);
                
            }
            
            
            
            /**    Called when dragging a grip on stage */
            protected function gripEdited(e:Event=null):void {
                emptyShape();
                bground.graphics.lineStyle(1,0xFFFFFF,1);
                tiling.drawPreview(bground.graphics);
                
                tiling.output.fillRect(tiling.output.rect,0x0);
            }
            
            
            /**    Called when releasing a grip on stage */
            protected function gripReleased(e:Event=null):void {
                
                emptyShape();
                tiling.updatePath();
                
                this.dispatchEvent(new Event(Event.CHANGE,true));
            }
            
            
            /**    Clears the background and possible preview graphics */
            private function emptyShape():void {
                bground.graphics.clear();
                bground.graphics.beginFill(0x0,0.25);
                bground.graphics.drawRect(0,0, 600,400);
                bground.graphics.endFill();
            }
            
            
            /**    sets the parameter 'prop' on filter with value */
            private function setFilterProp(prop:String, value:*):void {
                tiling[prop]=value;
                //    this is for updating the controls:
                this.dispatchEvent(new Event(Event.CHANGE,true));
            }
            
            
            /**    upload an image from local computer */
            private function uploadImage():void {
                //    initSource as parameter is the function to call when upload is ready
                new ImageFormatImporter(initSource);
                imageCombo.selectedIndex=-1;
            }
            
            
            /**    save .png to local computer */
            private function savePNG():void {
                new PngFormatExporter(tiling.output, this.name+".png");
            }
            
            
            /**    save .jpg to local computer */
            private function saveJPG():void {
                new JpgFormatExporter(tiling.output, this.name+".jpg");
            }
            
            
            
        ]]>
        
    </mx:Script>
    
    <mx:HBox x="30" y="30">
        <mx:Panel label="Disks">
            
            <mx:VBox id="controls" x="20" y="40" horizontalAlign="center" verticalGap="5" 
                     width="170" height="465" backgroundColor="0x808080">
                
                <mx:Spacer height="20" /> 
                
                <mx:ComboBox 
                    id="imageCombo" width="150" 
                    change="initImage()" rowCount="10" 
                    selectedIndex="0"
                    prompt="Select an Image"> 
                    <mx:ArrayCollection> 
                        <mx:Object label="Grid" />
                        <mx:Object label="Chessboard" />
                        <mx:Object label="Gradient" />
                        <mx:Object label="Telephone Cord" />
                        <mx:Object label="Chain" />
                        <mx:Object label="Thorns" />
                        <mx:Object label="Barbwire" />
                        <mx:Object label="Yellow Rose" />
                        <mx:Object label="Landscape" />
                        
                        <mx:Object label="... Browse" />
                    </mx:ArrayCollection>
                </mx:ComboBox>
                
                <mx:Image id="sourcePreview" width="144" height="108"
                          click="tiling.output.fillRect(tiling.output.rect,0);tiling.output.draw(sourcePreview.source as Bitmap)" 
                          />
                <mx:Spacer height="20" /> 
                
                
                <mx:HSlider value="@{tiling.offsetX}" minimum="-200" maximum="200"
                            change="setFilterProp('offsetX',event.value);" liveDragging="true" 
                            labels="['','offset Point','']" labelOffset="0" width="150"
                            />
                
                <mx:HSlider value="@{tiling.offsetY}" minimum="-200" maximum="200" width="150"
                            change="setFilterProp('offsetY',event.value)" liveDragging="true" 
                            />
                
                <mx:HSlider minimum="0.1" value="@{tiling.scale}" maximum="5.0"
                            change="setFilterProp('scale',event.value);" 
                            liveDragging="true" width="150" snapInterval="0.1"
                            labels="['','Pattern Scale','']" labelOffset="0"    
                            />
                
                <mx:CheckBox id="repeatCB" 
                             change="tiling.repeat=repeatCB.selected;this.initSource((sourcePreview.source as Bitmap).bitmapData)" 
                             label="Repeat" labelPlacement="left" selected="@{tiling.repeat}" /> 
                
                <!-- this is a control for filter quality:
                <mx:CheckBox id="dividedCB" change="tiling.divided=dividedCB.selected" 
                             label="Divide" labelPlacement="left" selected="@{tiling.divided}" /> 
                -->
                
                <mx:HBox>
                    <mx:Label text="Fit to Curve" />
                    <mx:NumericStepper minimum="0" value="@{tiling.fit}" maximum="7"
                                       change="setFilterProp('fit',event.value);" 
                            />
                </mx:HBox>
                                   
                <mx:HSlider minimum="-30" value="0" maximum="30"
                            change="tiling.rotation=event.value;" liveDragging="false" snapInterval="5"
                            labels="['','Rotation','']" labelOffset="0" width="150"
                            />
                
                <mx:Spacer height="20" /> 
                
                <mx:HBox>
                    <mx:Button label="Save as .png" width="96" click="savePNG();" />
                    <mx:Button label=".jpg" width="45" click="saveJPG()" />
                </mx:HBox>
                
            </mx:VBox>
        </mx:Panel>
        <mx:Label id="laabeli" />
        <mx:Spacer width="25" />
        <!--    UIRef: the container for image -->
        <mx:UIComponent id="UIRef" />
    </mx:HBox>
    
</mx:Application>