////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You 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.
//
////////////////////////////////////////////////////////////////////////////////

package spark.components 
{

import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.geom.Rectangle;
import flash.utils.Dictionary;

import mx.core.FlexVersion;
import mx.core.IFlexModule;
import mx.core.IFontContextComponent;
import mx.core.IUIComponent;
import mx.core.IUITextField;
import mx.core.IVisualElement;
import mx.core.IVisualElementContainer;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.graphics.shaderClasses.ColorBurnShader;
import mx.graphics.shaderClasses.ColorDodgeShader;
import mx.graphics.shaderClasses.ColorShader;
import mx.graphics.shaderClasses.ExclusionShader;
import mx.graphics.shaderClasses.HueShader;
import mx.graphics.shaderClasses.LuminosityShader;
import mx.graphics.shaderClasses.SaturationShader;
import mx.graphics.shaderClasses.SoftLightShader;
import mx.styles.AdvancedStyleClient;
import mx.styles.IAdvancedStyleClient;
import mx.styles.ISimpleStyleClient;
import mx.styles.IStyleClient;
import mx.styles.StyleProtoChain;

import spark.components.supportClasses.GroupBase;
import spark.core.DisplayObjectSharingMode;
import spark.core.IGraphicElement;
import spark.core.IGraphicElementContainer;
import spark.core.ISharedDisplayObject;
import spark.events.ElementExistenceEvent;

use namespace mx_internal;

//--------------------------------------
//  Events
//--------------------------------------

/**
 *  Dispatched when a visual element is added to the content holder.
 *  <code>event.element</code> is the visual element that was added.
 *
 *  @eventType spark.events.ElementExistenceEvent.ELEMENT_ADD
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="elementAdd", type="spark.events.ElementExistenceEvent")]

/**
 *  Dispatched when a visual element is removed from the content holder.
 *  <code>event.element</code> is the visual element that's being removed.
 *
 *  @eventType spark.events.ElementExistenceEvent.ELEMENT_REMOVE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="elementRemove", type="spark.events.ElementExistenceEvent")]

//--------------------------------------
//  Styles
//--------------------------------------

/**
 *  Color of text shadows.
 * 
 *  @default #FFFFFF
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="textShadowColor", type="uint", format="Color", inherit="yes", theme="mobile")]

/**
 *  Alpha of text shadows.
 * 
 *  @default 0.55
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="textShadowAlpha", type="Number",inherit="yes", minValue="0.0", maxValue="1.0", theme="mobile")]

//--------------------------------------
//  Excluded APIs
//--------------------------------------

[Exclude(name="addChild", kind="method")]
[Exclude(name="addChildAt", kind="method")]
[Exclude(name="removeChild", kind="method")]
[Exclude(name="removeChildAt", kind="method")]
[Exclude(name="setChildIndex", kind="method")]
[Exclude(name="swapChildren", kind="method")]
[Exclude(name="swapChildrenAt", kind="method")]
[Exclude(name="numChildren", kind="property")]
[Exclude(name="getChildAt", kind="method")]
[Exclude(name="getChildIndex", kind="method")]

//--------------------------------------
//  Other metadata
//--------------------------------------

[ResourceBundle("components")]

[DefaultProperty("mxmlContent")] 

[IconFile("Group.png")]

/**
 *  The Group class is the base container class for visual elements.
 *  The Group container takes as children any components that implement 
 *  the IUIComponent interface, and any components that implement 
 *  the IGraphicElement interface. 
 *  Use this container when you want to manage visual children, 
 *  both visual components and graphical components. 
 *
 *  <p>To improve performance and minimize application size, 
 *  the Group container cannot be skinned. 
 *  If you want to apply a skin, use the SkinnableContainer instead.</p>
 * 
 *  <p><b>Note:</b> The scale grid might not function correctly when there 
 *  are DisplayObject children inside of the Group, such as a component 
 *  or another Group.  If the children are GraphicElement objects, and 
 *  they all share the Group's DisplayObject, then the scale grid works 
 *  properly.</p> 
 * 
 *  <p>Setting any of the following properties on a GraphicElement child
 *  requires that GraphicElement to create its own DisplayObject,
 *  thus negating the scale grid properties on the Group.</p>  
 * 
 *  <pre>
 *  alpha
 *  blendMode other than BlendMode.NORMAL or "auto"
 *  colorTransform
 *  filters
 *  mask
 *  matrix
 *  rotation
 *  scaling
 *  3D properties
 *  bounds outside the extent of the Group
 *  </pre>
 *
 *  <p>The Group container has the following default characteristics:</p>
 *  <table class="innertable">
 *     <tr><th>Characteristic</th><th>Description</th></tr>
 *     <tr><td>Default size</td><td>Large enough to display its children</td></tr>
 *     <tr><td>Minimum size</td><td>0 pixels</td></tr>
 *     <tr><td>Maximum size</td><td>10000 pixels wide and 10000 pixels high</td></tr>
 *  </table>
 *  
 *  @mxml
 *
 *  <p>The <code>&lt;s:Group&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;s:Group
 *    <strong>Properties</strong>
 *    blendMode="auto"
 *    mxmlContent="null"
 *    scaleGridBottom="null"
 *    scaleGridLeft="null"
 *    scaleGridRight="null"
 *    scaleGridTop="null"
 *  
 *    <strong>Events</strong>
 *    elementAdd="<i>No default</i>"
 *    elementRemove="<i>No default</i>"
 *  /&gt;
 *  </pre>
 *
 *  @see spark.components.DataGroup
 *  @see spark.components.SkinnableContainer
 *
 *  @includeExample examples/GroupExample.mxml
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class Group extends GroupBase implements IVisualElementContainer, 
                                                IGraphicElementContainer, 
                                                ISharedDisplayObject
{
    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function Group():void
    {
        super();    
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    private var needsDisplayObjectAssignment:Boolean = false;
    private var layeringMode:uint = ITEM_ORDERED_LAYERING;
    private var numGraphicElements:uint = 0;
    private var deferredStyleClients:Dictionary = null;  // of IAdvancedStyleClient
    
    private static const ITEM_ORDERED_LAYERING:uint = 0;
    private static const SPARSE_LAYERING:uint = 1;    

    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //--------------------------------------------------------------------------
   
    //----------------------------------
    //  baselinePosition
    //----------------------------------
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function get baselinePosition():Number
    {
        if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_5)
            return super.baselinePosition;
        
        if (!validateBaselinePosition())
            return NaN;
        
        var bElement:IVisualElement = baselinePositionElement;
        
        // If no baselinePositionElement is specified, use the first element
        if (bElement == null)
        {
            for (var i:int = 0; i < numElements; i++)
            {
                var elt:IVisualElement = getElementAt(i);
                if (elt.includeInLayout)
                {
                    bElement = elt;
                    break;
                }
            }
        }
            
        
        if (bElement)
            return bElement.baselinePosition + bElement.y;
        else
            return super.baselinePosition;
    }
    
    [Inspectable(category="General", enumeration="noScale,scale", defaultValue="noScale")]
    
    /**
     *  @private
     */
    override public function set resizeMode(value:String):void
    {
        if (isValidScaleGrid())
        {
            // Force the resize mode to be scale if we 
            // have set scaleGrid properties
            value = ResizeMode.SCALE;
        }
         
        super.resizeMode = value;
    }
    
    /**
     *  @private
     */
    override public function set scrollRect(value:Rectangle):void
    {
        // Work-around for Flash Player bug: if GraphicElements share
        // the Group's Display Object and cacheAsBitmap is true, the
        // scrollRect won't function correctly. 
        var previous:Boolean = canShareDisplayObject;
        super.scrollRect = value;
        
        if (numGraphicElements > 0 && previous != canShareDisplayObject)
            invalidateDisplayObjectOrdering(); 
        
        if (mouseEnabledWhereTransparent && hasMouseListeners)
        {        
            // Re-render our mouse event fill if necessary.
            redrawRequested = true;
            super.$invalidateDisplayList();
         }
    }

    /**
     * @private
     */  
    override mx_internal function set hasMouseListeners(value:Boolean):void
    {
        if (mouseEnabledWhereTransparent)
            redrawRequested = true;
        super.hasMouseListeners = value;
    }  

    /**
     *  @private
     */
    override public function set width(value:Number):void
    {
        if (_width != value)
        {
            if (mouseEnabledWhereTransparent && hasMouseListeners)
            {        
                // Re-render our mouse event fill if necessary.
                redrawRequested = true;
                super.$invalidateDisplayList();
            }
        }
        super.width = value;
    }
    
    /**
     *  @private
     */
    override public function set height(value:Number):void
    {
        if (_height != value)
        {
            if (mouseEnabledWhereTransparent && hasMouseListeners)
            {        
                // Re-render our mouse event fill if necessary.
                redrawRequested = true;
                super.$invalidateDisplayList();
            }
        }
        super.height = value;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  alpha
    //----------------------------------

    [Inspectable(defaultValue="1.0", category="General", verbose="1")]

    /**
     *  @private
     */
    override public function set alpha(value:Number):void
    {
        if (super.alpha == value)
            return;
        
        if (_blendMode == "auto")
        {
            // If alpha changes from an opaque/transparent (1/0) and translucent
            // (0 < value < 1), then trigger a blendMode change
            if ((value > 0 && value < 1 && (super.alpha == 0 || super.alpha == 1)) ||
                ((value == 0 || value == 1) && (super.alpha > 0 && super.alpha < 1)))
            {
                blendModeChanged = true;
                invalidateDisplayObjectOrdering();
                invalidateProperties();
            }
        }
        
        super.alpha = value;
    }
    
    //----------------------------------
    //  baselinePositionElement
    //---------------------------------- 
    
    private var _baselinePositionElement:IVisualElement;
    
    /**
     *  The element used to calculate the GroupBase's baselinePosition 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get baselinePositionElement():IVisualElement
    {
        return _baselinePositionElement;
    }
    
    /**
     *  @private 
     */ 
    public function set baselinePositionElement(value:IVisualElement):void
    {
        if (value === _baselinePositionElement)
            return;
        
        _baselinePositionElement = value;
        invalidateParentSizeAndDisplayList();
    }
    
    //----------------------------------
    //  blendMode
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the blendMode property.
     */
    private var _blendMode:String = "auto";  
    private var blendModeChanged:Boolean;
    private var blendShaderChanged:Boolean;

    [Inspectable(category="General", enumeration="auto,add,alpha,darken,difference,erase,hardlight,invert,layer,lighten,multiply,normal,subtract,screen,overlay,colordodge,colorburn,exclusion,softlight,hue,saturation,color,luminosity", defaultValue="auto")]

    /**
     *  A value from the BlendMode class that specifies which blend mode to use. 
     *  A bitmap can be drawn internally in two ways. 
     *  If you have a blend mode enabled or an external clipping mask, the bitmap is drawn 
     *  by adding a bitmap-filled square shape to the vector render. 
     *  If you attempt to set this property to an invalid value, 
     *  Flash Player or Adobe AIR sets the value to <code>BlendMode.NORMAL</code>. 
     *
     *  <p>A value of "auto" (the default) is specific to Group's use of 
     *  blendMode and indicates that the underlying blendMode should be 
     *  <code>BlendMode.NORMAL</code> except when <code>alpha</code> is not
     *  equal to either 0 or 1, when it is set to <code>BlendMode.LAYER</code>. 
     *  This behavior ensures that groups have correct
     *  compositing of their graphic objects when the group is translucent.</p>
     * 
     *  @default "auto"
     *
     *  @see flash.display.DisplayObject#blendMode
     *  @see flash.display.BlendMode
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function get blendMode():String
    {
        return _blendMode; 
    }
    
    /**
     *  @private
     */
    override public function set blendMode(value:String):void
    {
        if (value == _blendMode)
            return;
        
        invalidateProperties();
        blendModeChanged = true;
        
        //The default blendMode in FXG is 'auto'. There are only
        //certain cases where this results in a rendering difference,
        //one being when the alpha of the Group is > 0 and < 1. In that
        //case we set the blendMode to layer to avoid the performance
        //overhead that comes with a non-normal blendMode. 
        
        if (value == "auto")
        {
            _blendMode = value;
            // SDK-29631: Use super.$blendMode instead of super.blendMode
            // since Group completely overrides blendMode and we 
            // want to bypass the extra logic in UIComponent which
            // has its own override.
            // TODO (egeorgie): figure out whether we can share some
            // of that logic in the future.
            if (((alpha > 0 && alpha < 1) && super.$blendMode != BlendMode.LAYER) ||
                ((alpha == 1 || alpha == 0) && super.$blendMode != BlendMode.NORMAL) )
            {
                invalidateDisplayObjectOrdering();
            }
        }
        else 
        {
            var oldValue:String = _blendMode;
            _blendMode = value;
            
            // If one of the non-native Flash blendModes is set, 
            // record the new value and set the appropriate 
            // blendShader on the display object. 
            if (isAIMBlendMode(value))
            {
                blendShaderChanged = true;
            }
        
            // Only need to re-do display object assignment if blendmode was normal
            // and is changing to something else, or the blend mode was something else 
            // and is going back to normal.  This is because display object sharing
            // only happens when blendMode is normal.
            if ((oldValue == BlendMode.NORMAL || value == BlendMode.NORMAL) && 
                !(oldValue == BlendMode.NORMAL && value == BlendMode.NORMAL))
            {
                invalidateDisplayObjectOrdering();
            }
        
        }
    }
    
    /**
     *  override setting of children
     */
    override protected function addMXMLChildren(comps:Array):void
    {
        mxmlContent = comps;
    }
    
    //----------------------------------
    //  mxmlContent
    //----------------------------------

    private var mxmlContentChanged:Boolean = false;
    private var _mxmlContent:Array;

    [ArrayElementType("mx.core.IVisualElement")]

    /**
     *  The visual content children for this Group.
     * 
     *  This method is used internally by Flex and is not intended for direct
     *  use by developers.
     *
     *  <p>The content items should only be IVisualElement objects.  
     *  An <code>mxmlContent</code> Array should not be shared between multiple
     *  Group containers because visual elements can only live in one container 
     *  at a time.</p>
     * 
     *  <p>If the content is an Array, do not modify the Array 
     *  directly. Use the methods defined by the Group class instead.</p>
     *
     *  @default null
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function set mxmlContent(value:Array):void
    {
        if (createChildrenCalled)
        {
            setMXMLContent(value);
        }
        else
        {
            mxmlContentChanged = true;
            _mxmlContent = value;
            // we will validate this in createChildren();
        }
    }
    
    /**
     *  @private
     */
    mx_internal function getMXMLContent():Array
    {
        if (_mxmlContent)
            return _mxmlContent.concat();
        else
            return null;
    }
    
   /**
     *  @private
     *  Adds the elements in <code>mxmlContent</code> to the Group.
     *  Flex calls this method automatically; you do not call it directly.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */ 
    private function setMXMLContent(value:Array):void
    {
        var i:int;
        
        // if there's old content and it's different than what 
        // we're trying to set it to, then let's remove all the old 
        // elements first.
        if (_mxmlContent != null && _mxmlContent != value)
        {
            for (i = _mxmlContent.length - 1; i >= 0; i--)
            {
                elementRemoved(_mxmlContent[i], i);
            }
        }
        
        _mxmlContent = (value) ? value.concat() : null;  // defensive copy
        
        if (_mxmlContent != null)
        {
            var n:int = _mxmlContent.length;
            for (i = 0; i < n; i++)
            {   
                var elt:IVisualElement = _mxmlContent[i];

                // A common mistake is to bind the viewport property of a Scroller
                // to a group that was defined in the MXML file with a different parent    
                if (elt.parent && (elt.parent != this))
                    throw new Error(resourceManager.getString("components", "mxmlElementNoMultipleParents", [elt]));

                elementAdded(elt, i);
            }
        }
    }
    
    //--------------------------------------------------------------------------
    //
    //  Properties: ScaleGrid
    //
    //--------------------------------------------------------------------------

    private var scaleGridChanged:Boolean = false;
    
    // store the scaleGrid into a rectangle to save space (top, left, bottom, right);
    private var scaleGridStorageVariable:Rectangle;

    //----------------------------------
    //  scale9Grid
    //----------------------------------
    
    /**
     *  @private
     */
    override public function set scale9Grid(value:Rectangle):void
    {
        if (value != null)
        {
            scaleGridTop = value.top;
            scaleGridBottom = value.bottom;
            scaleGridLeft = value.left;
            scaleGridRight = value.right;
        }
        else
        {
            scaleGridTop = NaN;
            scaleGridBottom = NaN;
            scaleGridLeft = NaN;
            scaleGridRight = NaN;
        }
    }

    //----------------------------------
    //  scaleGridBottom
    //----------------------------------
    
    [Inspectable(category="General")]
    
    /**
     *  Specifies the bottom coordinate of the scale grid.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get scaleGridBottom():Number
    {
        if (scaleGridStorageVariable)
            return scaleGridStorageVariable.height;
        
        return NaN;
    }
    
    public function set scaleGridBottom(value:Number):void
    {
        if (!scaleGridStorageVariable)
            scaleGridStorageVariable = new Rectangle(NaN, NaN, NaN, NaN);
        
        if (value != scaleGridStorageVariable.height)
        {
            scaleGridStorageVariable.height = value;
            scaleGridChanged = true;
            invalidateProperties();
            invalidateDisplayList();
        }
    }
    
    //----------------------------------
    //  scaleGridLeft
    //----------------------------------
    
    [Inspectable(category="General")]
    
    /**
     * Specifies the left coordinate of the scale grid.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get scaleGridLeft():Number
    {
        if (scaleGridStorageVariable)
            return scaleGridStorageVariable.x;
        
        return NaN;
    }
    
    public function set scaleGridLeft(value:Number):void
    {
        if (!scaleGridStorageVariable)
            scaleGridStorageVariable = new Rectangle(NaN, NaN, NaN, NaN);
        
        if (value != scaleGridStorageVariable.x)
        {
            scaleGridStorageVariable.x = value;
            scaleGridChanged = true;
            invalidateProperties();
            invalidateDisplayList();
        }

    }

    //----------------------------------
    //  scaleGridRight
    //----------------------------------
    
    [Inspectable(category="General")]
    
    /**
     * Specifies the right coordinate of the scale grid.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get scaleGridRight():Number
    {
        if (scaleGridStorageVariable)
            return scaleGridStorageVariable.width;
        
        return NaN;
    }
    
    public function set scaleGridRight(value:Number):void
    {
        if (!scaleGridStorageVariable)
            scaleGridStorageVariable = new Rectangle(NaN, NaN, NaN, NaN);
        
        if (value != scaleGridStorageVariable.width)
        {
            scaleGridStorageVariable.width = value;
            scaleGridChanged = true;
            invalidateProperties();
            invalidateDisplayList();
        }

    }

    //----------------------------------
    //  scaleGridTop
    //----------------------------------
    
    [Inspectable(category="General")]
    
    /**
     * Specifies the top coordinate of the scale grid.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get scaleGridTop():Number
    {
        if (scaleGridStorageVariable)
            return scaleGridStorageVariable.y;
        
        return NaN;
    }
    
    public function set scaleGridTop(value:Number):void
    {
        if (!scaleGridStorageVariable)
            scaleGridStorageVariable = new Rectangle(NaN, NaN, NaN, NaN);
        
        if (value != scaleGridStorageVariable.y)
        {
            scaleGridStorageVariable.y = value;
            scaleGridChanged = true;
            invalidateProperties();
            invalidateDisplayList();
        }
    } 
    
    private function isValidScaleGrid():Boolean
    {
        return !isNaN(scaleGridLeft) &&
               !isNaN(scaleGridTop) &&
               !isNaN(scaleGridRight) &&
               !isNaN(scaleGridBottom);
    }
      
    //--------------------------------------------------------------------------
    //
    //  Overridden methods: UIComponent
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  Defer adding IAdvancedStyleClients until createChildren() time.  The AdvancedStyleClient's
     *  styleName might be a component's show inclusion in the IVisualElement hierarchy was also
     *  deferred.
     */ 
    override public function addStyleClient(styleClient:IAdvancedStyleClient):void    
    {
        if (!createChildrenCalled)
        {
            if (!deferredStyleClients)
                deferredStyleClients = new Dictionary(true);
            deferredStyleClients[styleClient] = true;
        }
        else 
        {
            super.addStyleClient(styleClient);
        }
    }
    
    /**
     *  @private
     */     
    override public function removeStyleClient(styleClient:IAdvancedStyleClient):void
    {
        if (deferredStyleClients && !createChildrenCalled)
            delete deferredStyleClients[styleClient];
        else
            super.removeStyleClient(styleClient);
    }
    
    /**
     *  @private
     *  Whether createChildren() has been called or not.
     *  We use this in the setter for mxmlContent to know 
     *  whether to validate the value immediately, or just 
     *  wait to let createChildren() do it.
     */
    private var createChildrenCalled:Boolean = false;
    
    /**
     *  @private
     */ 
    override protected function createChildren():void
    {
        super.createChildren();
        
        createChildrenCalled = true;
        
        if (mxmlContentChanged)
        {
            mxmlContentChanged = false;
            setMXMLContent(_mxmlContent);
        }
        
        if (deferredStyleClients)
        {
            for (var obj:Object in deferredStyleClients)
            {
                var styleClient:IAdvancedStyleClient = obj as IAdvancedStyleClient;
                if (styleClient)
                    super.addStyleClient(styleClient);
            }
            deferredStyleClients = null;
        }        
    }
    
    /**
     *  @private
     */ 
    override public function validateProperties():void
    {
        super.validateProperties();
        
        // Property validation happens top-down, so now let's 
        // validate graphic element properties after 
        // calling super.validateProperties()
        if (numGraphicElements > 0)
        {
            var length:int = numElements;
            for (var i:int = 0; i < length; i++)
            {
                var element:IGraphicElement = getElementAt(i) as IGraphicElement;
                if (element)
                    element.validateProperties();
            }
        }
    }
    
    /**
     *  @private
     */ 
    override protected function commitProperties():void
    {
        super.commitProperties();
        invalidatePropertiesFlag = false;
        
        if (blendModeChanged)
        {
            blendModeChanged = false;
            
            // Figure out the correct blendMode value
            // to set. 
            // SDK-29631: Use super.$blendMode instead of super.blendMode
            // since Group completely overrides blendMode and we 
            // want to bypass the extra logic in UIComponent which
            // has its own override.
            // TODO (egeorgie): figure out whether we can share some
            // of that logic in the future.
            if (_blendMode == "auto")
            {
                if (alpha == 0 || alpha == 1) 
                    super.$blendMode = BlendMode.NORMAL;
                else
                    super.$blendMode = BlendMode.LAYER;
            }
            else if (!isAIMBlendMode(_blendMode))
            {
                super.$blendMode = _blendMode;
            }
            
            if (blendShaderChanged) 
            {
                // The graphic element's blendMode was set to a non-Flash 
                // blendMode. We mimic the look by instantiating the 
                // appropriate shader class and setting the blendShader
                // property on the displayObject. 
                blendShaderChanged = false; 
                switch(_blendMode)
                {
                    case "color": 
                    {
                        super.blendShader = new ColorShader();
                        break; 
                    }
                    case "colordodge":
                    {
                        super.blendShader = new ColorDodgeShader();
                        break; 
                    }
                    case "colorburn":
                    {
                        super.blendShader = new ColorBurnShader();
                        break; 
                    }
                    case "exclusion":
                    {
                        super.blendShader = new ExclusionShader();
                        break; 
                    }
                    case "hue":
                    {
                        super.blendShader = new HueShader();
                        break; 
                    }
                    case "luminosity":
                    {
                        super.blendShader = new LuminosityShader();
                        break; 
                    }
                    case "saturation": 
                    {
                        super.blendShader = new SaturationShader();
                        break; 
                    }
                    case "softlight":
                    {
                        super.blendShader = new SoftLightShader();
                        break; 
                    }
                }
            }
        }
        
        // Due to dependent properties alpha and blendMode there may be a need
        // for a second pass at committing properties (to ensure our new
        // blendMode or blendShader is assigned to our underlying display 
        // object).
        if (invalidatePropertiesFlag)
        {
            super.commitProperties();
            invalidatePropertiesFlag = false;
        }
        
        if (needsDisplayObjectAssignment)
        {
            needsDisplayObjectAssignment = false;
            assignDisplayObjects();
        }
        
        if (scaleGridChanged)
        {
            // Don't reset scaleGridChanged since we also check it in updateDisplayList
            if (isValidScaleGrid())
                resizeMode = ResizeMode.SCALE; // Force the resizeMode to scale 
        }
    }
    
    /**
     *  @private
     */
    override public function validateSize(recursive:Boolean = false):void
    {
        // Since IGraphicElement is not ILayoutManagerClient, we need to make sure we
        // validate sizes of the elements, even in cases where recursive==false.
        
        // Size validation happens bottom-up, so now let's 
        // validate graphic element size before 
        // calling super.validateSize()
        if (numGraphicElements > 0)
        {
            var length:int = numElements;
            for (var i:int = 0; i < length; i++)
            {
                var element:IGraphicElement = getElementAt(i) as IGraphicElement;
                if (element)
                    element.validateSize();
            }
        }

        super.validateSize(recursive);
    }   
    
    /**
     *  @private
     */  
    override public function setActualSize(w:Number, h:Number):void
    {
        if (_width != w || _height != h)
        {
            if (mouseEnabledWhereTransparent && hasMouseListeners)
            {        
                // Re-render our mouse event fill if necessary.
                redrawRequested = true;
                super.$invalidateDisplayList();
            }
        }

        super.setActualSize(w, h);
    }
    
    /**
     *  @private
     */
    override public function validateDisplayList():void
    {
        // call super.validateDisplayList() and let updateDisplayList() run
        super.validateDisplayList();

        // If the DisplayObject assignment is still not completed, then postpone validation
        // of the GraphicElements. invalidateDisplayList() will be called during the next 
        // commitProperties() call since needsDisplayObjectAssignment=true, 
        // so we will be re-running validateDisplayList() anyways
        if (needsDisplayObjectAssignment && invalidatePropertiesFlag)
            return;
        
        // DisplayList validation happens top-down, so we should
        // validate graphic element DisplayList after 
        // calling super.validateDisplayList().  This is 
        // gets tricky because of graphic-element sharing.  We clear
        // Group's graphic's object in updateDisplayList() and handle the 
        // rest of the DisplayList validation in here.
        
        // Iterate through the graphic elements. If an element has a displayObject that has been 
        // invalidated, then validate all graphic elements that draw to this displayObject. 
        // The algorithm assumes that all of the elements that share a displayObject are in between
        // the element with the shared displayObject and the next element that has a displayObject.
        
        var sharedDisplayObject:ISharedDisplayObject = this;
        if (numGraphicElements > 0)
        {
            var length:int = numElements;
            for (var i:int = 0; i < length; i++)
            {
                var element:IGraphicElement = getElementAt(i) as IGraphicElement;
                if (!element)
                    continue;
                
                // Do a special check for layer, we may stumble upon an element with layer != 0
                // before we're done with the current shared sequence and we don't want to mark
                // the sequence as valid, until we reach the next sequence.   
                if (element.depth == 0)
                {
                    // Is this the start of a new shared sequence?          
                    if (element.displayObjectSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT)
                    {
                        // We have finished redrawing the previous sequence
                        if (sharedDisplayObject)
                            sharedDisplayObject.redrawRequested = false;
                        
                        // Start the new sequence
                        sharedDisplayObject = element.displayObject as ISharedDisplayObject;
                    }
                    
                    if (!sharedDisplayObject || sharedDisplayObject.redrawRequested) 
                        element.validateDisplayList();
                }
                else
                {
                    // If we have layering, we don't share the display objects.
                    // Don't update the current sharedDisplayObject 
                    var elementDisplayObject:ISharedDisplayObject = element.displayObject as ISharedDisplayObject;
                    if (!elementDisplayObject || elementDisplayObject.redrawRequested)
                    {
                        element.validateDisplayList();
                        
                        if (elementDisplayObject)
                            elementDisplayObject.redrawRequested = false;
                    }
                }
            }
        }
        
        // Mark the last shared displayObject valid
        if (sharedDisplayObject)
            sharedDisplayObject.redrawRequested = false;
    }
    
    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        // let user's code (layout) run first before dealing with graphic element 
        // sharing because that's when redraws can be requested
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        
        // Clear the group's graphic because graphic elements might be drawing to it
        // This isn't needed for DataGroup because there's no DisplayObject sharing
        // This code exists in updateDisplayList() as opposed to validateDisplayList() 
        // because of compatibility issues since most of this code was 
        // refactored from updateDisplayList() and in to validateDisplayList().  User's code 
        // already assumed that they could call super.updateDisplayList() and then be able to draw 
        // into the Group's graphics object.  Because of that, the graphics.clear() call is left 
        // in updateDisplayList() instead of in validateDisplayList() with the rest of the graphic 
        // element sharing code.
        var sharedDisplayObject:ISharedDisplayObject = this;
        if (sharedDisplayObject.redrawRequested)
        {
            // clear the graphics here.  The pattern is usually to call graphics.clear() 
            // before calling super.updateDisplayList() so what happens in super.updateDisplayList() 
            // isn't erased.  However, in this case, what happens in super.updateDisplayList() isn't 
            // much, and we want to make sure super.updateDisplayList() runs first since the layout 
            // is what actually triggers the the shareDisplayObject to request to be redrawn.
            graphics.clear();
            drawBackground();
            
            // If a scaleGrid is set, make sure the extent of the groups bounds are filled so
            // the player will scale our contents as expected. 
            if (isValidScaleGrid() && resizeMode == ResizeMode.SCALE)
            {
                graphics.lineStyle();
                graphics.beginFill(0, 0);
                graphics.drawRect(0, 0, 1, 1);
                graphics.drawRect(measuredWidth - 1, measuredHeight - 1, 1, 1);
                graphics.endFill();
            }
        }
        
        if (scaleGridChanged)
        {
            scaleGridChanged = false;
        
            if (isValidScaleGrid())
            {
                // Check for DisplayObjects other than overlays
                var overlayCount:int = _overlay ? _overlay.numDisplayObjects : 0;
                if (numChildren - overlayCount > 0)
                    throw new Error(resourceManager.getString("components", "scaleGridGroupError"));

                super.scale9Grid = new Rectangle(scaleGridLeft, 
                                                 scaleGridTop,    
                                                 scaleGridRight - scaleGridLeft, 
                                                 scaleGridBottom - scaleGridTop);
            } 
            else
            {
                super.scale9Grid = null;
            }                              
        }
    }

    /**
     *  @private
     *  TODO (rfrishbe): Most of this code is a duplicate of UIComponent::notifyStyleChangeInChildren,
     *  refactor as appropriate to avoid code duplication once we have a common
     *  child iterator between UIComponent and Group.
     */ 
    override public function notifyStyleChangeInChildren(
                        styleProp:String, recursive:Boolean):void
    {
        if (mxmlContentChanged || !recursive) 
            return;
            
        var n:int = numElements;
        for (var i:int = 0; i < n; i++)
        {
            var child:ISimpleStyleClient = getElementAt(i) as ISimpleStyleClient;
            if (child)
            {
                child.styleChanged(styleProp);
                
                if (child is IStyleClient)
                    IStyleClient(child).notifyStyleChangeInChildren(styleProp, recursive);
            }
        }
        
        if (advanceStyleClientChildren != null)
        {
            for (var styleClient:Object in advanceStyleClientChildren)
            {
                var iAdvanceStyleClientChild:IAdvancedStyleClient = styleClient 
                    as IAdvancedStyleClient;
                
                if (iAdvanceStyleClientChild)
                {
                    iAdvanceStyleClientChild.styleChanged(styleProp);
                }
            }
        }
    }
    
    /**
     *  @private
     *  TODO (rfrishbe): Most of this code is a duplicate of UIComponent::regenerateStyleCache,
     *  refactor as appropriate to avoid code duplication once we have a common
     *  child iterator between UIComponent and Group.
     */ 
    override public function regenerateStyleCache(recursive:Boolean):void
    {
        // Regenerate the proto chain for this object
        initProtoChain();

        // Recursively call this method on each child.
        var n:int = numElements;
        for (var i:int = 0; i < n; i++)
        {
            var child:IVisualElement = getElementAt(i);

            if (child is IStyleClient)
            {
                // Does this object already have a proto chain?
                // If not, there's no need to regenerate a new one.
                if (IStyleClient(child).inheritingStyles !=
                    StyleProtoChain.STYLE_UNINITIALIZED)
                {
                    IStyleClient(child).regenerateStyleCache(recursive);
                }
            }
            else if (child is IUITextField)
            {
                // Does this object already have a proto chain?
                // If not, there's no need to regenerate a new one.
                if (IUITextField(child).inheritingStyles)
                    StyleProtoChain.initTextField(IUITextField(child));
            }
        }
        
        // Call this method on each non-visual StyleClient
        if (advanceStyleClientChildren != null)
        {
            for (var styleClient:Object in advanceStyleClientChildren)
            {
                var iAdvanceStyleClientChild:IAdvancedStyleClient = styleClient
                    as IAdvancedStyleClient;
                
                if (iAdvanceStyleClientChild && 
                    iAdvanceStyleClientChild.inheritingStyles !=
                    StyleProtoChain.STYLE_UNINITIALIZED)
                {
                    iAdvanceStyleClientChild.regenerateStyleCache(recursive);
                }
            }
        }
    }

	/** 
	 * 
	 * @private
	 * Spark components get their children created earlier than createChildren
	 * but not parented until createChildren
	 */ 
	override public function parentChanged(p:DisplayObjectContainer):void
	{
		super.parentChanged(p);
		var children:Array =  this.MXMLDescriptor;
		if (children && !processedMXMLDescriptors)
		{
			generateMXMLInstances(document, children);
			processedMXMLDescriptors = true;
		}
	}

    //--------------------------------------------------------------------------
    //
    //  Content management
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    override public function get numElements():int
    {
        if (_mxmlContent == null)
            return 0;

        return _mxmlContent.length;
    }
    
    /**
     *  @private
     */ 
    override public function getElementAt(index:int):IVisualElement
    {
        // check for RangeError:
        checkForRangeError(index);
        
        return _mxmlContent[index];
    }
    
    /**
     *  @private 
     *  Checks the range of index to make sure it's valid
     */ 
    private function checkForRangeError(index:int, addingElement:Boolean = false):void
    {
        // figure out the maximum allowable index
        var maxIndex:int = (_mxmlContent == null ? -1 : _mxmlContent.length - 1);
        
        // if adding an element, we allow an extra index at the end
        if (addingElement)
            maxIndex++;
            
        if (index < 0 || index > maxIndex)
            throw new RangeError(resourceManager.getString("components", "indexOutOfRange", [index]));
    }
    
    /**
     * @private
     */
    private function isAIMBlendMode(value:String):Boolean
    {
        if (value == "colordodge" || 
            value =="colorburn" || value =="exclusion" || 
            value =="softlight" || value =="hue" || 
            value =="saturation" || value =="color" ||
            value =="luminosity")
            return true; 
        else return false; 
    }
 
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function addElement(element:IVisualElement):IVisualElement
    {
        var index:int = numElements;
        
        // This handles the case where we call addElement on something
        // that already is in the list.  Let's just handle it silently
        // and not throw up any errors.
        if (element.parent == this)
            index = numElements-1;
        
        return addElementAt(element, index);
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function addElementAt(element:IVisualElement, index:int):IVisualElement
    {
        if (element == this)
            throw new ArgumentError(resourceManager.getString("components", "cannotAddYourselfAsYourChild"));
            
        // check for RangeError:
        checkForRangeError(index, true);
        
        var host:DisplayObject = element.parent; 
        
        // This handles the case where we call addElement on something
        // that already is in the list.  Let's just handle it silently
        // and not throw up any errors.
        if (host == this)
        {
            setElementIndex(element, index);
            return element;
        }
        else if (host is IVisualElementContainer)
        {
            // Remove the item from the group if that group isn't this group
            IVisualElementContainer(host).removeElement(element);
        }
        
        // If we don't have any content yet, initialize it to an empty array
        if (_mxmlContent == null)
            _mxmlContent = [];
        
        _mxmlContent.splice(index, 0, element);
        
        if (!mxmlContentChanged)
            elementAdded(element, index);
        
        scaleGridChanged = true;
                
        return element;
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function removeElement(element:IVisualElement):IVisualElement
    {
        return removeElementAt(getElementIndex(element));
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function removeElementAt(index:int):IVisualElement
    {
        // check RangeError
        checkForRangeError(index);
        
        var element:IVisualElement = _mxmlContent[index];
        
        // Need to call elementRemoved before removing the item so anyone listening
        // for the event can access the item.
        
        if (!mxmlContentChanged)
            elementRemoved(element, index);
        
        _mxmlContent.splice(index, 1);
        
        return element;
    }
        
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function removeAllElements():void
    {
        for (var i:int = numElements - 1; i >= 0; i--)
        {
            removeElementAt(i);
        }
    }
    
    /**
     *  @private
     */ 
    override public function getElementIndex(element:IVisualElement):int
    {
        var index:int = _mxmlContent ? _mxmlContent.indexOf(element) : -1;
        
        if (index == -1)
            throw ArgumentError(resourceManager.getString("components", "elementNotFoundInGroup", [element]));
        else
            return index;
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function setElementIndex(element:IVisualElement, index:int):void
    {
        // check for RangeError...this is done in addItemAt
        // but we want to do it before removing the element
        checkForRangeError(index);
        
        if (getElementIndex(element) == index)
            return;
        
        removeElement(element);
        addElementAt(element, index);
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function swapElements(element1:IVisualElement, element2:IVisualElement):void
    {
        swapElementsAt(getElementIndex(element1), getElementIndex(element2));
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function swapElementsAt(index1:int, index2:int):void
    {
        checkForRangeError(index1);
        checkForRangeError(index2);

        // Make sure that index1 is the smaller index so that addElementAt 
        // doesn't RTE
        if (index1 > index2)
        {
            var temp:int = index2;
            index2 = index1;
            index1 = temp; 
        }
        else if (index1 == index2)
            return;

        var element1:IVisualElement = _mxmlContent[index1];
        var element2:IVisualElement = _mxmlContent[index2];

        // Make sure we do the proper invalidations, but don't dispatch events
        if (!mxmlContentChanged)
        {
            elementRemoved(element1, index1, false /*notifyListeners*/);
            elementRemoved(element2, index2, false /*notifyListeners*/);
        }
        
        // Step 1: remove
        // Make sure we remove the bigger index first
        _mxmlContent.splice(index2, 1);
        _mxmlContent.splice(index1, 1);

        // Step 2: swap
        // Add them in reverse order 
        _mxmlContent.splice(index1, 0, element2);
        _mxmlContent.splice(index2, 0, element1);

        // Make sure we do the proper invalidations, but don't dispatch events
        if (!mxmlContentChanged)
        {
            elementAdded(element2, index1, false /*notifyListeners*/);
            elementAdded(element1, index2, false /*notifyListeners*/);
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Content management (internal)
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    override public function invalidateLayering():void
    {
        if (layeringMode == ITEM_ORDERED_LAYERING)
            layeringMode = SPARSE_LAYERING;
        invalidateDisplayObjectOrdering();
    }

    /**
     *  Adds an item to this Group.
     *  Flex calls this method automatically; you do not call it directly.
     *
     *  @param item The item that was added.
     *
     *  @param index The index where the item was added.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function elementAdded(element:IVisualElement, index:int, notifyListeners:Boolean = true):void
    {
        if (layout)
            layout.elementAdded(index);        
                
        if (element.depth != 0)
            invalidateLayering();

        // Set the moduleFactory to the child, but don't overwrite an existing moduleFactory.
        // Propagate moduleFactory to the child, but don't overwrite an existing moduleFactory.
        if (element is IFlexModule && IFlexModule(element).moduleFactory == null)
        {
            if (moduleFactory != null)
                IFlexModule(element).moduleFactory = moduleFactory;
                
            else if (document is IFlexModule && document.moduleFactory != null)
                IFlexModule(element).moduleFactory = document.moduleFactory;
                
            else if (parent is IFlexModule && IFlexModule(element).moduleFactory != null)
                IFlexModule(element).moduleFactory = IFlexModule(parent).moduleFactory;
        }
        
        // Set the font context in non-UIComponent children.
        // UIComponent children use moduleFactory.
        if (element is IFontContextComponent && !(element is UIComponent) &&
            IFontContextComponent(element).fontContext == null)
        {  
            IFontContextComponent(element).fontContext = moduleFactory;
        }

        if (element is IGraphicElement) 
        {
            numGraphicElements++;
            addingGraphicElementChild(element as IGraphicElement);
            invalidateDisplayObjectOrdering();
        }   
        else
        {
            // item must be a DisplayObject
            
            // if the display object ordering is invalidated (because we have graphic elements 
            // that aren't actually in the display list), then lets just add our item to the end.  
            // If the ordering isn't invalidated, then let's just try to add it to the proper index.
            if (invalidateDisplayObjectOrdering())
            {
                // This always adds the child to the end of the display list. Any 
                // ordering discrepancies will be fixed up in assignDisplayObjects().
                addDisplayObjectToDisplayList(DisplayObject(element));
            }
            else
            {
                addDisplayObjectToDisplayList(DisplayObject(element), index);
            }
        }
        
        if (notifyListeners)
        {
            if (hasEventListener(ElementExistenceEvent.ELEMENT_ADD))
                dispatchEvent(new ElementExistenceEvent(
                    ElementExistenceEvent.ELEMENT_ADD, false, false, element, index));
            
            
            if (element is IUIComponent && element.hasEventListener(FlexEvent.ADD))
                element.dispatchEvent(new FlexEvent(FlexEvent.ADD));
        }
        
        invalidateSize();
        invalidateDisplayList();
    }
    
    /**
     *  Removes an item from this Group.
     *  Flex calls this method automatically; you do not call it directly.
     *
     *  @param index The index of the item that is being removed.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function elementRemoved(element:IVisualElement, index:int, notifyListeners:Boolean = true):void
    {
        var childDO:DisplayObject = element as DisplayObject;   

        if (notifyListeners)
        {        
            if (hasEventListener(ElementExistenceEvent.ELEMENT_REMOVE))
                dispatchEvent(new ElementExistenceEvent(
                    ElementExistenceEvent.ELEMENT_REMOVE, false, false, element, index));
            
            if (element is IUIComponent && element.hasEventListener(FlexEvent.REMOVE))
                element.dispatchEvent(new FlexEvent(FlexEvent.REMOVE));
        }
        
        if (element && (element is IGraphicElement))
        {
            numGraphicElements--;
            removingGraphicElementChild(element as IGraphicElement);
        }
        else if (childDO && childDO.parent == this)
        {
            super.removeChild(childDO);
        }
        
        invalidateDisplayObjectOrdering();
        invalidateSize();
        invalidateDisplayList();

        if (layout)
            layout.elementRemoved(index);     
    }
    
    /**
     *  @private
     */
    mx_internal function addingGraphicElementChild(child:IGraphicElement):void
    {
        // Special case (defensive coding) - if the element was previously
        // a child of this Group, and it didn't release its previously assigned
        // DisplayObject when its parent changed, and there's the possibility that
        // the Group may assign it the same DisplayObject and the same sharing mode,
        // we still need to invalidate and redraw as the displayObject likely has
        // been redrawn while the element was not a child of this Group.
        if (child.displayObject && child.displayObjectSharingMode == DisplayObjectSharingMode.USES_SHARED_OBJECT)
            invalidateGraphicElementDisplayList(child);
        
        child.parentChanged(this);

        // Sets up the inheritingStyles and nonInheritingStyles objects
        // and their proto chains so that getStyle() works.
        // If this object already has some children,
        // then reinitialize the children's proto chains.
        if (child is IStyleClient)
            IStyleClient(child).regenerateStyleCache(true);
        
        if (child is ISimpleStyleClient)
            ISimpleStyleClient(child).styleChanged(null);

        if (child is IStyleClient)
            IStyleClient(child).notifyStyleChangeInChildren(null, true);
    }
    
    /**
     *  @private
     */
    mx_internal function removingGraphicElementChild(child:IGraphicElement):void
    {
        // First discard the displayObject, as child may decide to destroy it
        // when parent changes.
        discardDisplayObject(child);        
        child.parentChanged(null);
    }

    /**
     *  Removes the element's <code>DisplayObject</code> from this <code>Group's</code>
     *  display list.
     *
     *  The <code>Group</code> also ensures any elements that share the
     *  <code>DisplayObject</code> is redrawn.
     * 
     *  <p>This method doesn't necessarily trigger new <code>DisplayObject</code>
     *  reassignment for the passed in <code>element</code>.
     *  To request new display object reassignment, call the
     *  <code>invalidateGraphicElementSharing()</code> method.</p> 
     *
     *  @param element The graphic element whose display object is discarded.
     *  @see #invalidateGraphicElementSharing
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function discardDisplayObject(element:IGraphicElement):void
    {
        var oldDisplayObject:DisplayObject = element.displayObject;
        if (!oldDisplayObject)
            return;

        // If the element created the display object
        if (element.displayObjectSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT &&
            oldDisplayObject.parent == this)
        {
            super.removeChild(oldDisplayObject);

            // Redo the shared sequences. 
            invalidateDisplayObjectOrdering();
        }
        else if (oldDisplayObject is ISharedDisplayObject)
        {
            // Redraw the shared sequence
            ISharedDisplayObject(oldDisplayObject).redrawRequested = true;

            // Make sure we do a pass through the graphic elements and redraw
            // the invalid ones.  We should only redraw, no need to redo the layout.
            super.$invalidateDisplayList();
        }
    }

    /**
     *  @private
     *  
     *  Returns true if the Group's display object can be shared with graphic elements
     *  inside the group
     */
    private function get canShareDisplayObject():Boolean
    {
        // Work-around for Flash Player bug: if GraphicElements share
        // the Group's Display Object and cacheAsBitmap is true, the
        // scrollRect won't function correctly.
        // We can't even check the cacheAsBitmap property since that will
        // cause a back buffer allocation, which is another FP bug.
        if (scrollRect)
            return false;
 
        // We can't share ourselves if we're in blendMode != normal, or we have 
        // to deal with any layering. The reason is because we handle layer = 0 first
        // in our implementation, and we don't want those to use our display object to 
        // draw into because there could be something further down the line that has 
        // layer < 0. The cases where we are in blendMode != normal is when blendMode
        // has been explicitly set or blendMode is auto and there is a fractional alpha. 
        return (_blendMode == "normal" || _blendMode == "auto" && (alpha == 0 || alpha == 1)) 
        && (layeringMode == ITEM_ORDERED_LAYERING);
    }
    
    /**
     *  @private
     *  
     *  Invalidates the display object ordering and will run assignDisplayObjects()
     *  if necessary.
     * 
     *  @return true if the display object ordering needed to be invalidated; 
     *          false otherwise.
     */
    private function invalidateDisplayObjectOrdering():Boolean
    {
        if (layeringMode == SPARSE_LAYERING || numGraphicElements > 0)
        {
            needsDisplayObjectAssignment = true;
            invalidateProperties();
            return true;
        }
        
        return false;
    }

    /**
     *  @private
     *  
     *  Called to assign display objects to graphic elements
     */
    private function assignDisplayObjects():void
    {
        var topLayerItems:Vector.<IVisualElement>;
        var bottomLayerItems:Vector.<IVisualElement>;        
        var keepLayeringEnabled:Boolean = false;
        var insertIndex:int = 0;
        
        // Keep track of the previous IVisualElement.  This is used when
        // assigning DisplayObjects to the IGraphicElements.
        // If the Group can share its DisplayObject with the IGraphicElements
        // then initialize the prevItem with this Group object.
        var prevItem:IVisualElement;
        if (canShareDisplayObject)
            prevItem = this;
            
        // Iterate through all of the items
        var len:int = numElements; 
        for (var i:int = 0; i < len; i++)
        {  
            var item:IVisualElement = getElementAt(i);
            
            if (layeringMode != ITEM_ORDERED_LAYERING)
            {
                var layer:Number = item.depth;
                if (layer != 0)
                {               
                    if (layer > 0)
                    {
                        if (topLayerItems == null) topLayerItems = new Vector.<IVisualElement>();
                        topLayerItems.push(item);
                        continue;                   
                    }
                    else
                    {
                        if (bottomLayerItems == null) bottomLayerItems = new Vector.<IVisualElement>();
                        bottomLayerItems.push(item);
                        continue;                   
                    }
                }
            }
            
            // this should only get called if layer == 0, or we don't care
            // about layering (layeringMode == ITEM_ORDERED_LAYERING)
            insertIndex = assignDisplayObjectTo(item, prevItem, insertIndex);
            prevItem = item;
        }
        
        // we've done all layer == 0 items. 
        // now let's put the higher z-index ones on next
        // then we'll handle the ones on bottom, but we'll
        // insert them in the very beginning (index = 0)
        
        if (topLayerItems != null)
        {
            keepLayeringEnabled = true;
            //topLayerItems.sortOn("layer",Array.NUMERIC);
            GroupBase.sortOnLayer(topLayerItems);
            len = topLayerItems.length;
            for (i=0;i<len;i++)
            {
                // For layer != 0, we never share display objects
                insertIndex = assignDisplayObjectTo(topLayerItems[i], null /*prevElement*/, insertIndex);
            }
        }
        
        if (bottomLayerItems != null)
        {
            keepLayeringEnabled = true;
            insertIndex = 0;

            //bottomLayerItems.sortOn("layer",Array.NUMERIC);
            GroupBase.sortOnLayer(bottomLayerItems);
            len = bottomLayerItems.length;

            for (i=0;i<len;i++)
            {
                // For layer != 0, we never share dsiplay objects
                insertIndex = assignDisplayObjectTo(bottomLayerItems[i], null /*prevElement*/, insertIndex);
            }
        }
        
        // If we tried to layer these visual elements and found that we 
        // don't actually need to because layer=0 for all of them, 
        // then lets optimize this next time and just skip the layering step.
        // If an element gets added that has layer set to something non-zero, then 
        // layeringMode will get set to SPARSE_LAYERING.
        // If the layer property changes on a current element, invalidateLayering()
        // will be called and layeringMode will get set to SPARSE_LAYERING.
        if (keepLayeringEnabled == false)
            layeringMode = ITEM_ORDERED_LAYERING;
            
        // Make sure we do a pass through the graphic elements and redraw
        // the invalid ones.  We should only redraw, no need to redo the layout.
        super.$invalidateDisplayList();
    }
    
    /**
     *  @private
     *  Assigns a DisplayObject to the curElement and ensures the DisplayObject
     *  is at insertIndex in the display object list.
     * 
     *  If <code>curElement</code> implements IGraphicElement, then both its
     *  DisplayObject and displayObjectSharingMode will be updated.
     * 
     *  @curElement The current element to assign DisplayObject to
     *  @prevEelement The previous element in the list of elements or null.
     *  @return Returns the display list index after the current element's
     *  DisplayObject.
     */
    private function assignDisplayObjectTo(curElement:IVisualElement,
                                           prevElement:IVisualElement,
                                           insertIndex:int):int
    {
        if (curElement is DisplayObject)
        {
            super.setChildIndex(curElement as DisplayObject, insertIndex++);
        }
        else if (curElement is IGraphicElement)
        {
            var current:IGraphicElement = IGraphicElement(curElement);
            var previous:IGraphicElement = prevElement as IGraphicElement;

            var oldDisplayObject:DisplayObject = current.displayObject;
            var oldSharingMode:String = current.displayObjectSharingMode;

            if (previous && previous.canShareWithNext(current) && current.canShareWithPrevious(previous) &&
                current.setSharedDisplayObject(previous.displayObject))
            {
                // If we are the second element in the shared sequence,
                // make sure that the first element has the correct displayObjectSharingMode
                if (previous.displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
                    previous.displayObjectSharingMode = DisplayObjectSharingMode.OWNS_SHARED_OBJECT;

                current.displayObjectSharingMode = DisplayObjectSharingMode.USES_SHARED_OBJECT;
            }
            else if (prevElement == this && current.setSharedDisplayObject(this))
            {
                current.displayObjectSharingMode = DisplayObjectSharingMode.USES_SHARED_OBJECT;
            }
            else
            {
                // We don't want to create new DisplayObjects for elements that
                // already have created their own their display objects.
                var ownsDisplayObject:Boolean = oldSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT;

                // If the element doesn't have a DisplayObject or it doesn't own
                // the DisplayObject it currently has, then create a new one
                var displayObject:DisplayObject = oldDisplayObject;
                if (!ownsDisplayObject || !displayObject)
                    displayObject = current.createDisplayObject();

                // Make sure the DisplayObject is at the correct position.
                // Check displayObject for null, some graphic elements
                // may choose not to create a DisplayObject during this pass.
                if (displayObject)
                    addDisplayObjectToDisplayList(displayObject, insertIndex++);

                current.displayObjectSharingMode = DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT;
            }
            invalidateAfterAssignment(current, oldSharingMode, oldDisplayObject);
        }
        return insertIndex;
    }

    /**
     *  @private
     *  Performs invalidation of the old and new shared sequenences.
     *  If necesary, removes the old display object from the list.
     */
    private function invalidateAfterAssignment(element:IGraphicElement,
                                               oldSharingMode:String,
                                               oldDisplayObject:DisplayObject):void
    {
        // Make sure we remove or mark for redraw the old displayObject
        var displayObject:DisplayObject = element.displayObject;
        var sharingMode:String = element.displayObjectSharingMode;

        if (oldDisplayObject == displayObject && sharingMode == oldSharingMode)
            return;

        // Make sure we redraw the display object        
        if (displayObject is ISharedDisplayObject)
            ISharedDisplayObject(displayObject).redrawRequested = true;

        // Old display object also needs to be redrawn, in case any other GE still uses it.
        if (oldDisplayObject is ISharedDisplayObject)
            ISharedDisplayObject(oldDisplayObject).redrawRequested = true;

        // Make sure we remove the old display object, if needed
        if (oldDisplayObject && oldDisplayObject.parent == this &&
            oldDisplayObject != displayObject && oldSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT)
            super.removeChild(oldDisplayObject);
    }

    /**
     *  @private
     *
     *  If the displayObject is not a child of this Group, then insert it at the
     *  specified index (or at the end of the list, when index is -1).
     *  Else, if the displayObject is already a child of the Group, then simply
     *  adjust its child index.  
     */ 
    private function addDisplayObjectToDisplayList(child:DisplayObject, index:int = -1):void
    {
        var overlayCount:int = _overlay ? _overlay.numDisplayObjects : 0;
        if (child.parent == this)
            super.setChildIndex(child, index != -1 ? index : super.numChildren - 1 - overlayCount);
        else
            super.addChildAt(child, index != -1 ? index : super.numChildren - overlayCount);
    }

    /**
     *  Notify the host component that an element has changed and needs to be redrawn.
     *  Group calls the <code>validateDisplayList()</code> method on the IGraphicElement
     *  to give it a chance to redraw.
     *
     *  @param element The element that has changed.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function invalidateGraphicElementDisplayList(element:IGraphicElement):void
    {
        if (element.displayObject is ISharedDisplayObject)
            ISharedDisplayObject(element.displayObject).redrawRequested = true;

        // Invalidate display list only, no need to run the layout.
        super.$invalidateDisplayList();
    }
    
    /**
     *  Notify the host component that an element changed and needs to validate properties.
     *  Group calls the <code>validateProperties()</code> method on the IGraphicElement
     *  to give it a chance to commit its properties.
     *
     *  @param element The element that has changed.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function invalidateGraphicElementProperties(element:IGraphicElement):void
    {
        invalidateProperties();        
    }

    /**
     *  Notify the host component that an element size has changed.
     *  Group calls the <code>validateSize()</code> method on the IGraphicElement
     *  to give it a chance to validate its size.
     * 
     *  @param element The element that has changed size.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function invalidateGraphicElementSize(element:IGraphicElement):void
    {
        // Invalidate the size only, no need to run the layout. 
        // Later on, if the size changes, then a layout pass will be triggered.
        super.$invalidateSize();
    }
    
    /**
     *  Notify the host that an element layer has changed.
     *  Group re-evaluates the sequences of elements with shared DisplayObjects
     *  and may re-assign the DisplayObjects and redraw the sequences as a result. 
     * 
     *  @param element The element that has changed size.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function invalidateGraphicElementSharing(element:IGraphicElement):void
    {
        // One of our children have told us they might need a displayObject     
        invalidateDisplayObjectOrdering();
    }
    
    /**
     *  @private
     */
    override public function addChild(child:DisplayObject):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "addChildError")));
    }
    
    /**
     *  @private
     */
    override public function addChildAt(child:DisplayObject, index:int):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "addChildAtError")));
    }
    
    /**
     *  @private
     */
    override public function removeChild(child:DisplayObject):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "removeChildError")));
    }
    
    /**
     *  @private
     */
    override public function removeChildAt(index:int):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "removeChildAtError")));
    }
    
    /**
     *  @private
     */
    override public function setChildIndex(child:DisplayObject, index:int):void
    {
        throw(new Error(resourceManager.getString("components", "setChildIndexError")));
    }
    
    /**
     *  @private
     */
    override public function swapChildren(child1:DisplayObject, child2:DisplayObject):void
    {
        throw(new Error(resourceManager.getString("components", "swapChildrenError")));
    }
    
    /**
     *  @private
     */
    override public function swapChildrenAt(index1:int, index2:int):void
    {
        throw(new Error(resourceManager.getString("components", "swapChildrenAtError")));
    }
    
    /**
     *  @private
     *  Override to ensure we set redrawRequested when appropriate.
     */
    override public function set mouseEnabledWhereTransparent(value:Boolean):void
    {
        if (value == mouseEnabledWhereTransparent)
            return;
        
        super.mouseEnabledWhereTransparent = value;
        redrawRequested = true;
    }
    
    //--------------------------------------------------------------------------
    //
    //  ISharedDisplayObject
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    private var _redrawRequested:Boolean = false;

    /**
     *  @private
     *  Contains <code>true</code> when any of the <code>IGraphicElement</code> objects that share
     *  this <code>DisplayObject</code> object needs to redraw or the background for the container
     *  needs to be redrawn.  
     *  This is used internally
     *  by the <code>Group</code> class and developers don't typically use this. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get redrawRequested():Boolean
    {
        return _redrawRequested;
    }

    /**
     *  @private
     */
    public function set redrawRequested(value:Boolean):void
    {
        _redrawRequested = value;
    }
}
}
