<?xml version="1.0" encoding="utf-8"?>
<!--

////////////////////////////////////////////////////////////////////////////////
//
//    Copyright 2014 Ardisia Labs LLC. All Rights Reserved.
//
//    This file is licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

-->
<s:Module xmlns:fx="http://ns.adobe.com/mxml/2009" 
          xmlns:s="library://ns.adobe.com/flex/spark" 
          xmlns:mx="library://ns.adobe.com/flex/mx" 
          xmlns:menuBar="ardisia.components.menuBar.*" 
          xmlns:graphicsEditor="components.graphicsEditor.*"
          xmlns:toolbar="ardisia.components.toolbar.*" 
          xmlns:compassContainer="ardisia.components.compassContainer.*" 
          xmlns:scroller="ardisia.components.scroller.*" 
          xmlns:expandingContainer="ardisia.components.expandingContainer.*" 
          xmlns:buttonBar="ardisia.components.buttonBar.*" 
          xmlns:viewStack="ardisia.components.viewStack.*" 
          xmlns:layouts="ardisia.components.buttonBar.layouts.*" 
          xmlns:colorPicker="ardisia.components.colorPicker.*" 
          xmlns:sliderField="ardisia.components.sliderField.*"
          xmlns:separators="ardisia.components.separators.*"
          xmlns:rotaryField="ardisia.components.rotaryField.*"
          xmlns:richTextEditor="ardisia.components.richTextEditor.*"
          xmlns:local="*" 
          xmlns:miniViewport="ardisia.components.miniViewport.*"
          xmlns:pane="ardisia.components.pane.*"
          frameRate="60"
          width="100%" height="100%"
          removedFromStage="removedFromStageHandler(event)"
          creationComplete="creationCompleteHandler(event)"
          backgroundColor="#E9E9E9">
    
    <!-- styles -->
    <fx:Style>
        @namespace graphicsEditor "ardisia.components.graphicsEditor.*";
        
        graphicsEditor|GraphicsEditor
        {
            flood-fill-cursor: Embed(source="cursors/fugue/paint-can.png");
            flood-fill-hot-spot: 15, 13;
            wand-cursor: Embed(source="cursors/fugue/wand.png");
            wand-hot-spot: 3, 3;
        }
        
    </fx:Style>
    
    <!-- scripts -->
    <fx:Script>
        <![CDATA[
            import flash.filters.BlurFilter;
            import flash.filters.ColorMatrixFilter;
            
            import mx.core.BitmapAsset;
            import mx.core.FlexGlobals;
            import mx.events.FlexEvent;
            import mx.events.MenuEvent;
            
            import spark.events.IndexChangeEvent;
            import spark.events.PopUpEvent;
            
            import ardisia.bitmapAdjustments.BitmapAdjustments;
            import ardisia.bitmapAdjustments.PixelateTypes;
            import ardisia.bitmapAdjustments.dataTypes.ThresholdData;
            import ardisia.components.buttonBar.events.ButtonBarEvent;
            import ardisia.components.colorPicker.events.ColorPickerEvent;
            import ardisia.components.graphicsEditor.BrushModes;
            import ardisia.components.graphicsEditor.GraphicsEditor;
            import ardisia.components.graphicsEditor.GraphicsEditorInteractionModes;
            import ardisia.components.graphicsEditor.GraphicsEditorVectorTypes;
            import ardisia.components.graphicsEditor.baseClasses.GraphicObjectBase;
            import ardisia.components.graphicsEditor.events.GraphicsEditorEvent;
            import ardisia.components.graphicsEditor.graphicObjects.BitmapGraphicObject;
            import ardisia.components.graphicsEditor.graphicObjects.TextGraphicObject;
            import ardisia.components.graphicsEditor.graphicObjects.VectorGraphicObject;
            import ardisia.components.pane.events.PaneEvent;
            import ardisia.components.toolbar.ToolbarColorTransformIconToggleButton;
            import ardisia.filters.BlackWhiteOutlineFilter;
            import ardisia.filters.BrightnessFilter;
            import ardisia.filters.BrownFilter;
            import ardisia.filters.BubblegumFilter;
            import ardisia.filters.ContrastFilter;
            import ardisia.filters.CoolFilter;
            import ardisia.filters.EdgeDetectFilter;
            import ardisia.filters.EmbossFilter;
            import ardisia.filters.GrayscaleFilter;
            import ardisia.filters.HueFilter;
            import ardisia.filters.InvertFilter;
            import ardisia.filters.SaturationFilter;
            import ardisia.filters.SepiaFilter;
            import ardisia.filters.SharpenFilter;
            import ardisia.filters.SoftWarmFilter;
            import ardisia.filters.WarmFilter;
            import ardisia.utils.GeomUtils;
            
            import components.graphicsEditor.panes.CanvasPropertiesPane;
            import components.graphicsEditor.panes.FiltersPane;
            import components.graphicsEditor.panes.ImportPane;
            import components.graphicsEditor.panes.SampleImagesPane;
            
            //--------------------------------------
            //  embedded assets
            //--------------------------------------
            
            [Embed(="images/Ada-Lovelace-portrait.jpg")]
            public var AdaImage:Class;
            
            [Embed(="images/buffalo.jpg")]
            public var BuffaloImage:Class;
            
            [Embed(="images/flower-2.jpg")]
            public var FlowerImage:Class;
            
            [Embed(="images/grapes.jpg")]
            public var GrapesImage:Class;
            
            [Embed(="images/kite.jpg")]
            public var KiteImage:Class;
            
            [Embed(="images/mud.jpg")]
            public var MudImage:Class;
            
            [Embed(="images/strawberries.jpg")]
            public var StrawberriesImage:Class;
            
            [Embed(="images/doughnut.png")]
            public var DonutImage:Class;
            
            //--------------------------------------------------------------------------
            //
            //  Variables
            //
            //--------------------------------------------------------------------------
            
            /**
             *     Current mode the filters pane is operating under.
             */
            protected var filterFormMode:String;
            
            /**
             *     Cloned bitmap for real time filter adjustments.
             */
            protected var clonedBmd:BitmapData;
            
            /**
             *     Counts the number of editors opened that do not have a name.  Used to 
             *     prevent name collisions.
             */
            protected var untitledCounter:int = 1;
            
            /**
             *     Update the toolbar on the next invalidation pass.
             * 
             *     @private
             */
            protected var toolbarAndMenuDirty:Boolean;
            
            /**
             *     Update the editor on the next invalidation pass.
             * 
             *     @private
             */
            protected var activeEditorDirty:Boolean;
            
            /**
             *     Update the transform rectangle on the next invalidation pass.
             * 
             *     @private
             */
            protected var transformRectDirty:Boolean;
            
            /**
             *    @private
             * 
             *     Clipboard of the current objects.  Content is added via cut/copy/paste, etc.
             */
            protected var clipboard:Vector.<GraphicObjectBase> = new Vector.<GraphicObjectBase>();
            
            //----------------------------------
            //  panes
            //----------------------------------
            
            /**
             *     @private
             * 
             *     Pane that handles canvas properties.
             */
            protected var canvasPropertiesPane:CanvasPropertiesPane;
            
            /**
             *     @private
             * 
             *     Pane that handles adding images to new editor instances.
             */
            protected var samplesPane:SampleImagesPane;
            
            /**
             *     @private
             * 
             *     Pane that handles importing objects into an existing editor.
             */
            protected var importPane:ImportPane;
            
            /**
             *     @private
             * 
             *     Pane that handles setting filter and bitmap adjustments.
             */
            protected var filtersPane:FiltersPane;
            
            //--------------------------------------------------------------------------
            //
            //  Properties
            //
            //--------------------------------------------------------------------------
            
            //----------------------------------
            //  activeEditor
            //----------------------------------
            
            /**
             *     The currently active GraphicsEditor instance.
             */
            public var activeEditor:GraphicsEditor;
            
            //--------------------------------------------------------------------------
            //
            //  Overridden methods
            //
            //--------------------------------------------------------------------------
            
            /**
             *     @private
             */
            override protected function commitProperties():void
            {
                function setEnabledMenuItem(menuPosition:int, 
                                            subMenuPosition:int, 
                                            bool:Boolean):void
                {
                    var menu:XML = (menuBar.dataProvider.getItemAt(menuPosition) as XML);
                    
                    if (menu.menuitem[subMenuPosition].@enabled != bool)
                        menu.menuitem[subMenuPosition].@enabled = bool;
                }
                
                super.commitProperties();
                
                if (toolbarAndMenuDirty)
                {
                    toolbarAndMenuDirty = false;
                    
                    var active:Boolean = activeEditor ? true : false;
                    var singleBitmapSelection:Boolean = activeEditor && activeEditor.selectedGraphicObjects && activeEditor.selectedGraphicObjects.length == 1 && activeEditor.selectedGraphicObjects[0] is BitmapGraphicObject ? true : false;
                    var selection:Boolean = activeEditor && activeEditor.selectedGraphicObjects && activeEditor.selectedGraphicObjects.length > 0 ? true : false;
                    var multiSelection:Boolean = activeEditor && activeEditor.selectedGraphicObjects && activeEditor.selectedGraphicObjects.length > 1 ? true : false;
                    
                    // import
                    importButton.enabled = active;
                    setEnabledMenuItem(0, 4, active);
                    
                    // export
                    exportButton.enabled = active;
                    setEnabledMenuItem(0, 5, active);
                    setEnabledMenuItem(0, 6, active);
                    
                    // undo / redo
                    if (activeEditor)
                    {
                        undoButton.enabled = activeEditor.editorStates.length > 1;
                        setEnabledMenuItem(1, 0, activeEditor.editorStates.length > 1);
                        redoButton.enabled = activeEditor.redoStates.length > 0;
                        setEnabledMenuItem(1, 1, activeEditor.redoStates.length > 0);
                    }
                    else
                    {
                        redoButton.enabled = undoButton.enabled = false;
                        setEnabledMenuItem(1, 0, false);
                        setEnabledMenuItem(1, 1, false);
                    }
                    
                    // cut copy
                    cutButton.enabled = selection;
                    copyButton.enabled = selection;
                    setEnabledMenuItem(1, 3, selection);
                    setEnabledMenuItem(1, 4, selection);
                    
                    // paste
                    pasteButton.enabled = clipboard.length > 0;
                    setEnabledMenuItem(1, 5, clipboard.length > 0);
                    
                    // delete
                    deleteButton.enabled = selection;
                    setEnabledMenuItem(1, 9, selection);
                    
                    // add grouping
                    groupGraphicObjectsButton.enabled = multiSelection;
                    setEnabledMenuItem(3, 3, multiSelection);
                    
                    // ungrouping
                    unGroupGraphicObjectsButton.enabled = selection;
                    setEnabledMenuItem(3, 4, selection);
                    
                    // flatten selection
                    flattenButton.enabled = selection;
                    setEnabledMenuItem(3, 5, selection);
                    
                    // rotation
                    rotateClockwiseButton.enabled = selection;
                    rotateCounterClockwiseButton.enabled = selection;
                    flipHorizontalButton.enabled = selection;
                    flipVerticalButton.enabled = selection;
                    setEnabledMenuItem(3, 7, selection);
                    setEnabledMenuItem(3, 8, selection);
                    setEnabledMenuItem(3, 9, selection);
                    setEnabledMenuItem(3, 10, selection);
                    
                    // depth
                    moveBackwardButton.enabled = selection;
                    moveForwardButton.enabled = selection;
                    moveToBackButton.enabled = selection;
                    moveToFrontButton.enabled = selection;
                    setEnabledMenuItem(3, 12, selection);
                    setEnabledMenuItem(3, 13, selection);
                    setEnabledMenuItem(3, 14, selection);
                    setEnabledMenuItem(3, 15, selection);
                    
                    // adjustments
                    setEnabledMenuItem(4, 0, singleBitmapSelection);
                    setEnabledMenuItem(4, 1, singleBitmapSelection);
                    setEnabledMenuItem(4, 2, singleBitmapSelection);
                    setEnabledMenuItem(4, 4, singleBitmapSelection);
                    setEnabledMenuItem(4, 6, singleBitmapSelection);
                    setEnabledMenuItem(4, 7, singleBitmapSelection);
                    setEnabledMenuItem(4, 8, singleBitmapSelection);
                    setEnabledMenuItem(4, 9, singleBitmapSelection);
                    setEnabledMenuItem(4, 10, singleBitmapSelection);
                    setEnabledMenuItem(4, 11, singleBitmapSelection);
                    setEnabledMenuItem(4, 12, singleBitmapSelection);
                    setEnabledMenuItem(4, 13, singleBitmapSelection);
                    setEnabledMenuItem(4, 14, singleBitmapSelection);
                    setEnabledMenuItem(4, 15, singleBitmapSelection);
                    
                    // filters
                    setEnabledMenuItem(5, 0, singleBitmapSelection);
                    setEnabledMenuItem(5, 1, singleBitmapSelection);
                    setEnabledMenuItem(5, 2, singleBitmapSelection);
                    setEnabledMenuItem(5, 3, singleBitmapSelection);
                    setEnabledMenuItem(5, 4, singleBitmapSelection);
                    setEnabledMenuItem(5, 6, singleBitmapSelection);
                    setEnabledMenuItem(5, 7, singleBitmapSelection);
                    setEnabledMenuItem(5, 8, singleBitmapSelection);
                    setEnabledMenuItem(5, 9, singleBitmapSelection);
                    setEnabledMenuItem(5, 10, singleBitmapSelection);
                    setEnabledMenuItem(5, 11, singleBitmapSelection);
                    setEnabledMenuItem(5, 13, singleBitmapSelection);
                    
                    // open canvas properties
                    canvasPropertiesButton.enabled = active;
                    setEnabledMenuItem(3, 0, active);
                    
                    // fit canvas
                    fitCanvasButton.enabled = active;
                    setEnabledMenuItem(3, 1, active);
                    
                    // color picker
                    if (activeEditor)
                        colorPickerSelect.selectedColor = activeEditor.canvasBackgroundColor;
                    colorPickerSelect.enabled = active;
                    
                    // zoom in/out
                    zoomDropDown.enabled = active;
                    setEnabledMenuItem(2, 0, active);
                    setEnabledMenuItem(2, 1, active);
                    
                    // zoom to fit
                    zoomToFitButton.enabled = active;
                    setEnabledMenuItem(2, 3, active);
                    
                    // select
                    setEnabledMenuItem(1, 7, active);
                }
                
                if (activeEditorDirty)
                {
                    activeEditorDirty = false;
                    
                    if (!activeEditor)
                        return;
                    
                    // zoom drop down
                    var len:int = zoomDropDown.dataProvider.length;
                    var selIndex:int = -1;
                    for (var i:int = len - 1; i > -1; i--)
                    {
                        var item:Object = zoomDropDown.dataProvider[i];
                        if (item.zoom == activeEditor.zoomFactor)
                        {
                            selIndex = i;
                            break;
                        }
                    }
                    if (selIndex > -1)
                    {
                        zoomDropDown.selectedIndex = selIndex;
                    }
                    else
                    {
                        zoomDropDown.selectedIndex = -1;
                        zoomDropDown.prompt = Math.round(activeEditor.zoomFactor * 100) + "%";
                    }
                    
                    // update colors
                    colorPickerSelect.selectedColor = activeEditor.canvasBackgroundColor;
                    activeEditor.strokeColor = strokeColorSelect.selectedColor;
                    activeEditor.fillColor = fillColorSelect.selectedColor;
                    
                    var selLayers:Vector.<GraphicObjectBase> = activeEditor.selectedGraphicObjects;
                    
                    // update components based on selection
                    switch (activeEditor.interactionMode)
                    {
                        
                        case GraphicsEditorInteractionModes.SELECT_FRONT:
                        case GraphicsEditorInteractionModes.SELECT_BEHIND:
                            // disable all bitmap options; must be enabled below    
                            distortButton.enabled = marqueeButton.enabled = wandButton.enabled = floodFillButton.enabled = eraserButton.enabled = false;
                            blurButton.enabled = sharpenButton.enabled = pinchButton.enabled = bloatButton.enabled = false;
                            
                            vectorContainer.visible = vectorContainer.includeInLayout = false;
                            colorsContainer.visible = colorsContainer.includeInLayout = false;
                            fillPropertiesContainer.visible = fillPropertiesContainer.includeInLayout = false;
                            fillColorContainer.visible = fillColorContainer.includeInLayout = false;
                            
                            // update transform mode
                            if (activeEditor.transformConstrainProportions)
                                transformTypeButtonBar.selectedIndex == 0;
                            else
                                transformTypeButtonBar.selectedIndex == 1;
                            
                            // nothing selected; hide additional property containers
                            if (!selLayers || selLayers.length == 0)
                            {
                                alphaRotationContainer.visible = alphaRotationContainer.includeInLayout = false;
                                transformRectContainer.visible = transformRectContainer.includeInLayout = false;
                                
                                return;
                            }
                                // single selection
                            else if (selLayers.length == 1)
                            {
                                alphaRotationContainer.visible = alphaRotationContainer.includeInLayout = true;
                                transformRectContainer.visible = transformRectContainer.includeInLayout = true;
                                
                                alphaSelect.value = Math.round(selLayers[0].alpha * 100);
                                rotationSelect.value = GeomUtils.getRotation(selLayers[0].transform.matrix);
                                
                                // single bitmap
                                if (selLayers[0] is BitmapGraphicObject)
                                {
                                    selectionDescriptionLabel.text = "Bitmap Object Selected";
                                    distortButton.enabled = marqueeButton.enabled = wandButton.enabled = floodFillButton.enabled = eraserButton.enabled = true;
                                    blurButton.enabled = sharpenButton.enabled = pinchButton.enabled = bloatButton.enabled = true;
                                }
                                if (selLayers[0] is VectorGraphicObject)
                                {
                                    selectionDescriptionLabel.text = "Vector Object Selected";
                                    var vectorObject:VectorGraphicObject = selLayers[0] as VectorGraphicObject;
                                    vectorContainer.visible = vectorContainer.includeInLayout = true;
                                    colorsContainer.visible = colorsContainer.includeInLayout = true;
                                    
                                    strokeWeightSelect.value = vectorObject.strokeWeight;
                                    strokeAA.selected = !vectorObject.strokePixelHinting;
                                    strokeAlphaSelect.value = vectorObject.strokeAlpha * 100;
                                    strokeColorSelect.selectedColor = vectorObject.strokeColor;
                                    
                                    // hide fill for lines
                                    if (VectorGraphicObject(selLayers[0]).type != GraphicsEditorVectorTypes.LINE)
                                    {
                                        fillColorContainer.visible = fillColorContainer.includeInLayout = true;
                                        fillPropertiesContainer.visible = fillPropertiesContainer.includeInLayout = true;
                                        fillColorSelect.selectedColor = vectorObject.fillColor;
                                        fillAlphaSelect.value = vectorObject.fillAlpha * 100;
                                    }
                                }
                                if (selLayers[0] is TextGraphicObject)
                                {
                                    selectionDescriptionLabel.text = "Text Object Selected";
                                }
                                
                            }
                            // multiple selection
                            else
                            {
                                alphaRotationContainer.visible = alphaRotationContainer.includeInLayout = true;
                                transformRectContainer.visible = transformRectContainer.includeInLayout = true;
                                
                                // ignore grouping for selection count
                                selectionDescriptionLabel.text = selLayers.length + "  Objects Selected";
                                
                                // clear alpha unless all selected objects have the same alpha
                                var alpha:Number = NaN;
                                var alphaSame:Boolean = true;
                                for each (var object:GraphicObjectBase in selLayers)
                                {
                                    if (isNaN(alpha))
                                    {
                                        alpha = object.alpha;
                                    }
                                    if (alpha != object.alpha)
                                    {
                                        alphaSame = false;
                                        break;
                                    }
                                }
                                alphaSelect.value = alphaSame ? Math.round(object.alpha * 100) : NaN;
                                rotationSelect.value = 0;
                            }
                            
                            break;
                        
                        case GraphicsEditorInteractionModes.BITMAP_LASSO:
                            activeEditor.bitmapLassoShape = marqueeShapeSelect.selectedItem.shape;
                            
                            break;
                        
                        case GraphicsEditorInteractionModes.WAND:
                            activeEditor.wandAntiAlias = wandAASelect.selected;
                            activeEditor.wandFillTolerance = wandToleranceSelect.value;
                            
                            break;
                        
                        case GraphicsEditorInteractionModes.FLOOD_FILL:
                            activeEditor.floodFillTolerance = floodFillToleranceSelect.value;
                            activeEditor.floodFillAlpha = floodFillAlphaSelect.value / 100;
                            activeEditor.floodFillAntiAlias = floodFillAASelect.selected;
                            activeEditor.floodFillColor = fillColorSelect.selectedColor;
                            
                            break;
                        
                        case GraphicsEditorInteractionModes.TEXT:
                            if (selLayers && selLayers.length > 0 && selLayers[0] is TextGraphicObject)
                            {
                                textContainer.enabled = true;
                                rte.target = TextGraphicObject(selLayers[0]).editableText;
                            }
                            else
                            {
                                textContainer.enabled = false;
                            }    
                            
                            break;
                        
                    }
                }
                
                if (transformRectDirty)
                {
                    transformRectDirty = false;
                    
                    if (!activeEditor)
                        return;
                    
                    // determine what rectangle is being considered
                    switch (activeEditor.interactionMode)
                    {
                        
                        case GraphicsEditorInteractionModes.SELECT_FRONT:
                        case GraphicsEditorInteractionModes.SELECT_BEHIND:
                        case GraphicsEditorInteractionModes.TEXT:
                            if (!activeEditor.selectedGraphicObjects || activeEditor.selectedGraphicObjects.length < 1)
                                return;
                            
                            var rect:Rectangle = activeEditor.getTransformRectangle2(activeEditor.viewportPart, null, false);
                            
                            // update rotation for single objects
                            if (activeEditor.selectedGraphicObjects.length == 1)
                            {
                                rotationSelect.commitValue(Math.round(GeomUtils.getRotation(activeEditor.selectedGraphicObjects[0].getLayoutMatrix())), false);
                            }
                            else
                            {
                                rotationSelect.value = 0;
                            }
                            
                            break;
                        
                        case GraphicsEditorInteractionModes.CROP:
                            rect = activeEditor.cropRectangle;
                            
                            // if the crop rectangle has dimensions, enable crop button
                            cropCanvasButton.enabled = rect.width > 0 && rect.height > 0;
                            
                            break;
                        
                    }
                    
                    if (rect)
                    {
                        widthSelect.value = rect.width;
                        heightSelect.value = rect.height;
                        xSelect.value = rect.x;
                        ySelect.value = rect.y;
                    }
                }
            }
            
            //--------------------------------------------------------------------------
            //
            //  Methods
            //
            //--------------------------------------------------------------------------
            
            /**
             *     Called by the module handler when the module has finished animating in.
             */
            public function animatedIn():void
            {
                addEditor();
                activeEditor.setCanvasSize(500, 500);
                
                // defer to give scroller a chance to initialize
                callLater(activeEditor.zoomToFit);
                
                updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);
                
                // setup the initial state
                activeEditor.updateState();
                
                alphaDisplayPane.floatPane(DisplayObject(FlexGlobals.topLevelApplication), true, true, true, null, moduleFactory);
            }
            
            /**
             *    Update the current interaction mode. 
             */
            protected function updateInteractionMode(mode:String):void
            {
                // default to the select front interaction mode
                if (!mode)
                    mode = GraphicsEditorInteractionModes.SELECT_FRONT;
                
                // reset all the toggleButtons
                selectButton.selected = selectBehindButton.selected = cropButton.selected = false;
                marqueeButton.selected = wandButton.selected = brushButton.selected = floodFillButton.selected = eraserButton.selected = false;
                blurButton.selected = sharpenButton.selected = bloatButton.selected = pinchButton.selected = distortButton.selected = false;
                textButton.selected = lineButton.selected = shapeButton.selected = false;
                zoomInButton.selected = zoomOutButton.selected = grabberButton.selected = false;
                
                // hide all tool containers
                selectionPropertiesContainer.visible = selectionPropertiesContainer.includeInLayout = false;
                transformRectContainer.visible = transformRectContainer.includeInLayout = false;
                cropContainer.visible = cropContainer.includeInLayout = false;
                marqueeContainer.visible = marqueeContainer.includeInLayout = false;
                wandContainer.visible = wandContainer.includeInLayout = false;
                cutCopyLassoContainer.visible = cutCopyLassoContainer.includeInLayout = false;
                brushContainer.visible = brushContainer.includeInLayout = false;
                floodFillContainer.visible = floodFillContainer.includeInLayout = false;
                colorsContainer.visible = colorsContainer.includeInLayout = false;
                textContainer.visible = textContainer.includeInLayout = false;
                addVectorContainer.visible = addVectorContainer.includeInLayout = false;
                vectorContainer.visible = vectorContainer.includeInLayout = false;
                
                switch (mode)
                {
                    
                    // select buttons
                    case GraphicsEditorInteractionModes.SELECT_FRONT:
                        selectButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.SELECT_FRONT;
                        selectionPropertiesContainer.visible = selectionPropertiesContainer.includeInLayout = true;
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.SELECT_BEHIND:
                        selectBehindButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.SELECT_BEHIND;
                        selectionPropertiesContainer.visible = selectionPropertiesContainer.includeInLayout = true;
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.CROP:
                        cropButton.selected = true; cropCanvasButton.enabled = false;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.CROP;
                        cropContainer.visible = cropContainer.includeInLayout = true;
                        transformRectContainer.visible = transformRectContainer.includeInLayout = true;
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.BITMAP_LASSO:
                        marqueeButton.selected = marqueeButton.enabled = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.BITMAP_LASSO;
                        marqueeContainer.visible = marqueeContainer.includeInLayout = true;
                        cutCopyLassoContainer.visible = cutCopyLassoContainer.includeInLayout = true;
                        
                        // update zoom in case zoomed in too much
                        handleZoom();
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.WAND:
                        wandButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.WAND;
                        
                        wandContainer.visible = wandContainer.includeInLayout = true;
                        cutCopyLassoContainer.visible = cutCopyLassoContainer.includeInLayout = true;
                        
                        // update zoom in case zoomed in too much
                        handleZoom();
                        
                        break;
                    
                    // bitmap buttons
                    case GraphicsEditorInteractionModes.BRUSH:
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.BRUSH;
                        
                        brushContainer.visible = brushContainer.includeInLayout = false;
                        colorsContainer.visible = colorsContainer.includeInLayout = false;
                        strokeColorContainer.visible = strokeColorContainer.includeInLayout = false;
                        fillColorContainer.visible = fillColorContainer.includeInLayout = false;
                        brushStrengthCt.visible = brushStrengthCt.includeInLayout = false;
                        brushAlphaCt.visible = brushAlphaCt.includeInLayout = false;
                        
                        switch (activeEditor.brushMode)
                        {
                            
                            case BrushModes.DRAW:
                                brushButton.selected = true;
                                activeEditor.interactionMode = GraphicsEditorInteractionModes.BRUSH;
                                activeEditor.brushShape = brushShapeSelect.selectedItem.shape;
                                activeEditor.brushStrength = brushStrengthSelect.value / 100;
                                activeEditor.brushAlpha = brushAlphaSelect.value / 100;
                                activeEditor.brushColor = strokeColorSelect.selectedColor;
                                
                                brushContainer.visible = brushContainer.includeInLayout = true;
                                brushStrengthCt.visible = brushStrengthCt.includeInLayout = true;
                                brushAlphaCt.visible = brushAlphaCt.includeInLayout = true;
                                colorsContainer.visible = colorsContainer.includeInLayout = true;
                                strokeColorContainer.visible = strokeColorContainer.includeInLayout = true;
                                
                                break;
                            
                            case BrushModes.ERASE:
                                eraserButton.selected = true;
                                brushContainer.visible = brushContainer.includeInLayout = true;
                                brushStrengthCt.visible = brushStrengthCt.includeInLayout = true;
                                brushAlphaCt.visible = brushAlphaCt.includeInLayout = true;
                                
                                break;
                            
                            case BrushModes.BLUR:
                                blurButton.selected = true;
                                brushContainer.visible = brushContainer.includeInLayout = true;
                                
                                break;
                            
                            case BrushModes.SHARPEN:
                                sharpenButton.selected = true;
                                brushContainer.visible = brushContainer.includeInLayout = true;
                                
                                break;
                            
                            case BrushModes.BLOAT:
                                bloatButton.selected = true;
                                brushContainer.visible = brushContainer.includeInLayout = true;
                                
                                break;
                            
                            case BrushModes.PINCH:
                                pinchButton.selected = true;
                                brushContainer.visible = brushContainer.includeInLayout = true;
                                
                                break;
                            
                        }
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.FLOOD_FILL:
                        floodFillButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.FLOOD_FILL;
                        
                        floodFillContainer.visible = floodFillContainer.includeInLayout = true;
                        colorsContainer.visible = colorsContainer.includeInLayout = true;
                        strokeColorContainer.visible = strokeColorContainer.includeInLayout = false;
                        fillColorContainer.visible = fillColorContainer.includeInLayout = true;
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.DISTORT:
                        distortButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.DISTORT;
                        
                        break;
                    
                    // vector buttons
                    case GraphicsEditorInteractionModes.VECTOR:
                        shapeButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.VECTOR;
                        activeEditor.shapeType = shapeTypeButtonBar.selectedItem.type;
                        
                        addVectorContainer.visible = addVectorContainer.includeInLayout = true;
                        
                        break;
                    
                    case "line":
                        lineButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.VECTOR;
                        activeEditor.shapeType = GraphicsEditorVectorTypes.LINE;
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.TEXT:
                        textButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.TEXT;
                        
                        textContainer.visible = textContainer.includeInLayout = true;
                        
                        break;
                    
                    // view buttons
                    
                    case GraphicsEditorInteractionModes.ZOOM_IN:
                        zoomInButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.ZOOM_IN;
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.ZOOM_OUT:
                        zoomOutButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.ZOOM_OUT;
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.GRABBER:
                        grabberButton.selected = true;
                        activeEditor.interactionMode = GraphicsEditorInteractionModes.GRABBER;
                        
                        break;
                    
                }
                
                activeEditorDirty = true;
                invalidateProperties();
            }
            
            /**
             *     Add a new GraphicsEditor instance and activate it.
             * 
             *     @param name the Name of the instance to add to the corresponding tab in 
             *     the TabBar.
             */
            protected function addEditor(name:String = null):void
            {
                var ct:SkinnableContainer = new SkinnableContainer();
                var ge:GraphicsEditor = new GraphicsEditor();
                ge.percentHeight = ge.percentWidth = 100;
                
                if (name)
                {
                    var label:String = name;
                }
                else
                {
                    label = "Untitled-" + untitledCounter;
                    untitledCounter++;
                }
                
                var item:Object = {
                    label: label,
                    container: ct,
                    editor: ge
                };
                
                tabBar.dataProvider.addItem(item);
                tabBar.selectedItem = item;
                viewstack.addElement(ct);
                viewstack.selectedChild = ct;
                
                ct.addElement(ge);
                
                setActiveEditor(ge);
            }
            
            /**
             *     Set the currently active and visible GraphicsEditor instance.
             * 
             *     @param editor GraphicsEditor
             */
            protected function setActiveEditor(editor:GraphicsEditor):void
            {
                if (activeEditor)
                {
                    activeEditor.removeEventListener(GraphicsEditorEvent.EDITOR_STATE_CHANGE, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.ZOOM_CHANGED, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.SELECTED_GRAPHIC_OBJECTS_CHANGED, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.ELEMENT_DRAGGING, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.ELEMENT_DRAG_END, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.TRANSFORM_DRAGGING, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.TRANSFORM_DRAG_END, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.CROP_RECTANGLE_CHANGED, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.VECTOR_OBJECT_INITIAL_DRAG, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.TEXT_EDIT_BEGIN, 
                        activeEditorHandler);
                    activeEditor.removeEventListener(GraphicsEditorEvent.BITMAP_LASSO_CHANGE, 
                        activeEditorHandler);
                    
                    miniViewport.viewport = null;
                }
                
                activeEditor = editor;
                
                // add new editor listeners
                if (activeEditor)
                {
                    activeEditor.addEventListener(GraphicsEditorEvent.EDITOR_STATE_CHANGE, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.ZOOM_CHANGED, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.SELECTED_GRAPHIC_OBJECTS_CHANGED, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.ELEMENT_DRAGGING, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.ELEMENT_DRAG_END, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.TRANSFORM_DRAGGING, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.TRANSFORM_DRAG_END, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.CROP_RECTANGLE_CHANGED, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.VECTOR_OBJECT_INITIAL_DRAG, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.TEXT_EDIT_BEGIN, 
                        activeEditorHandler);
                    activeEditor.addEventListener(GraphicsEditorEvent.BITMAP_LASSO_CHANGE, 
                        activeEditorHandler);
                    
                    miniViewport.viewport = activeEditor.viewportPart;
                    
                    updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);
                }
                
                toolbarAndMenuDirty = activeEditorDirty = transformRectDirty = true;
                
                invalidateProperties();
            }
            
            //--------------------------------------
            //  export
            //--------------------------------------
            
            /**
             *     Export the canvas of the activeEditor as a JPEG.
             */
            protected function exportJpeg():void
            {
                if (!activeEditor)
                    return;
                
                var bmd:BitmapData = activeEditor.exportBitmapData(false);
                var byteArray:ByteArray = new ByteArray(); 
                bmd.encode(new Rectangle(0, 0, bmd.width, bmd.height), new flash.display.JPEGEncoderOptions(), byteArray);
                var fileReference:FileReference = new FileReference();
                fileReference.save(byteArray, tabBar.selectedItem.label + ".jpg");
            }
            
            /**
             *     Export the canvas of the activeEditor as a lossless PNG.
             */
            protected function exportPng():void
            {
                if (!activeEditor)
                    return;
                
                var bmd:BitmapData = activeEditor.exportBitmapData();
                var byteArray:ByteArray = new ByteArray(); 
                bmd.encode(new Rectangle(0, 0, bmd.width, bmd.height), new flash.display.PNGEncoderOptions(), byteArray);
                var fileReference:FileReference = new FileReference();
                fileReference.save(byteArray, tabBar.selectedItem.label + ".png");
            }
            
            /**
             *     Apply a filter that is either applied or not, meaning there is no
             *     strength adjustment to the filter.
             * 
             *     @param type String
             */
            protected function applyStaticFilter(type:String):void
            {
                if (!activeEditor || !activeEditor.selectedGraphicObjects || 
                    activeEditor.selectedGraphicObjects.length == 0)
                    return;
                var object:BitmapGraphicObject = activeEditor.selectedGraphicObjects[0] as BitmapGraphicObject;
                if (!object)
                    return;
                
                var bmd:BitmapData = BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData;
                
                switch (type)
                {
                    
                    case "Auto Levels":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.autoLevels(bmd);
                        
                        break;
                    
                    case "Invert":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new InvertFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Sepia":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new SepiaFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Solarize":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.solarize(bmd);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Grayscale":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new GrayscaleFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Posterize":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.posterize(bmd, 5);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Brown":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new BrownFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Warm":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new WarmFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Soft Warm":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new SoftWarmFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Bubblegum":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new BubblegumFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Cool Blue":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new CoolFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Blur":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new BlurFilter());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Sharpen":
                        var filter:* = new SharpenFilter();
                        filter.strength = 10;
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), filter.clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Black and White Outline":
                        filter = new BlackWhiteOutlineFilter();
                        filter.strength = 35;
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), filter.clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Emboss":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new EmbossFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Edge Detect":
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), new EdgeDetectFilter().clone());
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Hope":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.thresholds(bmd, Vector.<ThresholdData>([
                            new ThresholdData(0xFF00324D, 0.26), 
                            new ThresholdData(0xFFD61A21, 0.52),
                            new ThresholdData(0xFF70959E, 0.68), 
                            new ThresholdData(0xFFFBE3A7, 1)
                        ]), false);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Heat Map":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.thresholds(bmd, Vector.<ThresholdData>([
                            new ThresholdData(0x0005FF, 0.0), 
                            new ThresholdData(0x00F8FF, 0.4), 
                            new ThresholdData(0x00FF0B, 0.6), 
                            new ThresholdData(0xFFF800, 0.8), 
                            new ThresholdData(0xFF0600, 1)
                        ]), true);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Predator":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.thresholds(bmd, Vector.<ThresholdData>([
                            new ThresholdData(0x0A00B2, 0.0), 
                            new ThresholdData(0xFF0000, 0.5), 
                            new ThresholdData(0xFFFC00, 1)
                        ]), true);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Brush Pen":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.thresholds(bmd, Vector.<ThresholdData>([
                            new ThresholdData(0xFF000000, 0.5), 
                            new ThresholdData(0xFFFFFFFF, 1)
                        ]), false);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Pixelate":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.pixelate(bmd, 0, -1, PixelateTypes.RECTANGLE, 5, 1, 0, 0);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Artsy":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.pixelate(bmd, 0, -1, PixelateTypes.CIRCLE, 15, -8, 1, NaN);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                    case "Vignette":
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData = BitmapAdjustments.vignette(bmd, 0.85);
                        BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                        
                        break;
                    
                }
                
                BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapDataDirty = true;
                activeEditor.updateState();
            }
            
            //--------------------------------------
            //  cut, copy, paste
            //--------------------------------------
            
            /**
             *     Copy or cut the selected object(s).
             * 
             *     @param cut Boolean
             */
            protected function copy(cut:Boolean = false):void
            {
                if (activeEditor && activeEditor.selectedGraphicObjects)
                {
                    // sort and remove by lower z to higher z so when they are pasted, they are pasted
                    // at the correct depth
                    var selectedObjects:Vector.<GraphicObjectBase> = activeEditor.getSortedSelectedObjects();
                    
                    // get transform rectangle to translate each object to a relative position
                    var transformRect:Rectangle = activeEditor.getTransformRectangle2(activeEditor.viewportPart);
                    
                    clipboard = new Vector.<GraphicObjectBase>();
                    for (var i:int = selectedObjects.length - 1; i > -1; i--)
                    {
                        var object:GraphicObjectBase = selectedObjects[i].clone();
                        clipboard.push(object);
                    }
                    if (cut)
                    {
                        activeEditor.removeSelectedGraphicObjects();
                        activeEditor.updateState();
                    }
                }
                toolbarAndMenuDirty = true;
                invalidateProperties();
            }
            
            /**
             *     Paste the clipboard object(s). 
             * 
             *     <p>Will be displayed at the position it had when it was cut, but if it is 
             *     displayed off screen, it will be moved to the upper-left corner.</p>
             */
            protected function paste():void
            {
                if (activeEditor && clipboard.length > 0)
                {
                    var selection:Vector.<GraphicObjectBase> = new Vector.<GraphicObjectBase>();
                    var visibleRect:Rectangle = activeEditor.getVisibleCanvas();
                    for each (var object:GraphicObjectBase in clipboard)
                    {
                        var newObject:GraphicObjectBase = object.clone();
                        activeEditor.addGraphicObject(newObject);
                        
                        // is the paste visible? if no, paste to upper-left of the visible canvas
                        var transformRect:Rectangle = activeEditor.getTransformRectangle2(activeEditor.canvasPart, 
                            Vector.<GraphicObjectBase>([newObject]));
                        if (!visibleRect.intersects(transformRect))
                        {
                            newObject.x = Math.round(visibleRect.x / activeEditor.zoomFactor);
                            newObject.y = Math.round(visibleRect.y / activeEditor.zoomFactor);
                        }
                        
                        selection.push(newObject);
                    }
                    
                    activeEditor.selectedGraphicObjects = selection;
                    activeEditor.updateState();
                }
            }
            
            //----------------------------------
            //  panes
            //----------------------------------
            
            /**
             *     Open the canvas properties pane.
             * 
             *     @param mode "new" or "edit"
             * 
             *     @param canvasColor NaN for transparent
             * 
             *     @param canvasWidth Number
             * 
             *     @param canvasHeight Number
             */
            protected function openCanvasPropertiesPane(mode:String = "new",
                                                        canvasColor:Number = NaN,
                                                        canvasWidth:Number = NaN, 
                                                        canvasHeight:Number = NaN):void
            {
                canvasPropertiesPane.floatPane(DisplayObject(FlexGlobals.topLevelApplication), true, true, true, null, moduleFactory);
                canvasPropertiesPane.mode = mode;
                canvasPropertiesPane.widthSelector.value = canvasWidth;
                canvasPropertiesPane.heightSelector.value = canvasHeight;
                if (canvasColor == 0xFFFFFF)
                {
                    canvasPropertiesPane.whiteColorSelect.selected = true;
                    canvasPropertiesPane.customColorSelector.selectedColor = 0xFFFFFF;
                }
                else if (isNaN(canvasColor))
                {
                    canvasPropertiesPane.transparentColorSelect.selected = true;
                }
                else
                {
                    canvasPropertiesPane.customColorSelect.selected = true;
                    canvasPropertiesPane.customColorSelector.selectedColor = canvasColor;
                }
                
                canvasPropertiesPane.addEventListener(PaneEvent.CLOSED,
                    canvasPropertiesPaneHandler);
                canvasPropertiesPane.addEventListener(PopUpEvent.CLOSE, 
                    canvasPropertiesPaneHandler);
            }
            
            /**
             *     Open the sample images pane.
             */
            protected function openSamplesPane():void
            {
                samplesPane.floatPane(DisplayObject(FlexGlobals.topLevelApplication), true, true, true, null, moduleFactory);
                samplesPane.list.selectedIndex = 0;
                
                samplesPane.addEventListener(PaneEvent.CLOSED,
                    samplesPaneHandler);
                samplesPane.addEventListener(PopUpEvent.CLOSE, 
                    samplesPaneHandler);
            }
            
            /**
             *     Open the import images pane.
             */
            protected function openImportPane():void
            {
                importPane.floatPane(DisplayObject(FlexGlobals.topLevelApplication), true, true, true, null, moduleFactory);
                importPane.list.selectedIndex = 0;
                
                importPane.addEventListener(PaneEvent.CLOSED,
                    importPaneHandler);
                importPane.addEventListener(PopUpEvent.CLOSE, 
                    importPaneHandler);
            }
            
            /**
             *     Open the filter pane for filters that have properties that
             *     can be adjusted.
             * 
             *     @param filterMode String the filter to apply
             */
            protected function openFiltersPane(filterMode:String):void
            {
                if (!activeEditor || !activeEditor.selectedGraphicObjects || 
                    activeEditor.selectedGraphicObjects.length == 0)
                    return;
                var object:BitmapGraphicObject = activeEditor.selectedGraphicObjects[0] as BitmapGraphicObject;
                if (!object)
                    return;
                
                filterFormMode = filterMode;
                
                filtersPane.floatPane(DisplayObject(FlexGlobals.topLevelApplication), true, true, true, null, moduleFactory);
                
                filtersPane.addEventListener(PaneEvent.CLOSED,
                    filtersPaneHandler);
                filtersPane.addEventListener(PopUpEvent.CLOSE, 
                    filtersPaneHandler);
                filtersPane.addEventListener("cancel", filtersPaneHandler);
                
                clonedBmd = BitmapGraphicObject(activeEditor.selectedGraphicObjects[0]).bitmapData.clone();
                
                filtersPane.brightnessContrastForm.visible = filtersPane.brightnessContrastForm.includeInLayout = false;
                filtersPane.hueSaturationForm.visible = filtersPane.hueSaturationForm.includeInLayout = false;
                filtersPane.colorBalanceForm.visible = filtersPane.colorBalanceForm.includeInLayout = false;
                
                switch (filterFormMode)
                {
                    
                    case "brightnessContrast":
                        filtersPane.brightnessContrastForm.visible = filtersPane.brightnessContrastForm.includeInLayout = true;
                        filtersPane.brightnessSelect.addEventListener(Event.CHANGE, 
                            filtersPaneHandler);
                        filtersPane.contrastSelect.addEventListener(Event.CHANGE, 
                            filtersPaneHandler);
                        
                        break;
                    
                    case "hueSaturation":
                        filtersPane.hueSaturationForm.visible = filtersPane.hueSaturationForm.includeInLayout = true;
                        filtersPane.hueSelect.addEventListener(Event.CHANGE, 
                            filtersPaneHandler);
                        filtersPane.saturationSelect.addEventListener(Event.CHANGE, 
                            filtersPaneHandler);
                        
                        break;
                    
                    case "colorBalance":
                        filtersPane.colorBalanceForm.visible = filtersPane.colorBalanceForm.includeInLayout = true;
                        filtersPane.redSelect.addEventListener(Event.CHANGE, 
                            filtersPaneHandler);
                        filtersPane.blueSelect.addEventListener(Event.CHANGE, 
                            filtersPaneHandler);
                        filtersPane.greenSelect.addEventListener(Event.CHANGE, 
                            filtersPaneHandler);
                        
                        break;
                    
                }
            }
            
            //--------------------------------------------------------------------------
            //
            //  Event handlers
            //
            //--------------------------------------------------------------------------
            
            /**
             *     @private
             */
            protected function creationCompleteHandler(event:FlexEvent):void
            {
                
                var updateStage:Function = function():void
                {
                    stage.quality = StageQuality.BEST;
                }
                callLater(updateStage);
                
                // initialize
                tabBar.dataProvider = new ArrayCollection();
                
                // setup panes to reduce latency
                canvasPropertiesPane = new CanvasPropertiesPane();
                canvasPropertiesPane.visible = false;
                addElement(canvasPropertiesPane);removeElement(canvasPropertiesPane);
                canvasPropertiesPane.visible = true;
                
                samplesPane = new SampleImagesPane();
                samplesPane.visible = false;
                addElement(samplesPane);removeElement(samplesPane);
                samplesPane.visible = true;
                
                importPane = new ImportPane();
                importPane.visible = false;
                addElement(importPane);removeElement(importPane);
                importPane.visible = true;
                
                filtersPane = new FiltersPane();
                filtersPane.visible = false;
                addElement(filtersPane);removeElement(filtersPane);
                filtersPane.visible = true;
                
                systemManager.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler, true);
                
                callLater(FlexGlobals.topLevelApplication.creationComplete);
            }
            
            /**
             *     Called when the module is removed from the stage.
             * 
             *     @param event Event
             */
            protected function removedFromStageHandler(event:Event):void
            {
                
            }
            
            /**
             *     Handles events dispatched by the active editor instance.
             * 
             *     @param event Event
             */
            protected function activeEditorHandler(event:Event):void
            {
                var graphicEvt:GraphicsEditorEvent = event as GraphicsEditorEvent;
                
                switch (event.type)
                {
                    
                    case GraphicsEditorEvent.EDITOR_STATE_CHANGE:
                        toolbarAndMenuDirty = true;
                        miniViewport.update();
                        
                        break;
                    
                    case  GraphicsEditorEvent.ZOOM_CHANGED:
                        activeEditorDirty = true;
                        miniViewport.update();
                        
                        break;
                    
                    case GraphicsEditorEvent.SELECTED_GRAPHIC_OBJECTS_CHANGED:
                        toolbarAndMenuDirty = true;
                        activeEditorDirty = true;
                        transformRectDirty = true;
                        miniViewport.update();
                        
                        break;
                    
                    case GraphicsEditorEvent.ELEMENT_DRAGGING:
                    case GraphicsEditorEvent.ELEMENT_DRAG_END:
                    case GraphicsEditorEvent.TRANSFORM_DRAGGING:
                    case GraphicsEditorEvent.TRANSFORM_DRAG_END:
                        transformRectDirty = true;
                        
                        break;
                    
                    case GraphicsEditorEvent.CROP_RECTANGLE_CHANGED:
                        transformRectDirty = true;
                        activeEditorDirty = true;
                        
                        break;
                    
                    case GraphicsEditorEvent.BITMAP_LASSO_CHANGE:
                        toolbarAndMenuDirty = true;
                        
                        break;
                    
                    case GraphicsEditorEvent.VECTOR_OBJECT_INITIAL_DRAG:
                        // select the new vector shape and change to the select
                        // interaction mode
                        activeEditor.selectedGraphicObjects = Vector.<GraphicObjectBase>([graphicEvt.graphicObject]);
                        updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);
                        
                        break;
                    
                    case GraphicsEditorEvent.TEXT_EDIT_BEGIN:
                        // make sure you are in the text mode
                        updateInteractionMode(GraphicsEditorInteractionModes.TEXT);
                        toolbarAndMenuDirty = true;
                        activeEditorDirty = true;
                        
                        break;
                    
                }
                
                invalidateProperties();
            }
            
            /**
             *     Handles changes to the alpha selector.
             * 
             *     @param event Event that triggered the handler
             */
            protected function alphaChangeHandler(event:Event):void
            {
                if (isNaN(alphaSelect.value))
                    return;
                
                for each (var element:GraphicObjectBase in activeEditor.selectedGraphicObjects)
                {
                    element.alpha = alphaSelect.value / 100;
                }
            }
            
            /**
             *     Handles changes to the rotation selector.
             * 
             *     @param event Event that triggered the handler
             */
            protected function rotationChangeHandler(event:Event):void
            {
                if (isNaN(rotationSelect.value) || !activeEditor || !activeEditor.selectedGraphicObjects || 
                    activeEditor.selectedGraphicObjects.length < 1)
                    return;
                
                // single selection, rotate to the requested value;
                if (activeEditor.selectedGraphicObjects.length == 1)
                {
                    var currentRotation:Number = GeomUtils.getRotation(activeEditor.selectedGraphicObjects[0].transform.matrix)
                    activeEditor.rotateSelectedGraphicObjects(rotationSelect.value - currentRotation);
                }
                    // multiple; rotate the full amount
                else
                {
                    activeEditor.rotateSelectedGraphicObjects(rotationSelect.value);
                }
            }
            
            /**
             *     Handles changes to the transform rect position and dimensions
             *     components.
             * 
             *     @param event Event
             */
            protected function transformChangeHandler(event:Event):void
            {
                if (!activeEditor)
                    return;
                
                var newWidth:Number = widthSelect.value;
                var newHeight:Number = heightSelect.value;
                var newX:Number = xSelect.value;
                var newY:Number = ySelect.value;
                
                switch (activeEditor.interactionMode)
                {
                    
                    case GraphicsEditorInteractionModes.SELECT_FRONT:
                    case GraphicsEditorInteractionModes.SELECT_BEHIND:
                        var rect:Rectangle = activeEditor.getTransformRectangle2(activeEditor.viewportPart, null, false);
                        
                        // avoid divide by zero
                        if (rect.width == 0 || rect.height == 0)
                            return;
                        
                        var xScale:Number = newWidth / rect.width;
                        var yScale:Number = newHeight / rect.height;
                        
                        // scale then translate
                        if (xScale != 0 || yScale != 0)
                        {
                            if (constrainTransform.selected)
                            {
                                // determine which button fired event
                                if (event.currentTarget == widthSelect)
                                    yScale = xScale;
                                else
                                    xScale = yScale;
                            }
                            
                            for each (var element:GraphicObjectBase in activeEditor.selectedGraphicObjects)
                            {
                                var matrix:Matrix = element.getLayoutMatrix();
                                matrix.scale(xScale, yScale);
                                element.setLayoutMatrix(matrix, false);
                            }
                            
                            rect = activeEditor.getTransformRectangle2(activeEditor.viewportPart, null, false);
                        }
                        
                        var xDelta:Number = newX - rect.x;
                        var yDelta:Number = newY - rect.y;
                        
                        if (xDelta != 0 || yDelta != 0)
                        {
                            for each (element in activeEditor.selectedGraphicObjects)
                            {
                                matrix = element.getLayoutMatrix();
                                matrix.translate(xDelta, yDelta);
                                matrix.tx = Math.round(matrix.tx);
                                matrix.ty = Math.round(matrix.ty);
                                element.setLayoutMatrix(matrix, false);
                            }
                        }
                        
                        activeEditor.applySelection();
                        
                        break;
                    
                    case GraphicsEditorInteractionModes.CROP:
                        if (constrainTransform.selected)
                        {
                            rect = activeEditor.cropRectangle;
                            
                            // avoid divide by zero
                            if (rect.width == 0 || rect.height == 0)
                                return;
                            
                            xScale = newWidth / rect.width;
                            yScale = newHeight / rect.height;
                            
                            if (xScale != 0 || yScale != 0)
                            {
                                // determine which button fired event
                                if (event.currentTarget == widthSelect)
                                    yScale = xScale;
                                else
                                    xScale = yScale;
                            }
                            
                            newWidth *= xScale;
                            newHeight *= yScale;
                            
                            newWidth= Math.round(newWidth);
                            newHeight= Math.round(newHeight);
                        }
                        
                        activeEditor.setCropRectangle(new Rectangle(newX, newY, newWidth, newHeight));
                        
                        break;
                    
                }
                
                transformRectDirty = true;
                invalidateProperties();
            }
            
            /**
             *     Handles events for the MenuBar.
             * 
             *     @param event Event
             */
            protected function menuBarHandler(event:MenuEvent):void
            {
                switch (event.type)
                {
                    
                    case MenuEvent.ITEM_CLICK:
                    {
                        switch (event.label)
                        {
                            case "New":
                                openCanvasPropertiesPane("new", NaN, 500, 500);
                                
                                break;
                            
                            case "Open Samples":
                                openSamplesPane();
                                
                                break;
                            
                            case "Import Samples":
                                openImportPane();
                                
                                break;
                            
                            case "Export as PNG":
                                exportPng();
                                
                                break;
                            
                            case "Export as JPEG":
                                exportJpeg();
                                
                                break;
                            
                            case "Canvas Properties":
                                if (activeEditor)
                                    openCanvasPropertiesPane("edit", activeEditor.canvasBackgroundColor, 
                                        activeEditor.canvasPart.width, activeEditor.canvasPart.height);
                                
                                break;    
                            
                            case "Undo":
                                if (activeEditor)
                                {
                                    activeEditor.undo();
                                    updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);
                                }
                                
                                break;
                            
                            case "Redo":
                                if (activeEditor)
                                {
                                    activeEditor.redo();
                                    updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);
                                }
                                
                                break;
                            
                            case "Cut":
                                copy(true);
                                
                                break;
                            
                            case "Copy":
                                copy(false);
                                
                                break;
                            
                            case "Paste":
                                paste();
                                
                                break;
                            
                            case "All":
                                if (activeEditor)
                                    activeEditor.selectAll();
                                
                                break;
                            
                            case "None":
                                if (activeEditor)
                                    activeEditor.clearSelection();
                                
                                break;
                            
                            case "Delete":
                                if (activeEditor)
                                {
                                    activeEditor.removeSelectedGraphicObjects();
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Zoom In":
                                if (activeEditor)
                                    activeEditor.zoomIn();
                                
                                break;
                            
                            case "Zoom Out":
                                if (activeEditor)
                                    activeEditor.zoomOut();
                                
                                break;
                            
                            case "Zoom To Fit":
                                if (activeEditor)
                                    activeEditor.zoomToFit();
                                
                                break;
                            
                            case "Fit Canvas":
                                if (activeEditor)
                                {
                                    activeEditor.fitCanvasToContent();
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Group":
                                if (activeEditor)
                                    activeEditor.groupSelectedGraphicObjects();
                                
                                break;
                            
                            case "Ungroup":
                                if (activeEditor)
                                    activeEditor.removeSelectedGrouping();
                                
                                break;
                            
                            case "Flatten Selection":
                                if (activeEditor)
                                {
                                    activeEditor.flattenSelectedGraphicObjects();
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Rotate 90 CW":
                                if (activeEditor)
                                {
                                    activeEditor.rotateSelectedGraphicObjects(90);
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Rotate 90 CCW":
                                if (activeEditor)
                                {
                                    activeEditor.rotateSelectedGraphicObjects(-90);
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Flip Horizontally":
                                if (activeEditor)
                                {
                                    activeEditor.flipSelectedGraphicObjects(true);
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Flip Vertically":
                                if (activeEditor)
                                {
                                    activeEditor.flipSelectedGraphicObjects(false);
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Bring to Front":
                                if (activeEditor)
                                {
                                    activeEditor.changeSelectedObjectsDepths(true, true);
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Bring Forward":
                                if (activeEditor)
                                {
                                    activeEditor.changeSelectedObjectsDepths(true, false);
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Send to Back":
                                if (activeEditor)
                                {
                                    activeEditor.changeSelectedObjectsDepths(false, true);
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Send Backward":
                                if (activeEditor)
                                {
                                    activeEditor.changeSelectedObjectsDepths(false, false);
                                    activeEditor.updateState();
                                }
                                
                                break;
                            
                            case "Brightness and Contrast":
                                if (activeEditor)
                                {
                                    // fit to screen so no filter oversize
                                    activeEditor.zoomToFit();
                                    
                                    openFiltersPane("brightnessContrast");
                                }
                                
                                break;
                            
                            case "Hue and Saturation":
                                if (activeEditor)
                                {
                                    // fit to screen so no filter oversize
                                    activeEditor.zoomToFit();
                                    
                                    openFiltersPane("hueSaturation");
                                }
                                
                                break;
                            
                            case "Color Balance":
                                if (activeEditor)
                                {
                                    // fit to screen so no filter oversize
                                    activeEditor.zoomToFit();
                                    
                                    openFiltersPane("colorBalance");
                                }
                                
                                break;
                            
                            case "Auto Levels":
                            case "Invert":
                            case "Sepia":
                            case "Solarize":
                            case "Grayscale":
                            case "Posterize":
                            case "Brown":
                            case "Warm":
                            case "Soft Warm":
                            case "Bubblegum":
                            case "Cool Blue":
                            case "Blur":
                            case "Sharpen":
                            case "Black and White Outline":
                            case "Emboss":
                            case "Edge Detect":
                            case "Hope":
                            case "Heat Map":
                            case "Predator":
                            case "Brush Pen":
                            case "Pixelate":    
                            case "Artsy":
                            case "Vignette":
                                applyStaticFilter(event.label);
                                
                                break;
                            
                        }
                        
                        break;
                        
                    }
                }
            }
            
            /**
             *     Handles events for the TabBar.
             * 
             *     @param event Event
             */
            protected function tabBarHandler(event:Event):void
            {
                switch (event.type)
                {
                    
                    case IndexChangeEvent.CHANGE:
                    {
                        viewstack.selectedChild = tabBar.selectedItem.container;
                        setActiveEditor(tabBar.selectedItem.editor)
                        
                        break;
                        
                    }
                        
                    case ButtonBarEvent.BUTTON_CLOSING:
                    {
                        var buttonEvt:ButtonBarEvent = event as ButtonBarEvent;
                        GraphicsEditor(tabBar.dataProvider[buttonEvt.indexToRemove].editor).removeAllGraphicObjects();
                        viewstack.removeElement(tabBar.dataProvider[buttonEvt.indexToRemove].container);
                        
                        // if no tabs
                        if (viewstack.numElements == 0)
                            setActiveEditor(null);
                        
                        break;
                        
                    }
                }
            }
            
            /**
             *     Handles the shape properties container controls.
             * 
             *     @param event Event
             */
            protected function vectorPropertiesHandler(event:Event):void
            {
                // only apply if a single vector graphic object is selected
                if (!activeEditor || activeEditor.selectedGraphicObjects.length != 1)
                    return;
                
                var selObject:VectorGraphicObject = activeEditor.selectedGraphicObjects[0] as VectorGraphicObject;
                
                if (!selObject)
                    return;
                
                selObject.strokeAlpha = strokeAlphaSelect.value / 100;
                selObject.strokePixelHinting = !strokeAA.selected;
                selObject.strokeWeight = strokeWeightSelect.value;
                selObject.fillAlpha = fillAlphaSelect.value / 100;
            }
            
            /**
             *     Handles the color properties container controls.
             * 
             *     @param event Event
             */
            protected function colorPropertiesHandler(event:Event):void
            {
                if (!activeEditor)
                    return;
                
                activeEditor.strokeColor = strokeColorSelect.selectedColor;
                activeEditor.fillColor = fillColorSelect.selectedColor;
                activeEditor.brushColor = strokeColorSelect.selectedColor;
                activeEditor.floodFillColor = fillColorSelect.selectedColor;
                
                // update selected 
                var selLayers:Vector.<GraphicObjectBase> = activeEditor.selectedGraphicObjects;
                if (selLayers && selLayers.length == 1 && selLayers[0] is VectorGraphicObject)
                {
                    var vecObject:VectorGraphicObject = VectorGraphicObject(selLayers[0]);
                    vecObject.strokeColor = strokeColorSelect.selectedColor;
                    if (VectorGraphicObject(vecObject).type != GraphicsEditorVectorTypes.LINE)
                    {
                        vecObject.fillAlpha = fillAlphaSelect.value / 100;
                        vecObject.fillColor = fillColorSelect.selectedColor;
                    }
                }
            }
            
            //----------------------------------
            //  pane handlers
            //----------------------------------
            
            /**
             *     Handles events for the canvas properties pane.
             * 
             *     @param event Event that triggered the handler
             */
            protected function canvasPropertiesPaneHandler(event:Event):void
            {
                switch (event.type)
                {
                    
                    case PopUpEvent.CLOSE:
                        if (canvasPropertiesPane.mode == "new")
                            addEditor();
                        activeEditor.canvasBackgroundColor = canvasPropertiesPane.whiteColorSelect.selected ? 0xFFFFFF : 
                        canvasPropertiesPane.transparentColorSelect.selected ? NaN : canvasPropertiesPane.customColorSelector.selectedColor;
                        activeEditor.setCanvasSize(canvasPropertiesPane.widthSelector.value, 
                            canvasPropertiesPane.heightSelector.value);
                        colorPickerSelect.selectedColor = activeEditor.canvasBackgroundColor;
                        activeEditor.updateState();
                        
                        break;
                    
                    case PaneEvent.CLOSED:
                        canvasPropertiesPane.removeEventListener(PaneEvent.CLOSED, 
                            canvasPropertiesPaneHandler);
                        canvasPropertiesPane.removeEventListener(PopUpEvent.CLOSE, 
                            canvasPropertiesPaneHandler);
                        
                        break;
                    
                }
                
                toolbarAndMenuDirty = true;
                invalidateProperties();
            }
            
            /**
             *     Handles events for the samples pane.
             * 
             *     @param event Event that triggered the handler
             */
            protected function samplesPaneHandler(event:Event):void
            {
                switch (event.type)
                {
                    
                    case PopUpEvent.CLOSE:
                        if (samplesPane.list.selectedIndex == 0)
                        {
                            addEditor("Ada Lovelace");
                            var bmd:BitmapData = (new AdaImage() as BitmapAsset).bitmapData;
                        }
                        else if (samplesPane.list.selectedIndex == 1)
                        {
                            addEditor("Flower");
                            bmd = (new FlowerImage() as BitmapAsset).bitmapData;
                        }
                        else if (samplesPane.list.selectedIndex == 2)
                        {
                            addEditor("Mud");
                            bmd = (new MudImage() as BitmapAsset).bitmapData;
                        }
                        else if (samplesPane.list.selectedIndex == 3)
                        {
                            addEditor("Strawberries");
                            bmd = (new StrawberriesImage() as BitmapAsset).bitmapData;
                        }
                        
                        updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);
                        activeEditor.canvasBackgroundColor = NaN;
                        activeEditor.setCanvasSize(bmd.width, bmd.height);
                        activeEditor.addBitmapGraphicObject(bmd, 0, 0);
                        activeEditor.updateState();
                        
                        break;
                    
                    case PaneEvent.CLOSED:
                        samplesPane.removeEventListener(PaneEvent.CLOSED,
                            samplesPaneHandler);
                        samplesPane.removeEventListener(PopUpEvent.CLOSE, 
                            samplesPaneHandler);
                        
                        break;
                    
                }
                
                toolbarAndMenuDirty = true;
                invalidateProperties();
            }
            
            /**
             *     Handles events for the import pane.
             * 
             *     @param event Event that triggered the handler
             */
            protected function importPaneHandler(event:Event):void
            {
                switch (event.type)
                {
                    
                    case PopUpEvent.CLOSE:
                        if (importPane.list.selectedIndex == 0)
                            var bmd:BitmapData = (new BuffaloImage() as BitmapAsset).bitmapData;
                        if (importPane.list.selectedIndex == 1)
                            bmd = (new GrapesImage() as BitmapAsset).bitmapData;
                        if (importPane.list.selectedIndex == 2)
                            bmd = (new DonutImage() as BitmapAsset).bitmapData;
                        if (importPane.list.selectedIndex == 3)
                            bmd = (new KiteImage() as BitmapAsset).bitmapData;
                        
                        var rect:Rectangle = activeEditor.getVisibleCanvas();
                        var object:BitmapGraphicObject = activeEditor.addBitmapGraphicObject(bmd, rect.x, rect.y);
                        updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);
                        activeEditor.selectedGraphicObjects = Vector.<GraphicObjectBase>([object]);
                        activeEditor.updateState();
                        
                        
                        break;
                    
                    case PaneEvent.CLOSED:
                        importPane.removeEventListener(PaneEvent.CLOSED,
                            importPaneHandler);
                        importPane.removeEventListener(PopUpEvent.CLOSE, 
                            importPaneHandler);
                        
                        break;
                    
                }
                
                toolbarAndMenuDirty = true;
                invalidateProperties();
            }
            
            /**
             *     Handles events for the filters pane.
             * 
             *     @param event Event that triggered the handler
             */
            protected function filtersPaneHandler(event:Event):void
            {
                var object:BitmapGraphicObject = activeEditor.selectedGraphicObjects[0] as BitmapGraphicObject;
                
                if (event.currentTarget == filtersPane)
                {
                    switch (event.type)
                    {
                        
                        case "cancel":
                            // restore bitmap data
                            object.bitmapData = clonedBmd;
                            
                            break;
                        
                        case PopUpEvent.CLOSE:
                            
                            
                            break;
                        
                        case PaneEvent.CLOSED:
                            filtersPane.removeEventListener(PaneEvent.CLOSED,
                                filtersPaneHandler);
                            filtersPane.removeEventListener(PopUpEvent.CLOSE, 
                                filtersPaneHandler);
                            filtersPane.removeEventListener("cancel", 
                                filtersPaneHandler);
                            
                            filtersPane.brightnessSelect.removeEventListener(Event.CHANGE, 
                                filtersPaneHandler);
                            filtersPane.contrastSelect.removeEventListener(Event.CHANGE, 
                                filtersPaneHandler);
                            filtersPane.hueSelect.removeEventListener(Event.CHANGE, 
                                filtersPaneHandler);
                            filtersPane.saturationSelect.removeEventListener(Event.CHANGE, 
                                filtersPaneHandler);
                            filtersPane.redSelect.removeEventListener(Event.CHANGE, 
                                filtersPaneHandler);
                            filtersPane.blueSelect.removeEventListener(Event.CHANGE, 
                                filtersPaneHandler);
                            filtersPane.greenSelect.removeEventListener(Event.CHANGE, 
                                filtersPaneHandler);
                            
                            filterFormMode = null;
                            clonedBmd = null;
                            
                            object.bitmapDataDirty = true;
                            activeEditor.updateState();
                            
                            break;
                        
                    }
                    
                    toolbarAndMenuDirty = true;
                    invalidateProperties();
                    
                    return;
                }
                
                switch (filterFormMode)
                {
                    
                    case "brightnessContrast":
                        var brightnessFilter:BrightnessFilter = new BrightnessFilter();
                        brightnessFilter.strength = filtersPane.brightnessSelect.value;
                        var contrastFilter:ContrastFilter = new ContrastFilter();
                        contrastFilter.strength = filtersPane.contrastSelect.value;
                        
                        var bmd:BitmapData = clonedBmd.clone();
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), brightnessFilter.clone());
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), contrastFilter.clone());
                        object.bitmapData = bmd;
                        
                        break;
                    
                    case "hueSaturation":
                        var hueFilter:HueFilter = new HueFilter();
                        hueFilter.strength = filtersPane.hueSelect.value;
                        var saturationFilter:SaturationFilter = new SaturationFilter();
                        saturationFilter.strength = filtersPane.saturationSelect.value;
                        
                        bmd = clonedBmd.clone();
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), hueFilter.clone());
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), saturationFilter.clone());
                        object.bitmapData = bmd;
                        
                        break;
                    
                    case "colorBalance":
                        var colorMatrixFilter:ColorMatrixFilter = new ColorMatrixFilter();
                        colorMatrixFilter.matrix = [
                            1, 0, 0, 0, filtersPane.redSelect.value * 255,
                            0, 1, 0, 0, filtersPane.greenSelect.value * 255,
                            0, 0, 1, 0, filtersPane.blueSelect.value * 255,
                            0, 0, 0, 1, 0
                        ];
                        
                        bmd = clonedBmd.clone();
                        bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), colorMatrixFilter);
                        object.bitmapData = bmd;
                        
                        break;
                    
                }
                
            }
            
            /**
             *     Handles keyboard keyDown events.
             * 
             *     @param event KeyboardEvent
             */
            protected function keyHandler(event:KeyboardEvent):void
            {
                if (event.ctrlKey)
                {
                    switch (event.keyCode)
                    {
                        // undo
                        case Keyboard.Z:
                            if (activeEditor)
                                activeEditor.undo();
                            
                            break;
                        
                        // redo
                        case Keyboard.Y:
                            if (activeEditor)
                                activeEditor.redo();
                            
                            break;
                        
                        // cut
                        case Keyboard.X:
                            copy(true);
                            
                            break;
                        
                        // copy
                        case Keyboard.C:
                            copy(false);
                            
                            break;
                        
                        // paste
                        case Keyboard.V:
                            paste();
                            
                            break;
                        
                    }
                }
                else
                {
                    switch (event.keyCode)
                    {
                        
                        // delete
                        case Keyboard.DELETE:
                            if (activeEditor)
                            {
                                activeEditor.removeSelectedGraphicObjects();
                                activeEditor.updateState();
                            }
                            
                            break;
                        
                    }
                }
                
            }
            
            /**
             *     Handle the zoom drop down list.
             */
            protected function handleZoom():void
            {
                if (!activeEditor)
                    return;
                
                if (zoomDropDown.selectedIndex < 0)
                    return;
                
                var proposedZoom:Number = zoomDropDown.selectedItem.zoom;
                
                // if in marquee or wand mode, make sure that the editor 
                // doesn't zoom beyond 35 megapixels because a filter is 
                // required for the marching ants animation and it can crash 
                // if too large
                if (activeEditor.interactionMode == GraphicsEditorInteractionModes.BITMAP_LASSO ||
                    activeEditor.interactionMode == GraphicsEditorInteractionModes.WAND)
                {
                    var object:BitmapGraphicObject = activeEditor.selectedGraphicObjects[0] as BitmapGraphicObject;
                    
                    var maxScale:Number = Math.sqrt(35000000 / (object.bitmapData.width * object.bitmapData.height));
                    
                    proposedZoom = Math.min(proposedZoom, maxScale);
                    activeEditor.zoomFactor = proposedZoom;
                }
                else
                {
                    activeEditor.zoomFactor = proposedZoom;
                }
            }
            
        ]]>
    </fx:Script>
    
    <!-- declarations -->
    <fx:Declarations>
        
        <pane:Pane id="alphaDisplayPane" 
                   title="Alpha Code">
            <s:Label top="20" right="20" bottom="20" left="20" 
                     text="This code is in a pre-alpha state.  This means that bugs are expected."/>
            <pane:controlBarContent>
                <s:Button label="Close"
                          click="alphaDisplayPane.closeFloatedPane();"/>
            </pane:controlBarContent>
        </pane:Pane>
        
    </fx:Declarations>
    
    <!-- states -->
    <s:states>
        <s:State name="stockholm" />
        <s:State name="london" />
        <s:State name="spark" />
    </s:states>
    
    <!-- menu bar -->
    <menuBar:MenuBar id="menuBar"
                     top="4" left="4"
                     labelField="@label"
                     itemClick="menuBarHandler(event)">
        <menuBar:dataProvider>
            <s:XMLListCollection>
                <fx:XMLList>
                    <menuitem label="File">
                        <menuitem label="New"/>
                        <menuitem type="separator"/>
                        <menuitem label="Open">
                            <menuitem label="Open Samples"/>
                            <menuitem label="Upload Image" enabled="false"/>
                        </menuitem>
                        <menuitem label="Save" enabled="false"/>
                        <menuitem label="Import">
                            <menuitem label="Import Samples"/>
                            <menuitem label="Upload Image" enabled="false"/>
                        </menuitem>
                        <menuitem label="Export as JPEG"/>
                        <menuitem label="Export as PNG"/>
                    </menuitem>
                    <menuitem label="Edit">
                        <menuitem label="Undo"/>
                        <menuitem label="Redo"/>
                        <menuitem type="separator"/>
                        <menuitem label="Cut"/>
                        <menuitem label="Copy"/>
                        <menuitem label="Paste"/>
                        <menuitem type="separator"/>
                        <menuitem label="Select">
                            <menuitem label="All"/>
                            <menuitem label="None"/>
                        </menuitem>
                        <menuitem type="separator"/>
                        <menuitem label="Delete"/>
                    </menuitem>
                    <menuitem label="View">
                        <menuitem label="Zoom In"/>
                        <menuitem label="Zoom Out"/>
                        <menuitem type="separator"/>
                        <menuitem label="Zoom To Fit"/>
                    </menuitem>
                    <menuitem label="Modify">
                        <menuitem label="Canvas Properties"/>
                        <menuitem label="Fit Canvas"/>
                        <menuitem type="separator"/>
                        <menuitem label="Group"/>
                        <menuitem label="Ungroup"/>
                        <menuitem label="Flatten Selection"/>
                        <menuitem type="separator"/>
                        <menuitem label="Rotate 90 CW"/>
                        <menuitem label="Rotate 90 CCW"/>
                        <menuitem label="Flip Horizontally"/>
                        <menuitem label="Flip Vertically"/>
                        <menuitem type="separator"/>
                        <menuitem label="Bring to Front"/>
                        <menuitem label="Bring Forward"/>
                        <menuitem label="Send to Back"/>
                        <menuitem label="Send Backward"/>
                        <menuitem type="separator"/>
                        <menuitem label="Distort"/>
                    </menuitem>
                    <menuitem label="Adjustments">
                        <menuitem label="Brightness and Contrast"/>
                        <menuitem label="Hue and Saturation"/>
                        <menuitem label="Color Balance"/>
                        <menuitem type="separator"/>
                        <menuitem label="Auto Levels"/>
                        <menuitem type="separator"/>
                        <menuitem label="Invert"/>
                        <menuitem label="Sepia"/>
                        <menuitem label="Solarize"/>
                        <menuitem label="Grayscale"/>
                        <menuitem label="Posterize"/>
                        <menuitem label="Brown"/>
                        <menuitem label="Warm"/>
                        <menuitem label="Soft Warm"/>
                        <menuitem label="Bubblegum"/>
                        <menuitem label="Cool Blue"/>
                    </menuitem>
                    <menuitem label="Filters">
                        <menuitem label="Blur"/>
                        <menuitem label="Sharpen"/>
                        <menuitem label="Black and White Outline"/>
                        <menuitem label="Emboss"/>
                        <menuitem label="Edge Detect"/>
                        <menuitem type="separator"/>
                        <menuitem label="Hope"/>
                        <menuitem label="Heat Map"/>
                        <menuitem label="Predator"/>
                        <menuitem label="Brush Pen"/>
                        <menuitem label="Pixelate"/>
                        <menuitem label="Artsy"/>
                        <menuitem type="separator"/>
                        <menuitem label="Vignette"/>
                    </menuitem>
                </fx:XMLList>
            </s:XMLListCollection>
        </menuBar:dataProvider>
    </menuBar:MenuBar>
    
    <!-- toolbar -->
    <toolbar:Toolbar top="26" right="-1" left="-1"
                     paddingTop="3" paddingRight="4" paddingBottom="4" paddingLeft="4">
        <s:HGroup verticalCenter="0" 
                  gap="2">
            <toolbar:ToolbarButton id="newDocumentButton"
                                   toolTip="New Document" 
                                   icon="@Embed(source='icons/fugue/document-image.png')"
                                   click="openCanvasPropertiesPane('new', NaN, 500, 500);"/>
            <toolbar:ToolbarButton id="openButton" 
                                   toolTip="Open Samples" 
                                   icon="@Embed(source='icons/fugue/folder-horizontal-open.png')"
                                   click="openSamplesPane()"/>
            <toolbar:ToolbarButton enabled="false" 
                                   toolTip="Save (not implemented)" 
                                   icon="@Embed(source='icons/fugue/disk-black.png')"
                                   click="openImportPane()"/>
            <toolbar:ToolbarButton id="importButton" 
                                   toolTip="Import" 
                                   icon="@Embed(source='icons/fugue/image--arrow.png')"
                                   click="openImportPane()"/>
            <toolbar:ToolbarButton id="exportButton" 
                                   toolTip="Export" 
                                   icon="@Embed(source='icons/fugue/image-export.png')"
                                   click="exportJpeg()"/>
            
            <separators:VSeparator height="100%"
                                   paddingLeft="5" paddingRight="5"/>
            
            <toolbar:ToolbarButton id="undoButton"
                                   enabled="false"
                                   toolTip="Undo"
                                   icon="@Embed(source='icons/fugue/arrow-curve-180-left.png')"
                                   click="activeEditor.undo();updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);"/>
            <toolbar:ToolbarButton id="redoButton"
                                   enabled="false"
                                   toolTip="Redo"
                                   icon="@Embed(source='icons/fugue/arrow-curve.png')"
                                   click="activeEditor.redo();updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);"/>
            
            <separators:VSeparator height="100%"
                                   paddingLeft="5" paddingRight="5"/>
            
            <toolbar:ToolbarButton id="cutButton"
                                   toolTip="Cut"
                                   icon="@Embed(source='icons/fugue/cutter.png')" 
                                   click="copy(true);"/>
            <toolbar:ToolbarButton id="copyButton"
                                   toolTip="Copy"
                                   icon="@Embed(source='icons/fugue/document-copy.png')" 
                                   click="copy(false)"/>
            <toolbar:ToolbarButton id="pasteButton"
                                   toolTip="Paste"
                                   icon="@Embed(source='icons/fugue/clipboard-paste-image.png')" 
                                   click="paste()"/>
            <toolbar:ToolbarButton id="deleteButton" 
                                   icon="@Embed(source='icons/fugue/layer--minus.png')"
                                   enabled="true"
                                   toolTip="Delete"
                                   click="activeEditor.removeSelectedGraphicObjects();activeEditor.updateState();"/>    
            
            <separators:VSeparator height="100%"
                                   paddingLeft="5" paddingRight="5"/>
            
            <toolbar:ToolbarButton id="groupGraphicObjectsButton" 
                                   icon="@Embed(source='icons/fugue/layers-group.png')"
                                   enabled="true"
                                   toolTip="Group Objects"
                                   click="activeEditor.groupSelectedGraphicObjects();"/>
            <toolbar:ToolbarButton id="unGroupGraphicObjectsButton" 
                                   icon="@Embed(source='icons/fugue/layers-ungroup.png')"
                                   enabled="true"
                                   toolTip="Ungroup Objects"
                                   click="activeEditor.removeSelectedGrouping();"/>
            <toolbar:ToolbarButton id="flattenButton" 
                                   icon="@Embed(source='icons/fugue/layer-transparent.png')"
                                   enabled="true"
                                   toolTip="Flatten Objects"
                                   click="activeEditor.flattenSelectedGraphicObjects();activeEditor.updateState();"/>
            <toolbar:ToolbarButton id="rotateClockwiseButton" 
                                   icon="@Embed(source='icons/fugue/layer-rotate.png')"
                                   enabled="true"
                                   toolTip="Rotate clockwise"
                                   click="activeEditor.rotateSelectedGraphicObjects(90);activeEditor.updateState();"/>
            <toolbar:ToolbarButton id="rotateCounterClockwiseButton" 
                                   icon="@Embed(source='icons/fugue/layer-rotate-left.png')"
                                   enabled="true"
                                   toolTip="Rotate Counter-Clockwise"
                                   click="activeEditor.rotateSelectedGraphicObjects(-90);activeEditor.updateState();"/>
            <toolbar:ToolbarButton id="flipHorizontalButton" 
                                   icon="@Embed(source='icons/fugue/layer-flip.png')"
                                   enabled="true"
                                   toolTip="Flip Horizontally"
                                   click="activeEditor.flipSelectedGraphicObjects(true);activeEditor.updateState();"/>
            <toolbar:ToolbarButton id="flipVerticalButton" 
                                   icon="@Embed(source='icons/fugue/layer-flip-vertical.png')"
                                   enabled="true"
                                   toolTip="Flip Vertically"
                                   click="activeEditor.flipSelectedGraphicObjects(false);activeEditor.updateState();"/>
            
            <separators:VSeparator height="100%"
                                   paddingLeft="5" paddingRight="5"/>
            
            <toolbar:ToolbarButton id="moveToFrontButton" 
                                   icon="@Embed(source='icons/fugue/layers-stack-arrange.png')"
                                   enabled="true"
                                   toolTip="Bring To Front"
                                   click="activeEditor.changeSelectedObjectsDepths(true, true);activeEditor.updateState();"/>
            <toolbar:ToolbarButton id="moveForwardButton" 
                                   icon="@Embed(source='icons/fugue/layers-arrange.png')"
                                   enabled="true"
                                   toolTip="Bring Forward"
                                   click="activeEditor.changeSelectedObjectsDepths(true, false);activeEditor.updateState();"/>
            <toolbar:ToolbarButton id="moveToBackButton" 
                                   icon="@Embed(source='icons/fugue/layers-stack-arrange-back.png')"
                                   enabled="true"
                                   toolTip="Send To Back"
                                   click="activeEditor.changeSelectedObjectsDepths(false, true);activeEditor.updateState();"/>
            <toolbar:ToolbarButton id="moveBackwardButton" 
                                   icon="@Embed(source='icons/fugue/layers-arrange-back.png')"
                                   enabled="true"
                                   toolTip="Send Backward"
                                   click="activeEditor.changeSelectedObjectsDepths(false, false);activeEditor.updateState();"/>
            
        </s:HGroup>
        
        <s:HGroup right="0" 
                  verticalCenter="0"
                  verticalAlign="middle">
            <colorPicker:ColorPicker id="colorPickerSelect" 
                                     selectedColor="#FFFFFF"
                                     enableOutsideHoverColorSelect="true"
                                     showTransparency="true" showColorSpacePicker="true"
                                     change="activeEditor.setCanvasColor(colorPickerSelect.selectedColor);activeEditor.updateState();"/>
            <s:Button id="canvasPropertiesButton" 
                      label="Properties" 
                      width="90"
                      click="openCanvasPropertiesPane('edit', activeEditor.canvasBackgroundColor, activeEditor.canvasPart.width, activeEditor.canvasPart.height);"/>
            <s:Button id="fitCanvasButton" 
                      label="Fit Canvas" 
                      width="90"
                      click="activeEditor.fitCanvasToContent();activeEditor.updateState();"/>
            <separators:VSeparator height="100%"
                                   paddingLeft="5" paddingRight="5"/>
            <s:DropDownList id="zoomDropDown" 
                            width="90"
                            selectedIndex="6"
                            labelField="label"
                            change="handleZoom();">
                <s:layout>
                    <s:VerticalLayout gap="0" 
                                      horizontalAlign="contentJustify" 
                                      requestedMinRowCount="16" />
                </s:layout>
                <s:ArrayCollection>
                    <fx:Object label="5%" zoom=".05"/>
                    <fx:Object label="10%" zoom=".1"/>
                    <fx:Object label="25%" zoom=".25"/>
                    <fx:Object label="50%" zoom=".5"/>
                    <fx:Object label="66%" zoom=".66"/>
                    <fx:Object label="75%" zoom=".75"/>
                    <fx:Object label="100%" zoom="1.0"/>
                    <fx:Object label="150%" zoom="1.5"/>
                    <fx:Object label="200%" zoom="2"/>
                    <fx:Object label="300%" zoom="3"/>
                    <fx:Object label="400%" zoom="4"/>
                    <fx:Object label="500%" zoom="5"/>
                    <fx:Object label="800%" zoom="8"/>
                    <fx:Object label="1600%" zoom="16"/>
                    <fx:Object label="3200%" zoom="32"/>
                    <fx:Object label="6400%" zoom="64"/>
                </s:ArrayCollection>
            </s:DropDownList>
            <s:Button id="zoomToFitButton"
                      width="90"
                      label="Zoom To Fit"
                      click="activeEditor.zoomToFit();"/>
        </s:HGroup>
        
    </toolbar:Toolbar>
    
    <compassContainer:CompassContainer id="cc"
                                       top="58" right="-1" bottom="-1" left="-1"
                                       gap="-1" resizeRegionWidth="6"
                                       westWidth="240"
                                       westRegionTitle="Tools"
                                       centerBorderVisible="true" showCenterChrome="false"
                                       westBackgroundColor="#EEEEEE">
        
        <!--- west -->
        <compassContainer:westContent>
            <scroller:Scroller top="-1" right="0" bottom="0" left="0"
                               top.london="-2"
                               focusEnabled="true">
                
                <s:VGroup gap="-1"
                          horizontalAlign="contentJustify">
                    
                    <!--- preview -->
                    <expandingContainer:ExpandingContainer label="Preview"
                                                           open="true">
                        <s:Group width="100%" height="120">
                            <miniViewport:MiniViewport id="miniViewport" 
                                                       top="5"
                                                       width="100%" height="110"
                                                       borderVisible="false"/>
                        </s:Group>
                    </expandingContainer:ExpandingContainer>
                    
                    <!--- mode -->
                    <expandingContainer:ExpandingContainer label="Mode"
                                                           open="true">
                        <s:VGroup width="100%" 
                                  horizontalAlign="justify"
                                  paddingTop="10" paddingBottom="20"
                                  gap="5">
                            
                            <!--- mode buttons -->
                            <s:VGroup verticalAlign="middle"
                                      horizontalAlign="justify"
                                      gap="3"
                                      paddingRight="10" paddingBottom="2" paddingLeft="15">
                                <s:HGroup gap="1" 
                                          verticalAlign="middle">
                                    <s:Label width="45" 
                                             text="Select:"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="selectButton"
                                                                                   toolTip="Select"
                                                                                   icon="@Embed(source='icons/fugue/cursor.png')"
                                                                                   change="updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT)"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="selectBehindButton"
                                                                                   toolTip="Select Behind"
                                                                                   icon="@Embed(source='icons/fugue/cursor-behind.png')"
                                                                                   change="updateInteractionMode(GraphicsEditorInteractionModes.SELECT_BEHIND)"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="cropButton"
                                                                                   toolTip="Crop"
                                                                                   icon="@Embed(source='icons/fugue/image-crop.png')"
                                                                                   change="updateInteractionMode(GraphicsEditorInteractionModes.CROP)"/>
                                </s:HGroup>
                                
                                <s:HGroup gap="1" 
                                          verticalAlign="top">
                                    <s:Label width="45" 
                                             text="Bitmap:"
                                             paddingTop="6"/>
                                    <s:VGroup gap="1">
                                        <s:HGroup gap="1">
                                            <toolbar:ToolbarColorTransformIconToggleButton id="marqueeButton"
                                                                                           toolTip="Marquee Tool"
                                                                                           icon="@Embed(source='icons/fugue/selection.png')"
                                                                                           change="updateInteractionMode(GraphicsEditorInteractionModes.BITMAP_LASSO)" />
                                            <toolbar:ToolbarColorTransformIconToggleButton id="wandButton"
                                                                                           toolTip="Wand Tool"
                                                                                           icon="@Embed(source='icons/fugue/wand.png')"
                                                                                           change="updateInteractionMode(GraphicsEditorInteractionModes.WAND)" />
                                            <toolbar:ToolbarColorTransformIconToggleButton id="brushButton"
                                                                                           toolTip="Brush Tool"
                                                                                           icon="@Embed(source='icons/fugue/palette-paint-brush.png')"
                                                                                           change="activeEditor.brushMode=BrushModes.DRAW;updateInteractionMode(GraphicsEditorInteractionModes.BRUSH);" />
                                            <toolbar:ToolbarColorTransformIconToggleButton id="floodFillButton"
                                                                                           toolTip="Floodfill Tool"
                                                                                           icon="@Embed(source='icons/fugue/paint-can.png')"
                                                                                           change="updateInteractionMode(GraphicsEditorInteractionModes.FLOOD_FILL);"/>
                                            <toolbar:ToolbarColorTransformIconToggleButton id="eraserButton"
                                                                                           toolTip="Eraser Tool"
                                                                                           icon="@Embed(source='icons/fugue/eraser.png')"
                                                                                           change="activeEditor.brushMode=BrushModes.ERASE;updateInteractionMode(GraphicsEditorInteractionModes.BRUSH);"/>
                                        </s:HGroup>
                                        <s:HGroup gap="1">
                                            <toolbar:ToolbarColorTransformIconToggleButton id="blurButton" 
                                                                                           toolTip="Blur" 
                                                                                           icon="@Embed(source='icons/fugue/water.png')"
                                                                                           change="activeEditor.brushMode=BrushModes.BLUR;updateInteractionMode(GraphicsEditorInteractionModes.BRUSH)"/>
                                            <toolbar:ToolbarColorTransformIconToggleButton id="sharpenButton" 
                                                                                           toolTip="Sharpen" 
                                                                                           icon="@Embed(source='icons/sharpen.png')"
                                                                                           change="activeEditor.brushMode=BrushModes.SHARPEN;updateInteractionMode(GraphicsEditorInteractionModes.BRUSH)"/>
                                            <toolbar:ToolbarColorTransformIconToggleButton id="bloatButton" 
                                                                                           toolTip="Bloat" 
                                                                                           icon="@Embed(source='icons/bloat.png')"
                                                                                           change="activeEditor.brushMode=BrushModes.BLOAT;updateInteractionMode(GraphicsEditorInteractionModes.BRUSH)"/>
                                            <toolbar:ToolbarColorTransformIconToggleButton id="pinchButton" 
                                                                                           toolTip="Pinch" 
                                                                                           icon="@Embed(source='icons/pinch.png')"
                                                                                           change="activeEditor.brushMode=BrushModes.PINCH;updateInteractionMode(GraphicsEditorInteractionModes.BRUSH)"/>
                                            <toolbar:ToolbarColorTransformIconToggleButton id="distortButton" 
                                                                                           toolTip="Distort" 
                                                                                           icon="@Embed(source='icons/fugue/distort.png')"
                                                                                           change="updateInteractionMode(GraphicsEditorInteractionModes.DISTORT)"/>
                                        </s:HGroup>
                                    </s:VGroup>
                                </s:HGroup>
                                
                                <s:HGroup gap="1" 
                                          verticalAlign="middle">
                                    <s:Label width="45" 
                                             text="Vector:"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="shapeButton"
                                                                                   toolTip="Add Shape"
                                                                                   icon="@Embed(source='icons/fugue/layer-select.png')"
                                                                                   change="updateInteractionMode(GraphicsEditorInteractionModes.VECTOR)"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="lineButton"
                                                                                   toolTip="Add Line"
                                                                                   icon="@Embed(source='icons/fugue/layer-shape-line.png')"
                                                                                   change="updateInteractionMode('line')"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="textButton"
                                                                                   toolTip="Add Text"
                                                                                   icon="@Embed(source='icons/fugue/edit.png')"
                                                                                   change="updateInteractionMode(GraphicsEditorInteractionModes.TEXT)"/>
                                </s:HGroup>
                                
                                <s:HGroup gap="1" 
                                          verticalAlign="middle">
                                    <s:Label width="45" 
                                             text="View:"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="zoomInButton" 
                                                                                   toolTip="Zoom In"
                                                                                   icon="@Embed(source='icons/fugue/magnifier-zoom-in.png')"
                                                                                   change="updateInteractionMode(GraphicsEditorInteractionModes.ZOOM_IN)"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="zoomOutButton"
                                                                                   toolTip="Zoom Out"
                                                                                   icon="@Embed(source='icons/fugue/magnifier-zoom-out.png')"
                                                                                   change="updateInteractionMode(GraphicsEditorInteractionModes.ZOOM_OUT)"/>
                                    <toolbar:ToolbarColorTransformIconToggleButton id="grabberButton"
                                                                                   toolTip="Grabber"
                                                                                   icon="@Embed(source='icons/fugue/hand.png')"
                                                                                   change="updateInteractionMode(GraphicsEditorInteractionModes.GRABBER)"/>
                                </s:HGroup>
                            </s:VGroup>
                            
                            <!--- text container -->
                            <s:SkinnableContainer id="textContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15"
                                          gap="4"
                                          paddingBottom="2">
                                    <s:Label text="Text Properties"
                                             fontWeight="bold"/>
                                    <richTextEditor:RichTextEditor id="rte" 
                                                                   focusEnabled="false"
                                                                   selectionHighlighting="whenFocused"
                                                                   skinClass="components.graphicsEditor.skins.RichTextEditorSkin"/>
                                </s:VGroup>
                            </s:SkinnableContainer>
                            
                            
                            <!--- selection properties -->
                            <s:SkinnableContainer id="selectionPropertiesContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15"
                                          gap="14"
                                          paddingBottom="2">
                                    <s:VGroup gap="4">
                                        <s:Label text="Transform Type"
                                                 fontWeight="bold"/>
                                        <s:HGroup gap="1">
                                            <s:ButtonBar id="transformTypeButtonBar"
                                                         width="49"
                                                         requireSelection="true"
                                                         selectedIndex="0"
                                                         iconField="icon" labelField=""
                                                         change="activeEditor.transformConstrainProportions=transformTypeButtonBar.selectedIndex == 1"
                                                         skinClass.stockholm="components.graphicsEditor.skins.SmallButtonBarStockholm"
                                                         skinClass.london="components.graphicsEditor.skins.SmallButtonBarLondon">
                                                <s:layout>
                                                    <s:ButtonBarHorizontalLayout gap="1"/>
                                                </s:layout>
                                                <s:dataProvider>
                                                    <mx:ArrayCollection>
                                                        <fx:Object toolTip="Free Transform" icon="@Embed(source='icons/fugue/layer-select.png')"/>
                                                        <fx:Object toolTip="Scale" icon="@Embed(source='icons/fugue/image-resize.png')"/>
                                                    </mx:ArrayCollection>
                                                </s:dataProvider>
                                            </s:ButtonBar>
                                        </s:HGroup>
                                    </s:VGroup>
                                    <s:VGroup id="alphaRotationContainer" 
                                              gap="4">
                                        <s:Label id="selectionDescriptionLabel"
                                                 fontWeight="bold"
                                                 paddingBottom="5"/>
                                        
                                        <s:HGroup verticalAlign="middle">
                                            <s:Label width="65" 
                                                     text="Rotation:"/>
                                            <rotaryField:RotaryField id="rotationSelect"
                                                                     width="50"
                                                                     change="rotationChangeHandler(event);" />
                                        </s:HGroup>
                                        <s:HGroup verticalAlign="middle">
                                            <s:Label width="65" 
                                                     text="Alpha:"/>
                                            <sliderField:SliderField id="alphaSelect"
                                                                     width="50"
                                                                     minimum="0" maximum="100" value="100"
                                                                     change="alphaChangeHandler(event)"/>
                                        </s:HGroup>
                                    </s:VGroup>
                                </s:VGroup>
                            </s:SkinnableContainer>
                            
                            <!--- crop -->
                            <s:SkinnableContainer id="cropContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:Button id="cropCanvasButton" 
                                          top="14" bottom="6" left="15"
                                          label="Crop Canvas"
                                          click="activeEditor.crop();"/>
                            </s:SkinnableContainer>
                            
                            <!--- bitmap lasso -->
                            <s:SkinnableContainer id="marqueeContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15"
                                          gap="4"
                                          paddingBottom="2">
                                    <s:Label text="Lasso Shape"
                                             fontWeight="bold"
                                             paddingTop="4"/>
                                    <s:ButtonBar id="marqueeShapeSelect"
                                                 width="49"
                                                 requireSelection="true"
                                                 selectedIndex="0"
                                                 iconField="icon" labelField=""
                                                 change="activeEditor.bitmapLassoShape=marqueeShapeSelect.selectedItem.shape"
                                                 skinClass.stockholm="components.graphicsEditor.skins.SmallButtonBarStockholm"
                                                 skinClass.london="components.graphicsEditor.skins.SmallButtonBarLondon">
                                        <s:layout>
                                            <s:ButtonBarHorizontalLayout gap="1"/>
                                        </s:layout>
                                        <s:dataProvider>
                                            <mx:ArrayCollection>
                                                <fx:Object shape="ellipse" toolTip="Ellipse" icon="@Embed(source='icons/circle.png')"/>
                                                <fx:Object shape="rectangle" toolTip="Rectangle" icon="@Embed(source='icons/square.png')"/>
                                            </mx:ArrayCollection>
                                        </s:dataProvider>
                                    </s:ButtonBar>
                                    
                                </s:VGroup>
                                
                            </s:SkinnableContainer>
                            
                            <!--- wand -->
                            <s:SkinnableContainer id="wandContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15"
                                          gap="4"
                                          paddingBottom="2">
                                    <s:Label text="Wand Properties"
                                             fontWeight="bold"
                                             paddingBottom="5"/>
                                    <s:HGroup verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Tolerance:"/>
                                        <sliderField:SliderField id="wandToleranceSelect"
                                                                 width="50"
                                                                 minimum="0" maximum="255" value="25"
                                                                 change="activeEditor.wandFillTolerance=wandToleranceSelect.value"/>
                                    </s:HGroup>
                                    <s:HGroup verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Anti-Alias:"/>
                                        <s:CheckBox id="wandAASelect"
                                                    selected="true"
                                                    change="activeEditor.wandAntiAlias=wandAASelect.selected"/>
                                    </s:HGroup>
                                </s:VGroup>
                            </s:SkinnableContainer>
                            
                            <!--- cut / copy options-->
                            <s:SkinnableContainer id="cutCopyLassoContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:HGroup top="14" left="15">
                                    <s:Button id="cutLassosButton" 
                                              width="80"
                                              label="Cut"
                                              click="activeEditor.copyBitmapLasso(true);updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);"/>
                                    <s:Button id="copyLassosButton" 
                                              width="80"
                                              label="Copy"
                                              click="activeEditor.copyBitmapLasso();updateInteractionMode(GraphicsEditorInteractionModes.SELECT_FRONT);"/>
                                </s:HGroup>
                            </s:SkinnableContainer>
                            
                            <!--- brush -->
                            <s:SkinnableContainer id="brushContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15"
                                          gap="4"
                                          paddingBottom="2">
                                    <s:Label text="Brush Properties"
                                             fontWeight="bold"
                                             paddingTop="4"/>
                                    <s:HGroup verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Shape:"/>
                                        <s:ButtonBar id="brushShapeSelect"
                                                     width="49"
                                                     requireSelection="true"
                                                     selectedIndex="0"
                                                     iconField="icon" labelField=""
                                                     change="activeEditor.brushShape=brushShapeSelect.selectedItem.shape"
                                                     skinClass.stockholm="components.graphicsEditor.skins.SmallButtonBarStockholm"
                                                     skinClass.london="components.graphicsEditor.skins.SmallButtonBarLondon">
                                            <s:layout>
                                                <s:ButtonBarHorizontalLayout gap="1"/>
                                            </s:layout>
                                            <s:dataProvider>
                                                <mx:ArrayCollection>
                                                    <fx:Object shape="circle" toolTip="Circle Brush" icon="@Embed(source='icons/circle.png')"/>
                                                    <fx:Object shape="square" toolTip="Square Brush" icon="@Embed(source='icons/square.png')"/>
                                                </mx:ArrayCollection>
                                            </s:dataProvider>
                                        </s:ButtonBar>
                                    </s:HGroup>
                                    <s:HGroup verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Size:"/>
                                        <sliderField:SliderField id="brushSizeSelect"
                                                                 width="50"
                                                                 minimum="2" maximum="150" value="50"
                                                                 change="activeEditor.brushSize=brushSizeSelect.value"/>
                                    </s:HGroup>
                                    <s:HGroup id="brushStrengthCt" 
                                              verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Hardness:"/>
                                        <sliderField:SliderField id="brushStrengthSelect"
                                                                 width="50"
                                                                 minimum="1" maximum="100" value="50"
                                                                 change="activeEditor.brushStrength=brushStrengthSelect.value / 100" />
                                    </s:HGroup>
                                    <s:HGroup id="brushAlphaCt"
                                              verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Alpha:"/>
                                        <sliderField:SliderField id="brushAlphaSelect"
                                                                 width="50"
                                                                 minimum="1" maximum="100" value="50"
                                                                 change="activeEditor.brushAlpha=brushAlphaSelect.value / 100"/>
                                    </s:HGroup>
                                </s:VGroup>
                            </s:SkinnableContainer>
                            
                            <!--- flood fill -->
                            <s:SkinnableContainer id="floodFillContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15"
                                          gap="4"
                                          paddingBottom="2">
                                    <s:Label text="Flood Fill Properties"
                                             fontWeight="bold"
                                             paddingBottom="5"/>
                                    <s:HGroup verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Tolerance:"/>
                                        <sliderField:SliderField id="floodFillToleranceSelect"
                                                                 width="50"
                                                                 minimum="1" maximum="255" value="10"
                                                                 change="activeEditor.floodFillTolerance=floodFillToleranceSelect.value"/>
                                    </s:HGroup>
                                    <s:HGroup verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Anti-Alias:"/>
                                        <s:CheckBox id="floodFillAASelect"
                                                    selected="true"
                                                    change="activeEditor.floodFillAntiAlias=floodFillAASelect.selected"/>
                                    </s:HGroup>
                                    <s:HGroup verticalAlign="middle">
                                        <s:Label width="65" 
                                                 text="Alpha:"/>
                                        <sliderField:SliderField id="floodFillAlphaSelect"
                                                                 width="50"
                                                                 minimum="1" maximum="100" value="50"
                                                                 change="activeEditor.floodFillAlpha=floodFillAlphaSelect.value / 100"/>
                                    </s:HGroup>
                                </s:VGroup>
                            </s:SkinnableContainer>
                            
                            <!--- add vector container -->
                            <s:SkinnableContainer id="addVectorContainer">
                                <separators:HSeparator width="100%" 
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15" bottom="2"
                                          gap="4">
                                    <s:Label text="Shape Type"
                                             fontWeight="bold"/>
                                    <s:HGroup gap="1">
                                        <s:ButtonBar id="shapeTypeButtonBar"
                                                     width="49"
                                                     requireSelection="true"
                                                     selectedIndex="0"
                                                     iconField="icon" labelField=""
                                                     change="activeEditor.shapeType=shapeTypeButtonBar.selectedItem.type"
                                                     skinClass.stockholm="components.graphicsEditor.skins.SmallButtonBarStockholm"
                                                     skinClass.london="components.graphicsEditor.skins.SmallButtonBarLondon">
                                            <s:layout>
                                                <s:ButtonBarHorizontalLayout gap="1"/>
                                            </s:layout>
                                            <s:dataProvider>
                                                <mx:ArrayCollection>
                                                    <fx:Object type="rectangle" toolTip="Free Transform" icon="@Embed(source='icons/fugue/layer-select.png')"/>
                                                    <fx:Object type="ellipse" toolTip="Scale" icon="@Embed(source='icons/fugue/layer-shape-ellipse.png')"/>
                                                </mx:ArrayCollection>
                                            </s:dataProvider>
                                        </s:ButtonBar>
                                    </s:HGroup>
                                </s:VGroup>
                            </s:SkinnableContainer>
                            
                            <!--- vector properties -->
                            <s:SkinnableContainer id="vectorContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15"
                                          gap="14">
                                    <s:VGroup gap="4">
                                        <s:Label text="Stroke Properties:"
                                                 fontWeight="bold"
                                                 paddingBottom="2"/>
                                        <s:HGroup variableColumnWidth="true"
                                                  verticalAlign="middle">
                                            <s:Label width="65"
                                                     text="Weight:"/>
                                            <sliderField:SliderField id="strokeWeightSelect"
                                                                     width="50"
                                                                     minimum="1" maximum="100" value="1"
                                                                     change="vectorPropertiesHandler(event)"/>
                                        </s:HGroup>
                                        <s:HGroup variableColumnWidth="true"
                                                  verticalAlign="middle">
                                            <s:Label width="65"
                                                     text="Anti-Alias:"/>
                                            <s:CheckBox id="strokeAA"
                                                        selected="false"
                                                        change="vectorPropertiesHandler(event)"/>
                                        </s:HGroup>
                                        <s:HGroup verticalAlign="middle">
                                            <s:Label width="65" 
                                                     text="Alpha:"/>
                                            <sliderField:SliderField id="strokeAlphaSelect"
                                                                     width="50"
                                                                     minimum="0" maximum="100" value="100"
                                                                     change="vectorPropertiesHandler(event)"/>
                                        </s:HGroup>
                                    </s:VGroup>
                                    <s:VGroup id="fillPropertiesContainer" 
                                              gap="4">
                                        <s:Label text="Fill Properties:"
                                                 fontWeight="bold"
                                                 paddingBottom="2"/>
                                        <s:HGroup verticalAlign="middle">
                                            <s:Label width="65" 
                                                     text="Alpha:"/>
                                            <sliderField:SliderField id="fillAlphaSelect"
                                                                     width="50"
                                                                     minimum="0" maximum="100" value="100"
                                                                     change="vectorPropertiesHandler(event)"/>
                                        </s:HGroup>
                                    </s:VGroup>
                                </s:VGroup>
                                
                            </s:SkinnableContainer>
                            
                            <!--- colors -->
                            <s:SkinnableContainer id="colorsContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="10" left="15" bottom="2"
                                          gap="4">
                                    <s:HGroup id="strokeColorContainer" 
                                              variableColumnWidth="true"
                                              verticalAlign="middle">
                                        <s:Label width="65"
                                                 text="Stroke:"/>
                                        <colorPicker:ColorPicker id="strokeColorSelect"
                                                                 enableOutsideHoverColorSelect="true"
                                                                 showTransparency="true"
                                                                 showColorSpacePicker="true"
                                                                 selectedColor="#000000"
                                                                 change="colorPropertiesHandler(event);"/>
                                    </s:HGroup>
                                    <s:HGroup id="fillColorContainer" 
                                              variableColumnWidth="true"
                                              verticalAlign="middle">
                                        <s:Label width="65"
                                                 text="Fill:"/>
                                        <colorPicker:ColorPicker id="fillColorSelect"
                                                                 enableOutsideHoverColorSelect="true"
                                                                 showTransparency="true"
                                                                 showColorSpacePicker="true"
                                                                 selectedColor="#FFFFFF"
                                                                 change="colorPropertiesHandler(event);"/>
                                    </s:HGroup>
                                </s:VGroup>
                            </s:SkinnableContainer>
                            
                            <!--- transform rectangle -->
                            <s:SkinnableContainer id="transformRectContainer">
                                <separators:HSeparator width="100%"
                                                       paddingTop="0" paddingBottom="0"/>
                                <s:VGroup top="14" left="15" 
                                          gap="4"
                                          horizontalAlign="justify">
                                    <s:Label text="Transform Rectangle"
                                             fontWeight="bold"/>
                                    <s:CheckBox id="constrainTransform" 
                                                label="Constrain Proportions"
                                                selected="false"/>
                                    <s:HGroup variableColumnWidth="true"
                                              verticalAlign="middle">
                                        <s:Label width="12"
                                                 text="X:"/>
                                        <s:NumericStepper id="xSelect" 
                                                          width="65"
                                                          minimum="-5000" maximum="5000"
                                                          change="transformChangeHandler(event)"/>
                                        <s:Label width="17"
                                                 text="W:"
                                                 textAlign="right"/>
                                        <s:NumericStepper id="widthSelect" 
                                                          width="65"
                                                          minimum="0" maximum="5000"
                                                          change="transformChangeHandler(event)"/>
                                    </s:HGroup>
                                    <s:HGroup variableColumnWidth="true"
                                              verticalAlign="middle">
                                        <s:Label width="12"
                                                 text="Y:"/>
                                        <s:NumericStepper id="ySelect" 
                                                          width="65"
                                                          minimum="-5000" maximum="5000"
                                                          change="transformChangeHandler(event)"/>
                                        <s:Label width="17"
                                                 text="H:"
                                                 textAlign="right"/>
                                        <s:NumericStepper id="heightSelect" 
                                                          width="65"
                                                          minimum="0" maximum="5000"
                                                          change="transformChangeHandler(event)"/>
                                    </s:HGroup>
                                </s:VGroup>
                            </s:SkinnableContainer>
                            
                        </s:VGroup>
                    </expandingContainer:ExpandingContainer>
                    
                </s:VGroup>
                
            </scroller:Scroller>
        </compassContainer:westContent>
        
        <!--- center -->
        <s:VGroup top="-1" right="-1" bottom="-1" left="-1"
                  horizontalAlign="justify"
                  gap="-1">
            
            <buttonBar:TabBar id="tabBar"
                              height="30"
                              depth="1"
                              labelField="label"
                              skinClass="components.graphicsEditor.skins.TabBarSkin"
                              buttonClosing="tabBarHandler(event)"
                              change="tabBarHandler(event)">
                <buttonBar:layout>
                    <layouts:ButtonBarLayout gap="-1"
                                             usePreferredWidth="true"/>
                </buttonBar:layout>
            </buttonBar:TabBar>
            
            <viewStack:ViewStack id="viewstack"
                                 width="100%" height="100%"
                                 backgroundColor="#DDDDDD"
                                 borderVisible="true"/>
            
        </s:VGroup>
        
    </compassContainer:CompassContainer>
    
</s:Module>