////////////////////////////////////////////////////////////////////////////////
//
//  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.DisplayObject;
import flash.events.Event;
import flash.geom.PerspectiveProjection;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import flash.utils.getQualifiedClassName;

import mx.collections.IList;
import mx.core.IDataRenderer;
import mx.core.IFactory;
import mx.core.IInvalidating;
import mx.core.ILayoutElement;
import mx.core.IVisualElement;
import mx.core.mx_internal;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.PropertyChangeEvent;
import mx.managers.ILayoutManagerClient;
import mx.managers.LayoutManager;
import mx.utils.MatrixUtil;

import spark.components.supportClasses.GroupBase;
import spark.events.RendererExistenceEvent;
import spark.layouts.supportClasses.LayoutBase;

use namespace mx_internal;  // for mx_internal property contentChangeDelta


/**
 *  Dispatched when a renderer is added to this dataGroup.
 * <code>event.renderer</code> is the renderer that was added.
 *
 *  @eventType spark.events.RendererExistenceEvent.RENDERER_ADD
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="rendererAdd", type="spark.events.RendererExistenceEvent")]

/**
 *  Dispatched when a renderer is removed from this dataGroup.
 * <code>event.renderer</code> is the renderer that was removed.
 *
 *  @eventType spark.events.RendererExistenceEvent.RENDERER_REMOVE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="rendererRemove", type="spark.events.RendererExistenceEvent")]

//--------------------------------------
//  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("dataProvider")] 

[IconFile("DataGroup.png")]

/**
 *  The DataGroup class is the base container class for data items.
 *  The DataGroup class converts data items to visual elements for display.
 *  While this container can hold visual elements, it is often used only 
 *  to hold data items as children.
 *
 *  <p>The DataGroup class takes as children data items or visual elements 
 *  that implement the IVisualElement interface and are DisplayObjects.  
 *  Data items can be simple data items such String and Number objects, 
 *  and more complicated data items such as Object and XMLNode objects. 
 *  While these containers can hold visual elements, 
 *  they are often used only to hold data items as children.</p>
 *
 *  <p>An item renderer defines the visual representation of the 
 *  data item in the container. 
 *  The item renderer converts the data item into a format that can 
 *  be displayed by the container. 
 *  You must pass an item renderer to a DataGroup container to render 
 *  data items appropriately.</p>
 *
 *  <p>To improve performance and minimize application size, 
 *  the DataGroup container cannot be skinned. 
 *  If you want to apply a skin, use the SkinnableDataContainer instead. </p>
 *  
 *  <p>The DataGroup 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:DataGroup&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;s:DataGroup
 *    <strong>Properties</strong>
 *    dataProvider="null"
 *    itemRenderer="null"
 *    itemRendererFunction="null"
 *    typicalItem="null"
 *  
 *    <strong>Events</strong>
 *    rendererAdd="<i>No default</i>"
 *    rendererRemove="<i>No default</i>"
 *  /&gt;
 *  </pre>
 *
 *  @see spark.components.SkinnableDataContainer
 *  @see spark.components.Group
 *  @see spark.skins.spark.DefaultItemRenderer
 *  @see spark.skins.spark.DefaultComplexItemRenderer
 *  @includeExample examples/DataGroupExample.mxml
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class DataGroup extends GroupBase implements IItemRendererOwner
{
    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function DataGroup()
    {
        super();
        
        _rendererUpdateDelegate = this;
    }
    
    /**
     *  @private
     *  flag to indicate whether a child in the item renderer has a non-zero layer, requiring child re-ordering.
     */
    private var _layeringFlags:uint = 0;
    
    private static const LAYERING_ENABLED:uint =    0x1;
    private static const LAYERING_DIRTY:uint =      0x2;
    
    /**
     *  @private
     *  The following variables are used to track free virtual item renderers.
     *  When an item renderer is created an entry is added to rendererToFactoryMap
     *  so when it's time to move the renderer to the freeRendererMap "free list",
     *  we can store it with the other renderers produced by the same factory (IFactory).
     *  The value of rendererToFactoryMap[renderer] is a factory, the value of 
     *  freeRendererMap[factory] is the vector of free renderers produced by factory.
     */
    private var rendererToFactoryMap:Dictionary = new Dictionary(true);
    private var freeRendererMap:Dictionary = new Dictionary();
    private var addedVirtualRenderer:Boolean = false;  // see createVirtualRendererForItem()
    
    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  baselinePosition
    //----------------------------------
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function get baselinePosition():Number
    {
        if (!validateBaselinePosition())
            return NaN;
        
        if (numElements == 0)
            return super.baselinePosition;
        
        return getElementAt(0).baselinePosition + getElementAt(0).y;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  typicalItem
    //----------------------------------
    
    private var _typicalItem:Object = null;
    private var explicitTypicalItem:Object = null;
    private var typicalItemChanged:Boolean = false;
    private var typicalLayoutElement:ILayoutElement = null;
    
    [Inspectable(category="Data")]
    
    /**
     *  Layouts use the preferred size of the <code>typicalItem</code>
     *  when fixed row or column sizes are required, but a specific 
     *  <code>rowHeight</code> or <code>columnWidth</code> value is not set.
     *  Similarly virtual layouts use this item to define the size 
     *  of layout elements that have not been scrolled into view.
     *
     *  <p>The container  uses the typical data item, and the associated item renderer, 
     *  to determine the default size of the container children. 
     *  By defining the typical item, the container does not have to size each child 
     *  as it is drawn on the screen.</p>
     *
     *  <p>Setting this property sets the <code>typicalLayoutElement</code> property
     *  of the layout.</p>
     * 
     *  <p>Restriction: if the <code>typicalItem</code> is an IVisualItem, it must not 
     *  also be a member of the data Provider.</p>
     * 
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get typicalItem():Object
    {
        return _typicalItem;
    }
    
    /**
     *  @private
     */
    public function set typicalItem(value:Object):void
    {
        if (_typicalItem === value)
            return;
        _typicalItem = explicitTypicalItem = value;
        invalidateTypicalItemRenderer();
    }
    
    private function setTypicalLayoutElement(element:ILayoutElement):void
    {
        typicalLayoutElement = element;
        if (layout)
            layout.typicalLayoutElement = element;
    }
    
    /** 
     *  Call this method if some aspect of the <code>typicalItem</code> 
     *  has changed that should be reflected by the layout.  
     * 
     *  <p>This method is called automatically if the <code>typicalItem</code> 
     *  is changed directly. That means if the property is set to a new value 
     *  that is not "==" to current value.</p>
     * 
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3
     *  @productversion Flex 4.6 
     */
    public function invalidateTypicalItemRenderer():void
    {
        typicalItemChanged = true;
        invalidateProperties();
    }
    
    private function initializeTypicalItem():void
    {
        if (_typicalItem === null)
        {
            setTypicalLayoutElement(null);
            return;
        }
        
        var renderer:IVisualElement = createRendererForItem(_typicalItem, false);
        var obj:DisplayObject = DisplayObject(renderer);
        if (!obj)
        {
            setTypicalLayoutElement(null);
            return;
        }
        
        super.addChild(obj);
        setUpItemRenderer(renderer, 0, _typicalItem);
        if (obj is IInvalidating)
            IInvalidating(obj).validateNow();
        setTypicalLayoutElement(renderer);
        super.removeChild(obj);
    } 
    
    /**
     *  @private 
     *  Create and validate a new item renderer (IR) for dataProvider[index].  
     * 
     *  This method creates a new IR which is not a child of this DataGroup.  It does not 
     *  return the existing IR at the specified index and it does not cache the IRs it 
     *  creates.   This method is intended to be used by clients which need to measure 
     *  virtual IRs that may not be visible/allocated.
     */
    mx_internal function createItemRendererFor(index:int):IVisualElement
    {
        if ((index < 0) || (dataProvider == null) || (index >= dataProvider.length))
            return null;
        
        const item:Object = dataProvider.getItemAt(index);
        const renderer:IVisualElement = createRendererForItem(item);
        
        super.addChild(DisplayObject(renderer)); 
        setUpItemRenderer(renderer, index, item);
        if (renderer is IInvalidating)
            IInvalidating(renderer).validateNow();
        super.removeChild(DisplayObject(renderer));
        
        return renderer;
    }
    
    /**
     *  @private
     *  Called before measure/updateDisplayList(), if useVirtualLayout=true, to guarantee
     *  that the typicalLayoutElement has been defined.  If it hasn't, typicalItem is 
     *  initialized to dataProvider[0] and layout.typicalLayoutElement is set.
     */
    private function ensureTypicalLayoutElement():void
    {
        if (layout.typicalLayoutElement)
            return;
        
        const list:IList = dataProvider;
        if (list && (list.length > 0))
        {
            _typicalItem = list.getItemAt(0);
            
            // TextFlows are not shareable.  Soft-link TextFlow class.
            var isTextFlowClass:Boolean = 
                getQualifiedClassName(_typicalItem) == 
                    "flashx.textLayout.elements::TextFlow";
            
            if (isTextFlowClass)
                _typicalItem = _typicalItem["deepCopy"]();
            
            initializeTypicalItem();
        }
    }
    
    //----------------------------------
    //  layout
    //----------------------------------
    
    private var useVirtualLayoutChanged:Boolean = false;
    
    /**
     *  @private
     *  Sync the typicalLayoutElement var with this group's layout.
     */    
    override public function set layout(value:LayoutBase):void
    {
        var oldLayout:LayoutBase = layout;
        if (value == oldLayout)
            return; 
        
        if (oldLayout)
        {
            oldLayout.typicalLayoutElement = null;
            oldLayout.removeEventListener("useVirtualLayoutChanged", layout_useVirtualLayoutChangedHandler);
        }
        // Changing the layout may implicitly change layout.useVirtualLayout
        if (oldLayout && value && (oldLayout.useVirtualLayout != value.useVirtualLayout))
            changeUseVirtualLayout();
        super.layout = value;    
        if (value)
        {
            // If typicalLayoutElement was specified for this DataGroup, then use
            // it, otherwise use the layout's typicalLayoutElement, if any.
            if (typicalLayoutElement)
                value.typicalLayoutElement = typicalLayoutElement;
            else
                typicalLayoutElement = value.typicalLayoutElement;
            value.addEventListener("useVirtualLayoutChanged", layout_useVirtualLayoutChangedHandler);
        }
    }
    
    /**
     *  @private
     *  If layout.useVirtualLayout changes, recreate the ItemRenderers.  This can happen
     *  if the layout's useVirtualLayout property is changed directly, or if the DataGroup's
     *  layout is changed. 
     */    
    private function changeUseVirtualLayout():void
    {
        removeDataProviderListener();
        removeAllItemRenderers();
        useVirtualLayoutChanged = true;
        invalidateProperties();
    }
    
    private function layout_useVirtualLayoutChangedHandler(event:Event):void
    {
        changeUseVirtualLayout();
    }
    
    //----------------------------------
    //  itemRenderer
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the itemRenderer property.
     */
    private var _itemRenderer:IFactory;
    
    private var itemRendererChanged:Boolean;
    
    [Inspectable(category="Data")]
    
    /**
     *  The item renderer to use for data items. 
     *  The class must implement the IDataRenderer interface.
     *  If defined, the <code>itemRendererFunction</code> property
     *  takes precedence over this property.
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get itemRenderer():IFactory
    {
        return _itemRenderer;
    }
    
    /**
     *  @private
     */
    public function set itemRenderer(value:IFactory):void
    {
        _itemRenderer = value;
        
        removeDataProviderListener();
        removeAllItemRenderers();
        invalidateProperties();
        
        itemRendererChanged = true;
        typicalItemChanged = true;
    }
    
    //----------------------------------
    //  itemRendererFunction
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the itemRendererFunction property.
     */
    private var _itemRendererFunction:Function;
    
    [Inspectable(category="Data")]
    
    /**
     *  Function that returns an item renderer IFactory for a 
     *  specific item.  You should define an item renderer function 
     *  similar to this sample function:
     *  
     *  <pre>
     *    function myItemRendererFunction(item:Object):IFactory</pre>
     * 
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get itemRendererFunction():Function
    {
        return _itemRendererFunction;
    }
    
    /**
     *  @private
     */
    public function set itemRendererFunction(value:Function):void
    {
        _itemRendererFunction = value;
        
        removeDataProviderListener();
        removeAllItemRenderers();
        invalidateProperties();
        
        itemRendererChanged = true;
        typicalItemChanged = true;
    }
    
    //----------------------------------
    //  rendererUpdateDelegate
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the rendererUpdateDelegate property.
     */
    private var _rendererUpdateDelegate:IItemRendererOwner;
    
    /**
     *  @private
     *  The rendererUpdateDelgate is used to delegate item renderer
     *  updates to another component, usually the owner of the
     *  DataGroup within the context of data centric component such
     *  as List. 
     *  
     *  The registered delegate must implement the IItemRendererOwner interface.
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function get rendererUpdateDelegate():IItemRendererOwner
    {
        return _rendererUpdateDelegate;
    }
    
    /**
     *  @private
     */
    mx_internal function set rendererUpdateDelegate(value:IItemRendererOwner):void
    {
        _rendererUpdateDelegate = value;
    }
    
    //----------------------------------
    //  dataProvider
    //----------------------------------
    
    private var _dataProvider:IList;
    private var dataProviderChanged:Boolean;
    
    [Bindable("dataProviderChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  The data provider for this DataGroup. 
     *  It must be an IList.
     * 
     *  <p>There are several IList implementations included in the 
     *  Flex framework, including ArrayCollection, ArrayList, and
     *  XMLListCollection.</p>
     *
     *  @default null
     *
     *  @see #itemRenderer
     *  @see #itemRendererFunction
     *  @see mx.collections.IList
     *  @see mx.collections.ArrayCollection
     *  @see mx.collections.ArrayList
     *  @see mx.collections.XMLListCollection
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get dataProvider():IList
    {
        return _dataProvider;
    }
    
    /**
     *  @private
     */
    public function set dataProvider(value:IList):void
    {
        if (_dataProvider == value)
            return;
        
        removeDataProviderListener();
        _dataProvider = value;  // listener will be added by commitProperties()
        dataProviderChanged = true;
        invalidateProperties();
        dispatchEvent(new Event("dataProviderChanged"));        
    }
    
    /**
     *  @private
     *  Used below for sorting the virtualRendererIndices Vector.
     */
    private static function sortDecreasing(x:int, y:int):Number
    {
        return y - x;
    }
    
    /**
     *  @private
     *  Apply itemRemoved() to the renderer and dataProvider item at index.
     */
    private function removeRendererAt(index:int):void
    {
        // TODO (rfrishbe): we can't key off of the oldDataProvider for 
        // the item because it might not be there anymore (for instance, 
        // in a dataProvider reset where the new data is loaded into 
        // the dataProvider--the dataProvider doesn't actually change, 
        // but we still need to clean up).
        // Because of this, we are assuming the item is either:
        //   1.  The data property if the item implements IDataRenderer 
        //       and there is an itemRenderer or itemRendererFunction
        //   2.  The item itself
        
        // Probably could fix above by also storing indexToData[], but that doesn't 
        // seem worth it.  Sending in the wrong item here doesn't result in a big error...
        // just the event with have the wrong item associated with it
        
        const renderer:IVisualElement = indexToRenderer[index] as IVisualElement;
        if (renderer)
        {
            var item:Object;
            
            if (renderer is IDataRenderer && (itemRenderer != null || itemRendererFunction != null))
                item = IDataRenderer(renderer).data;
            else
                item = renderer;
            itemRemoved(item, index);
        }
    }
    
    /**
     *  @private
     *  Remove all of the item renderers, clear the indexToRenderer table, clear
     *  any cached virtual layout data, and clear the typical layout element.  Note that
     *  this method does not depend on the dataProvider itself, see removeRendererAt().
     */ 
    private function removeAllItemRenderers():void
    {
        if (indexToRenderer.length == 0)
            return;

        if (virtualRendererIndices && (virtualRendererIndices.length > 0))
        {
            for each (var index:int in virtualRendererIndices.concat().sort(sortDecreasing))
                removeRendererAt(index);
            
            virtualRendererIndices.length = 0;
            oldVirtualRendererIndices.length = 0;
            
            const freeRenderers:Vector.<IVisualElement> = allFreeRenderers();
            for each (var renderer:IVisualElement in freeRenderers)
                super.removeChild(renderer as DisplayObject);

            resetFreeRenderers();
        }   
        else 
        {
            for (index = indexToRenderer.length - 1; index >= 0; index--)
                removeRendererAt(index);
        }

        indexToRenderer = [];  // should be redundant
        
        if (layout)
        {
            layout.clearVirtualLayoutCache();
            layout.typicalLayoutElement = null;
        }
    }
    
    /**
     *  <p>Given a data item, return the <code>toString()</code> representation 
     *  of the data item for an item renderer to display. 
     *  Null data items return the empty string. </p>
     *
     *  @copy spark.components.IItemRendererOwner#itemToLabel()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function itemToLabel(item:Object):String
    {
        if (item !== null)
            return item.toString();
        return " ";
    }
    
    /**
     *  Return the indices of the item renderers visible within this DataGroup.
     * 
     *  <p>If <code>clipAndEnableScrolling</code> is <code>true</code>, 
     *  return the indices of the <code>visible</code> = <code>true</code> 
     *  ItemRenderers that overlap this DataGroup's <code>scrollRect</code>.
     *  That is, the ItemRenders 
     *  that are at least partially visible relative to this DataGroup.  
     *  If <code>clipAndEnableScrolling</code> is <code>false</code>, 
     *  return a list of integers from 
     *  0 to <code>dataProvider.length</code> - 1.  
     *  Note that if this DataGroup's owner is a 
     *  Scroller, then <code>clipAndEnableScrolling</code> has been 
     *  set to <code>true</code>.</p>
     * 
     *  <p>The corresponding item renderer for each returned index can be 
     *  retrieved with the <code>getElementAt()</code> method, 
     *  even if the layout is virtual</p>
     * 
     *  <p>The order of the items in the returned Vector is not guaranteed.</p>
     * 
     *  <p>Note that the VerticalLayout and HorizontalLayout classes provide bindable
     *  <code>firstIndexInView</code> and <code>lastIndexInView</code> properties 
     *  which contain the same information as this method.</p>
     * 
     *  @return The indices of the visible item renderers.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getItemIndicesInView():Vector.<int>
    {
        if (layout && layout.useVirtualLayout)
            return (virtualRendererIndices) ? virtualRendererIndices.concat() : new Vector.<int>(0);
        
        if (!dataProvider)
            return new Vector.<int>(0);
        
        const scrollR:Rectangle = scrollRect;
        const dataProviderLength:int = dataProvider.length;
        
        if (scrollR)
        {
            const visibleIndices:Vector.<int> = new Vector.<int>();
            const eltR:Rectangle = new Rectangle();
            const perspectiveProjection:PerspectiveProjection = transform.perspectiveProjection;            
            
            for (var index:int = 0; index < dataProviderLength; index++)
            {
                var elt:IVisualElement = getElementAt(index);
                if (!elt || !elt.visible)
                    continue;
                
                // TODO (egeorgie): provide a generic getElementBounds() utility function
                if (elt.hasLayoutMatrix3D && perspectiveProjection)
                {
                    eltR.x = 0; 
                    eltR.y = 0;
                    eltR.width = elt.getLayoutBoundsWidth(false);
                    eltR.height = elt.getLayoutBoundsHeight(false);                    
                    MatrixUtil.projectBounds(eltR, elt.getLayoutMatrix3D(), perspectiveProjection);
                }
                else
                {
                    eltR.x = elt.getLayoutBoundsX();
                    eltR.y = elt.getLayoutBoundsY();
                    eltR.width = elt.getLayoutBoundsWidth();
                    eltR.height = elt.getLayoutBoundsHeight();                    
                }
                
                if (scrollR.intersects(eltR))
                    visibleIndices.push(index);
            }

            return visibleIndices;
        }
        else
        {
            const allIndices:Vector.<int> = new Vector.<int>(dataProviderLength);
            for (index = 0; index < dataProviderLength; index++)
                allIndices[index] = index;
            return allIndices;
        }
    }
    
    //--------------------------------------------------------------------------
    //
    //  Item -> Renderer mapping
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Return the item renderer factory for the specified item, if any.  Prefer 
     *  itemRendererFunction over itemRenderer.
     */
    private function itemToRendererFactory(item:Object):IFactory
    {
        if (itemRendererFunction != null)
            return itemRendererFunction(item);
        
        return itemRenderer;
    }
    
    /**
     *  Return a new renderer created with the specified factory and add an entry for it
     *  to rendererToFactoryMap so that we can free and allocate it later.
     */
    private function createRenderer(factory:IFactory):IVisualElement
    {
        const element:IVisualElement = factory.newInstance() as IVisualElement;
        rendererToFactoryMap[element] = factory;
        return element;
    }
    
    /**
     *  If a vector of free renderers exists for the specified factory, remove 
     *  one and return it.
     */
    private function allocateRenderer(factory:IFactory):IVisualElement
    {
        const renderers:Vector.<IVisualElement> = freeRendererMap[factory] as Vector.<IVisualElement>;
        if (renderers)
        {
            const element:IVisualElement = renderers.pop();
            if (renderers.length == 0)
                delete freeRendererMap[factory];
            if (element)
                return element;
        }
        
        return null;
    }
    
    /**
     *  Add the specified renderer to the rendererToFactoryMap.
     */
    private function freeRenderer(renderer:IVisualElement):void
    {
        if (!renderer)
            return;
        
        const factory:IFactory = rendererToFactoryMap[renderer]; 
        if (!factory)
            return;
        
        var freeRenderers:Vector.<IVisualElement> = freeRendererMap[factory];
        if (!freeRenderers)
        {
            freeRenderers = new Vector.<IVisualElement>();
            freeRendererMap[factory] = freeRenderers;            
        }
        freeRenderers.push(renderer);
    }
    
    /** 
     *  @private
     *  Return a vector of all of the renderers in freeRendererMap.
     */
    private function allFreeRenderers():Vector.<IVisualElement>
    {
        const rv:Vector.<IVisualElement> = new Vector.<IVisualElement>();
        
        for each (var v:Vector.<IVisualElement> in freeRendererMap)
        {
            for each (var e:IVisualElement in v)
                rv.push(e);
        }
        
        return rv;
    }
    
    /**
     *  @private
     *  Reset the private free renderers data.
     */
    private function resetFreeRenderers():void
    {
        rendererToFactoryMap = new Dictionary(true);
        freeRendererMap = new Dictionary();
    }
    
    /**
     *  @private
     *  Throw an error which indicates that we were unable to create an item renderer
     *  for the specified dataProvide and we weren't able to use the item as an 
     *  item renderer.
     */
    private function throwCreateRendererFailedError(item:Object):void
    {
        var err:String;
        if (itemIsRenderer(item))
            err = resourceManager.getString("components", "cannotDisplayVisualElement");
        else
            err = resourceManager.getString("components", "unableToCreateRenderer", [item]);
        
        throw new Error(err);
    }
    
    /**
     *  @private
     *  True if the specified dataProvider item would serve as a renderer.
     */
    private function itemIsRenderer(item:Object):Boolean
    {
        return (item is IVisualElement) && (item is DisplayObject);
    }
    
    /**
     *  @private
     *  Create or reuse an item renderer for the specified dataProvider item.  This method is 
     *  used by getVirtualLayoutElementAt(), i.e. when useVirtualLayout=true.
     * 
     *  This method actually "returns" two values: the renderer itself and a flag that indicates
     *  if the renderer was newly added.   The second value is actually just a variable.  Each  
     *  time this method is called it sets addedVirtualRenderer.
     */
    private function createVirtualRendererForItem(item:Object, failRTE:Boolean=true):IVisualElement
    {
        var renderer:IVisualElement = null;
        
        const rendererFactory:IFactory = itemToRendererFactory(item);
        if (rendererFactory)
            renderer = allocateRenderer(rendererFactory);  // use a free renderer

        if (!renderer && rendererFactory)
        {
            renderer = createRenderer(rendererFactory);
            addedVirtualRenderer = true;
        }
        
        if (!renderer && itemIsRenderer(item))
        {
            renderer = IVisualElement(item);
            addedVirtualRenderer = true;            
        }
        
        if (!renderer && failRTE)
            throwCreateRendererFailedError(item);
        
        return renderer;
    }
            
    /**
     *  @private
     *  Create an item renderer for the specified dataProvider item.   This method is used
     *  when useVirtualLayout=false.
     */
    private function createRendererForItem(item:Object, failRTE:Boolean=true):IVisualElement
    {
        var renderer:IVisualElement = null;
        
        const rendererFactory:IFactory = itemToRendererFactory(item);
        if (rendererFactory)
            renderer = createRenderer(rendererFactory);
        
        if (!renderer && itemIsRenderer(item))
            renderer = IVisualElement(item);
        
        if (!renderer && failRTE)
            throwCreateRendererFailedError(item);      

        return renderer;
    }
    
    /** 
     *  @private
     *  If layout.useVirtualLayout=false, then ensure that there's one item 
     *  renderer for every dataProvider item.   This method is only intended to be
     *  called by commitProperties().
     * 
     *  Reuse as many of the IItemRenderer renderers in indexToRenders as possible.
     */
    private function createItemRenderers():void
    {
        if (!dataProvider)
        {
            removeAllItemRenderers();
            return;
        }

        if (layout && layout.useVirtualLayout)
        {   
            // Add any existing renderers to the free list.
            if (virtualRendererIndices != null && 
                virtualRendererIndices.length > 0)
            {
                startVirtualLayout();   
                finishVirtualLayout();
            }
            
            // The item renderers will be created lazily, at updateDisplayList() time
            invalidateSize();
            invalidateDisplayList();
            
            return;
        }
        
        const dataProviderLength:int = dataProvider.length; 

        // Remove the renderers we're not going to need
        for(var index:int = indexToRenderer.length - 1; index >= dataProviderLength; index--)
            removeRendererAt(index);
        
        // Reset the existing renderers
        for(index = 0; index < indexToRenderer.length; index++)
        {
            var item:Object = dataProvider.getItemAt(index);
            var renderer:IVisualElement = indexToRenderer[index] as IVisualElement;
            
            // If the (new) item is-a renderer and the old renderer is a different 
            // DisplayObject, then we can't reuse the old renderer.
            
            if (renderer && (!itemIsRenderer(item) || (item == renderer)))
            {
                setUpItemRenderer(renderer, index, item);
            }
            else
            {
                removeRendererAt(index); 
                itemAdded(item, index);
            }
        }
        
        // Create new renderers
        for (index = indexToRenderer.length; index < dataProviderLength; index++)
            itemAdded(dataProvider.getItemAt(index), index);        
    }
    
    /**
     *  @private
     */
    override protected function commitProperties():void
    { 
        // If the itemRenderer, itemRendererFunction, or useVirtualLayout properties changed,
        // then recreate the item renderers from scratch.  If just the dataProvider changed,
        // and layout.useVirtualLayout=false, then reuse as many item renderers as possible,
        // remove the extra ones, or create more as needed.
        
        if (itemRendererChanged || useVirtualLayoutChanged || dataProviderChanged)
        {
            itemRendererChanged = false;
            useVirtualLayoutChanged = false;

            // SDK-29916: The layout's cache may be in sync with the old data provider.
            // The layout will sync up its cache with the new data provider
            // when the DataGroup validateSize() / validateDisplayList().
            // By clearing the cache here, we make sure that any insert/remove 
            // events for the new dataProvider, that occur from this point on till 
            // validteSize() / validateDisplayList(), won't be mixed up with the 
            // stale layout cache state that reflects the old data provider.
            if (layout)
                layout.clearVirtualLayoutCache();
            
            // item renderers and the dataProvider listener have already been removed
            createItemRenderers();
            addDataProviderListener();

            // Don't reset the scroll positions until the new ItemRenderers have been
            // created, see bug https://bugs.adobe.com/jira/browse/SDK-23175
            if (dataProviderChanged)
            {
                dataProviderChanged = false;
                verticalScrollPosition = horizontalScrollPosition = 0;
            }
            
            maskChanged = true;
        }
        
        // Need to create item renderers before calling super.commitProperties()
        // GroupBase's commitProperties reattaches the mask
        super.commitProperties();
        
        if (_layeringFlags & LAYERING_DIRTY)
        {
            if (layout && layout.useVirtualLayout)
                invalidateDisplayList();
            else
                manageDisplayObjectLayers();
        }
        
        if (typicalItemChanged)
        {
            typicalItemChanged = false;
            initializeTypicalItem();
        }
    }
    
    /**
     *  @private
     *  True if we are updating a renderer currently. 
     *  We keep track of this so we can ignore any dataProvider collectionChange
     *  UPDATE events while we are updating a renderer just in case we try to update 
     *  the rendererInfo of the same renderer twice.  This can happen if setting the 
     *  data in an item renderer causes the data to mutate and issue a propertyChange
     *  event, which causes an collectionChange.UPDATE event in the dataProvider.  This 
     *  can happen for components which are being treated as data because the first time 
     *  they get set on the renderer, they get added to the display list, which may 
     *  cause a propertyChange event (if there's a child with an ID in it, that causes 
     *  a propertyChange event) or the data to morph in some way.
     */
    private var renderersBeingUpdated:Boolean = false;
    
    /**
     *  @private 
     *  Sets the renderer's data, owner and label properties. 
     *  It does this by calling rendererUpdateDelegate.updateRenderer().
     *  By default, rendererUpdateDelegate points to ourselves, but if 
     *  the "true owner" of the item renderer is a List, then the 
     *  rendererUpdateDelegate points to that object.  The 
     *  rendererUpdateDelegate.updateRenderer() call is in charge of 
     *  setting all the properties on the renderer, like owner, itemIndex, 
     *  data, selected, etc...  Note that data should be the last property 
     *  set in this lifecycle.
     */
    private function setUpItemRenderer(renderer:IVisualElement, itemIndex:int, data:Object):void
    {
        if (!renderer)
            return;
        
        // keep track of whether we are actively updating an renderers 
        // so we can ignore any collectionChange.UPDATE events
        renderersBeingUpdated = true;
        
        // Defer to the rendererUpdateDelegate
        // to update the renderer.  By default, the delegate is DataGroup
        _rendererUpdateDelegate.updateRenderer(renderer, itemIndex, data);
        
        // technically if this got called "recursively", this renderersBeingUpdated flag
        // would be prematurely set to false, but in most cases, this check should be 
        // good enough.
        renderersBeingUpdated = false;
    }
    
    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function updateRenderer(renderer:IVisualElement, itemIndex:int, data:Object):void
    {
        // set the owner
        renderer.owner = this;
        
        // Set the index
        if (renderer is IItemRenderer)
            IItemRenderer(renderer).itemIndex = itemIndex;
        
        // set the label to the toString() of the data 
        if (renderer is IItemRenderer)
            IItemRenderer(renderer).label = itemToLabel(data);
        
        // always set the data last
        if ((renderer is IDataRenderer) && (renderer !== data))
            IDataRenderer(renderer).data = data;
    }
    
    /**
     *  @private
     *  If the renderer at the specified index has a non-zero depth then: append it to
     *  layers.topLayerItems if depth > 0, or to layers.bottomLayerItems if depth < 0.
     *  Otherwise, if depth is zero (the default) then change the renderer's childIndex 
     *  to insertIndex and increment insertIndex.  The possibly incremented insertIndex is returned.
     *   
     *  See manageDisplayObjectLayers().
     */
    private function sortItemAt(index:int, layers:Object, insertIndex:int):int
    {
        const renderer:IVisualElement = getElementAt(index);
        const layer:Number = renderer.depth;
        
        if (layer != 0)
        {               
            if (layer > 0)
            {
                if (layers.topLayerItems == null) 
                    layers.topLayerItems = new Vector.<IVisualElement>();
                layers.topLayerItems.push(renderer);
            }
            else
            {
                if (layers.bottomLayerItems == null) 
                    layers.bottomLayerItems = new Vector.<IVisualElement>();
                layers.bottomLayerItems.push(renderer);
            }
            
            return insertIndex;                   
        }
        
        super.setChildIndex(renderer as DisplayObject, insertIndex);        
        return insertIndex + 1;
    }
    
    /**
     *  @private
     */
    private function manageDisplayObjectLayers():void
    {      
        _layeringFlags &= ~LAYERING_DIRTY;
        
        var insertIndex:uint = 0;
        const layers:Object = {topLayerItems:null,  bottomLayerItems:null};
        
        if (layout && layout.useVirtualLayout)
        {
            for each (var index:int in virtualRendererIndices)
            insertIndex = sortItemAt(index, layers, insertIndex);
        }
        else
        {
            for (index = 0; index < numElements; index++) 
                insertIndex = sortItemAt(index, layers, insertIndex);            
        }
        
        // itemRenderers should be both DisplayObjects and IVisualElements
        const topLayerItems:Vector.<IVisualElement> = layers.topLayerItems;
        const bottomLayerItems:Vector.<IVisualElement> = layers.bottomLayerItems; 
        
        var myItemRenderer:IVisualElement;
        var keepLayeringEnabled:Boolean = false;
        var len:int = numElements;
        var i:int;
        
        if (topLayerItems != null)
        {
            keepLayeringEnabled = true;
            GroupBase.sortOnLayer(topLayerItems);
            len = topLayerItems.length;
            for (i=0;i<len;i++)
            {
                myItemRenderer = topLayerItems[i];
                super.setChildIndex(myItemRenderer as DisplayObject, insertIndex++);
            }
        }
        
        if (bottomLayerItems != null)
        {
            keepLayeringEnabled = true;
            insertIndex=0;
            
            GroupBase.sortOnLayer(bottomLayerItems);
            len = bottomLayerItems.length;
            
            for (i=0;i<len;i++)
            {
                myItemRenderer = bottomLayerItems[i];
                super.setChildIndex(myItemRenderer as DisplayObject, insertIndex++);
            }
        }
        
        if (keepLayeringEnabled == false)
        {
            _layeringFlags &= ~LAYERING_ENABLED;
        } 
    }
    
    //--------------------------------------------------------------------------
    //
    //  Layout item iteration
    //
    //  Iterators used by Layout objects. For visual items, the layout item
    //  is the item itself. For data items, the layout item is the item renderer
    //  instance that is associated with the item.
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    override public function get numElements():int
    {
        return dataProvider ? dataProvider.length : 0;
    }
    
    /** 
     *  @private
     *  Maps from renderer index (same as dataProvider index) to the item renderer itself.
     */
    private var indexToRenderer:Array = []; 
    
    /**
     *  @private
     *  The set of layout element indices requested with getVirtualElementAt() 
     *  during updateDisplayList(), and the set of "old" indices that were requested
     *  in the previous pass.  These vectors are used by finishVirtualLayout()
     *  to distinguish IRs that can be recycled or discarded.   The virtualRendererIndices
     *  vector is used in various places to iterate over all of the virtual renderers.
     */
    private var virtualRendererIndices:Vector.<int> = null;
    private var oldVirtualRendererIndices:Vector.<int> = null;
    
    /**
     *  @private 
     *  During a virtual layout, virtualLayoutUnderway is true.  This flag is used 
     *  to defeat calls to invalidateSize(), which occur when IRs are lazily validated.   
     *  See invalidateSize() and updateDisplayList().
     */
    private var virtualLayoutUnderway:Boolean = false;
    
    /**
     *  @private
     *  Called before super.updateDisplayList() if layout.useVirtualLayout=true.
     *  Also called by createItemRenderers to ready existing renderers
     *  to be recycled by the following call to finishVirtualLayout.
     * 
     *  Copies virtualRendererIndices to oldRendererIndices, clears virtualRendererIndices
     *  (which will be repopulated by subsequence getVirtualElementAt() calls), and
     *  calls ensureTypicalElement().
     */
    private function startVirtualLayout():void
    {
        // lazily create the virtualRendererIndices vectors
        
        if (!virtualRendererIndices)
            virtualRendererIndices = new Vector.<int>();
        if (!oldVirtualRendererIndices)
            oldVirtualRendererIndices = new Vector.<int>();
        
        // Copy the contents virtualRendererIndices to oldVirtualRendererIndices
        // and then clear virtualRendererIndices
        
        oldVirtualRendererIndices.length = 0;
        for each (var index:int in virtualRendererIndices)
            oldVirtualRendererIndices.push(index);
        virtualRendererIndices.length = 0;
        
        // Ensure that layout.typicalLayoutElement is set
        ensureTypicalLayoutElement();
    }
    
    /**
     *  @private
     *  Called after super.updateDisplayList() finishes.  Also called by
     *  createItemRenderers to recycle existing renderers that were added
     *  to oldVirtualRendererIndices by the preceeding call to 
     *  startVirtualLayout.
     * 
     *  Discard the ItemRenderers that aren't needed anymore, i.e. the ones
     *  not explicitly requested with getVirtualElementAt() during the most
     *  recent super.updateDisplayList().
     * 
     *  Discarded IRs may be added to the freeRenderers list per the rules
     *  defined in getVirtualElementAt().  If any visible renderer has a non-zero
     *  depth we resort all of them with manageDisplayObjectLayers(). 
     */
    private function finishVirtualLayout():void
    {

        if (oldVirtualRendererIndices.length == 0)
            return;
        
        // Remove the old ItemRenderers that aren't new ItemRenderers and if 
        // recycling is possible, add them to the freeRenderers list.
        
        for each (var vrIndex:int in oldVirtualRendererIndices)
        {
            // Skip renderers that are still in view.
            if (virtualRendererIndices.indexOf(vrIndex) != -1)
                continue;
            
            // Remove previously "in view" IR from the item=>IR table
            var elt:IVisualElement = indexToRenderer[vrIndex] as IVisualElement;
            delete indexToRenderer[vrIndex];
            
            // Free or remove the IR.
            var item:Object = (dataProvider.length > vrIndex) ? dataProvider.getItemAt(vrIndex) : null;
            if ((item != elt) && (elt is IDataRenderer))
            {
                // IDataRenderer(elt).data = null;  see https://bugs.adobe.com/jira/browse/SDK-20962
                elt.includeInLayout = false;
                elt.visible = false;
                
                freeRenderer(elt);
            }
            else if (elt)
            {
                dispatchEvent(new RendererExistenceEvent(RendererExistenceEvent.RENDERER_REMOVE, false, false, elt, vrIndex, item));
                super.removeChild(DisplayObject(elt));
            }
        }
        
        // If there are any visible renderers whose depth property is non-zero
        // then use manageDisplayObjectLayers to resort the children list.  Note:
        // we're assuming that the layout has set the bounds of any elements that
        // were allocated but aren't actually visible to 0x0.
        
        var depthSortRequired:Boolean = false;
        for each (vrIndex in virtualRendererIndices)
        {
            elt = indexToRenderer[vrIndex] as IVisualElement;
            if (!elt || !elt.visible || !elt.includeInLayout)
                continue;
            if ((elt.width == 0) || (elt.height == 0))
                continue;
            if (elt.depth != 0)
            {
                depthSortRequired = true;
                break;
            }
        }
        
        if (depthSortRequired)
            manageDisplayObjectLayers();
    }
    
    /**
     *  @private
     *  This function exists for applications that need to control their footprint by
     *  allowing currently unused IRs to be garbage collected.   It is not used by the SDK.
     */
    mx_internal function clearFreeRenderers():void
    {
        resetFreeRenderers();
    }
    
    /**
     *  @private
     *  During virtual layout getLayoutElementAt() eagerly validates lazily
     *  created (or recycled) IRs.   We don't want changes to those IRs to
     *  invalidate the size of this UIComponent.
     */
    override public function invalidateSize():void
    {
        if (!virtualLayoutUnderway)
            super.invalidateSize();
    }
    
    /**
     *  @private 
     *  Make sure there's a valid typicalLayoutElement for virtual layout.
     */
    override protected function measure():void
    {
        if (layout && layout.useVirtualLayout)
            ensureTypicalLayoutElement();
        
        super.measure();
    }
    
    /**
     *  @private
     *  Manages the state required by virtual layout. 
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        drawBackground();
        
        if (layout && layout.useVirtualLayout)
        {
            virtualLayoutUnderway = true;
            startVirtualLayout();   
        }           
        
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        
        if (virtualLayoutUnderway)
        {
            finishVirtualLayout();
            virtualLayoutUnderway = false;
        }
    }
    
    /**
     *  @private
     *  
     *  Returns the ItemRenderer being used for the data provider item at the specified index.
     *  Note that if the layout is virtual, ItemRenderers that are scrolled
     *  out of view may be reused.
     * 
     *  @param index The index of the data provider item.
     *
     *  @return The ItemRenderer being used for the data provider item 
     *  If the index is invalid, or if a data provider was not specified, then
     *  return <code>null</code>.
     *  If the layout is virtual and the specified item is not in view, then
     *  return <code>null</code>.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function getElementAt(index:int):IVisualElement
    {
        if ((index < 0) || (index >= indexToRenderer.length))
            return null;
        
        return indexToRenderer[index];
    }
    
    /**
     *  @private
     */
    override public function getVirtualElementAt(index:int, eltWidth:Number=NaN, eltHeight:Number=NaN):IVisualElement
    {
        if ((index < 0) || (dataProvider == null) || (index >= dataProvider.length))
            return null;
        
        var elt:IVisualElement = indexToRenderer[index];
        
        if (virtualLayoutUnderway)
        {
            if (virtualRendererIndices.indexOf(index) == -1)
                virtualRendererIndices.push(index);
            
            var item:Object;
            
            addedVirtualRenderer = false;  // set by createVirtualRendererForItem()
            if (!elt)
            {
                item = dataProvider.getItemAt(index);
                elt = createVirtualRendererForItem(item);
                elt.visible = true;
                elt.includeInLayout = true;
                indexToRenderer[index] = elt;
                addItemRendererToDisplayList(DisplayObject(elt)); 
                setUpItemRenderer(elt, index, item);
            }
            else
            {
                // No need to set the data and label in the IR again.
                // The collectionChangeHandler will handle updates to data.
                addItemRendererToDisplayList(DisplayObject(elt)); 
            }
            
            // We have the renderer now.  getVirtualElement() is called from within layout's 
            // updateDisplayList().  This means it hasn't gone through a fully baked validation 
            // pass yet.  To get it in to a valid state, we want to first force a 
            // commitProperties() and measure() to run on our item renderer.
            if (elt is ILayoutManagerClient)
                LayoutManager.getInstance().validateClient(elt as ILayoutManagerClient, true);
            
            // Now, we can resume normal layout updateDisplayList() code.  The layout 
            // could directly run this setLayoutBoundsSize() for us, but as legacy, 
            // getVirtualElementAt() calls this on behalf of the layout system
            // if eltWidth and eltHeight are both NaN
            if (!isNaN(eltWidth) || !isNaN(eltHeight))
                elt.setLayoutBoundsSize(eltWidth, eltHeight);
            
            if (addedVirtualRenderer) 
                dispatchEvent(new RendererExistenceEvent(RendererExistenceEvent.RENDERER_ADD, false, false, elt, index, item));
        }
        
        return elt;
    }
    
    /**
     *  @private
     *  
     *  Returns the index of the data provider item
     *  that the specified item renderer
     *  is being used for, or -1 if there is no such item. 
     *  Note that if the layout is virtual, ItemRenderers that are scrolled
     *  out of view may be reused.
     * 
     *  @param element The item renderer.
     *
     *  @return The index of the data provider item. 
     *  If <code>renderer</code> is <code>null</code>, or if the <code>dataProvider</code>
     *  property was not specified, then return -1.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function getElementIndex(element:IVisualElement):int
    {
        if ((dataProvider == null) || (element == null))
            return -1;
        
        return indexToRenderer.indexOf(element);
    }
    
    
    /**
     *  @private
     */
    override public function invalidateLayering():void
    {
        _layeringFlags |= (LAYERING_ENABLED | LAYERING_DIRTY);
        invalidateProperties();
    }
    
    /**
     *  @private
     *  Set the itemIndex of the IItemRenderer at index to index. See resetRenderersIndices.
     */
    private function resetRendererItemIndex(index:int):void
    {
        var renderer:IItemRenderer = indexToRenderer[index] as IItemRenderer;
        if (renderer)
            renderer.itemIndex = index;    
    }
    
    
    /**
     *  @private
     *  Recomputes every renderer's index.
     *  This is useful when an item gets added that may change the renderer's 
     *  index.  In turn, this index may cuase the renderer to change appearance, 
     *  like when alternatingItemColors is used.
     */
    private function resetRenderersIndices():void
    {
        if (indexToRenderer.length == 0)
            return;
        
        if (layout && layout.useVirtualLayout)
        {
            for each (var index:int in virtualRendererIndices)
                resetRendererItemIndex(index);
        }
        else
        {
            const indexToRendererLength:int = indexToRenderer.length;
            for (index = 0; index < indexToRendererLength; index++)
                resetRendererItemIndex(index);
            // TODO (rfrishbe): could make this more optimal by only re-computing a subset of the visible
            // item renderers, but it's probably not worth it
        }
    }
    
    /**
     *  Adds the itemRenderer for the specified dataProvider item to this DataGroup.
     * 
     *  This method is called as needed by the DataGroup implementation,
     *  it should not be called directly.
     *
     *  @param item The item that was added, the value of dataProvider[index].
     *  @param index The index where the dataProvider item was added.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function itemAdded(item:Object, index:int):void
    {
        if (layout)
            layout.elementAdded(index);
        
        if (layout && layout.useVirtualLayout)
        {
            // Increment all of the indices in virtualRendererIndices that are >= index.
            
            if (virtualRendererIndices)
            {
                const virtualRendererIndicesLength:int = virtualRendererIndices.length;
                for (var i:int = 0; i < virtualRendererIndicesLength; i++)
                {
                    const vrIndex:int = virtualRendererIndices[i];
                    if (vrIndex >= index)
                        virtualRendererIndices[i] = vrIndex + 1;
                }
                
                indexToRenderer.splice(index, 0, null); // shift items >= index to the right
                // virtual ItemRenderer itself will be added lazily, by updateDisplayList()
            }
            
            invalidateSize();
            invalidateDisplayList();
            return;
        }
        
        var myItemRenderer:IVisualElement = createRendererForItem(item);
        indexToRenderer.splice(index, 0, myItemRenderer);
        addItemRendererToDisplayList(myItemRenderer as DisplayObject, index);
        setUpItemRenderer(myItemRenderer, index, item);
        dispatchEvent(new RendererExistenceEvent(
            RendererExistenceEvent.RENDERER_ADD, false, false, 
            myItemRenderer, index, item));
        
        invalidateSize();
        invalidateDisplayList();
    }
    
    /**
     *  Removes the itemRenderer for the specified dataProvider item from this DataGroup.
     * 
     *  This method is called as needed by the DataGroup implementation,
     *  it should not be called directly.
     *
     *  @param item The item that is being removed.
     * 
     *  @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 itemRemoved(item:Object, index:int):void
    {
        if (layout)
            layout.elementRemoved(index);
        
        // Decrement all of the indices in virtualRendererIndices that are > index
        // Remove the one (at vrItemIndex) that equals index.
        
        if (virtualRendererIndices && (virtualRendererIndices.length > 0))
        {
            var vrItemIndex:int = -1;  // location of index in virtualRendererIndices 
            const virtualRendererIndicesLength:int = virtualRendererIndices.length;
            for (var i:int = 0; i < virtualRendererIndicesLength; i++)
            {
                const vrIndex:int = virtualRendererIndices[i];
                if (vrIndex == index)
                    vrItemIndex = i;
                else if (vrIndex > index)
                    virtualRendererIndices[i] = vrIndex - 1;
            }
            if (vrItemIndex != -1)
                virtualRendererIndices.splice(vrItemIndex, 1);
        }
        
        // Remove the old renderer at index (if any) from indexToRenderer[], from the
        // DataGroup, and clear its data property (if any).
        
        const oldRenderer:IVisualElement = indexToRenderer[index];
        
        if (indexToRenderer.length > index)
            indexToRenderer.splice(index, 1);
        
        if (oldRenderer)
        {
            dispatchEvent(new RendererExistenceEvent(
                RendererExistenceEvent.RENDERER_REMOVE, false, false, oldRenderer, index, item));
            
            if (oldRenderer is IDataRenderer && oldRenderer !== item)
                IDataRenderer(oldRenderer).data = null;
            
            var child:DisplayObject = oldRenderer as DisplayObject;
            if (child)
                super.removeChild(child);
        }
        
        invalidateSize();
        invalidateDisplayList();
    }
    
    /**
     *  @private
     */ 
    private function addItemRendererToDisplayList(child:DisplayObject, index:int = -1):void
    { 
        const childParent:Object = child.parent;
        const overlayCount:int = _overlay ? _overlay.numDisplayObjects : 0;
        const childIndex:int = (index != -1) ? index : super.numChildren - overlayCount;
        
        if (childParent == this)
        {
            super.setChildIndex(child, childIndex - 1);
            return;
        }
        
        if (childParent is DataGroup)
            DataGroup(childParent)._removeChild(child);
        
        if ((_layeringFlags & LAYERING_ENABLED) || 
            (child is IVisualElement && (child as IVisualElement).depth != 0))
            invalidateLayering();

        super.addChildAt(child, childIndex);
    }
    
    /**
     *  @private
     */
    private function addDataProviderListener():void
    {
        if (_dataProvider)
            _dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, dataProvider_collectionChangeHandler, false, 0, true);
    }

    /**
     *  @private
     */
    private function removeDataProviderListener():void
    {
        if (_dataProvider)
            _dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, dataProvider_collectionChangeHandler);
    }

    /**
     *  @private
     *  Called when contents within the dataProvider changes.  We will catch certain 
     *  events and update our children based on that.
     *
     *  @param event The collection change event
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function dataProvider_collectionChangeHandler(event:CollectionEvent):void
    {
        switch (event.kind)
        {
            case CollectionEventKind.ADD:
            {
                // items are added
                // figure out what items were added and where
                // for virtualization also figure out if items are now in view
                adjustAfterAdd(event.items, event.location);
                break;
            }
                
            case CollectionEventKind.REPLACE:
            {
                // items are replaced
                adjustAfterReplace(event.items, event.location);
                break;
            }
                
            case CollectionEventKind.REMOVE:
            {
                // items are added
                // figure out what items were removed
                // for virtualization also figure out what items are now in view
                adjustAfterRemove(event.items, event.location);
                break;
            }
                
            case CollectionEventKind.MOVE:
            {
                // one item is moved
                adjustAfterMove(event.items[0], event.location, event.oldLocation);
                break;
            }
                
            case CollectionEventKind.REFRESH:
            {
                // from a filter or sort...let's just reset everything
                removeDataProviderListener();
                dataProviderChanged = true;
                invalidateProperties();
                break;
            }
                
            case CollectionEventKind.RESET:
            {
                // reset everything
                removeDataProviderListener();                
                dataProviderChanged = true;
                invalidateProperties();
                break;
            }
                
            case CollectionEventKind.UPDATE:
            {
                // if a renderer is currently being updated, let's 
                // just ignore any UPDATE events.
                if (renderersBeingUpdated)
                    break;
                
                //update the renderer's data and data-dependant
                //properties. 
                for (var i:int = 0; i < event.items.length; i++)
                {
                    var pe:PropertyChangeEvent = event.items[i]; 
                    if (pe)
                    {
                        var index:int = dataProvider.getItemIndex(pe.source);
                        var renderer:IVisualElement = indexToRenderer[index];
                        setUpItemRenderer(renderer, index, pe.source); 
                    }
                }
                break;
            }
        }
    }
    
    /**
     *  @private
     */
    private function adjustAfterAdd(items:Array, location:int):void
    {
        var length:int = items.length;
        for (var i:int = 0; i < length; i++)
        {
            itemAdded(items[i], location + i);
        }
        
        // the order might have changed, so we might need to redraw the other 
        // renderers that are order-dependent (for instance alternatingItemColor)
        resetRenderersIndices();
    }
    
    /**
     *  @private
     */
    private function adjustAfterRemove(items:Array, location:int):void
    {
        var length:int = items.length;
        for (var i:int = length-1; i >= 0; i--)
        {
            itemRemoved(items[i], location + i);
        }
        
        // the order might have changed, so we might need to redraw the other 
        // renderers that are order-dependent (for instance alternatingItemColor)
        resetRenderersIndices();
    }
    
    /**
     *  @private
     */
    private function adjustAfterMove(item:Object, location:int, oldLocation:int):void
    {
        itemRemoved(item, oldLocation);
        itemAdded(item, location);
        resetRenderersIndices();
    }
    
    /**
     *  @private
     */
    private function adjustAfterReplace(items:Array, location:int):void
    {
        var length:int = items.length;
        for (var i:int = length-1; i >= 0; i--)
        {
            itemRemoved(items[i].oldValue, location + i);               
        }
        
        for (i = length-1; i >= 0; i--)
        {
            itemAdded(items[i].newValue, location);
        }
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods: Access to overridden methods of base classes
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     * 
     *  This method allows access to the base class's implementation
     *  of removeChild() (UIComponent's version), which can be useful since components
     *  can override removeChild() and thereby hide the native implementation.  For 
     *  instance, we override removeChild() here to throw an RTE to discourage people
     *  from using this method.  We need this method so we can remove children
     *  that were previously attached to another DataGroup (see addItemToDisplayList).
     */
    private function _removeChild(child:DisplayObject):DisplayObject
    {
        return super.removeChild(child);
    }
    
    /**
     *  @private
     */
    override public function addChild(child:DisplayObject):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "addChildDataGroupError")));
    }
    
    /**
     *  @private
     */
    override public function addChildAt(child:DisplayObject, index:int):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "addChildAtDataGroupError")));
    }
    
    /**
     *  @private
     */
    override public function removeChild(child:DisplayObject):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "removeChildDataGroupError")));
    }
    
    /**
     *  @private
     */
    override public function removeChildAt(index:int):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "removeChildAtDataGroupError")));
    }
    
    /**
     *  @private
     */
    override public function setChildIndex(child:DisplayObject, index:int):void
    {
        throw(new Error(resourceManager.getString("components", "setChildIndexDataGroupError")));
    }
    
    /**
     *  @private
     */
    override public function swapChildren(child1:DisplayObject, child2:DisplayObject):void
    {
        throw(new Error(resourceManager.getString("components", "swapChildrenDataGroupError")));
    }
    
    /**
     *  @private
     */
    override public function swapChildrenAt(index1:int, index2:int):void
    {
        throw(new Error(resourceManager.getString("components", "swapChildrenAtDataGroupError")));
    }
}
}
