////////////////////////////////////////////////////////////////////////////////
//
//  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.supportClasses
{

import flash.events.Event;
import flash.events.MouseEvent;

import mx.collections.IList;
import mx.core.FlexVersion;
import mx.core.IVisualElement;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.FlexEvent;

import spark.components.IItemRenderer;
import spark.components.IItemRendererOwner;
import spark.components.SkinnableDataContainer;
import spark.components.supportClasses.IDataProviderEnhance;
import spark.components.supportClasses.RegExPatterns;
import spark.events.IndexChangeEvent;
import spark.events.ListEvent;
import spark.events.RendererExistenceEvent;
import spark.layouts.supportClasses.LayoutBase;
import spark.utils.LabelUtil;

use namespace mx_internal;  //ListBase and List share selection properties that are mx_internal

/**
 *  Dispatched when the user rolls the mouse pointer over an item in the control.
 *
 *  @eventType spark.events.ListEvent.ITEM_ROLL_OVER
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10.2
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="itemRollOver", type="spark.events.ListEvent")]

/**
 *  Dispatched when the user rolls the mouse pointer out of an item in the control.
 *
 *  @eventType spark.events.ListEvent.ITEM_ROLL_OUT
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10.2
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="itemRollOut", type="spark.events.ListEvent")]

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

/**
 *  Dispatched when the selection is going to change. 
 *  Calling the <code>preventDefault()</code> method
 *  on the event prevents the selection from changing.
 *  
 *  <p>This event is dispatched when the user interacts with the control.
 *  When you change the value of the <code>selectedIndex</code> 
 *  or <code>selectedItem</code> properties programmatically, 
 *  the control does not dispatch the <code>changing</code> event. 
 *  It dispatches the <code>valueCommit</code> event instead.</p>
 *
 *  @eventType spark.events.IndexChangeEvent.CHANGING
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="changing", type="spark.events.IndexChangeEvent")]

/**
 *  Dispatched after the selection has changed. 
 *  This event is dispatched when the user interacts with the control.
 * 
 *  <p>When you change the value of the <code>selectedIndex</code> 
 *  or <code>selectedItem</code> properties programmatically, 
 *  the control does not dispatch the <code>change</code> event. 
 *  It dispatches the <code>valueCommit</code> event instead.</p>
 *
 *  @eventType spark.events.IndexChangeEvent.CHANGE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="change", type="spark.events.IndexChangeEvent")]

/**
 *  Dispatched after the focus has changed.  
 *
 *  @eventType spark.events.IndexChangeEvent.CARET_CHANGE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="caretChange", type="spark.events.IndexChangeEvent")]

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

[AccessibilityClass(implementation="spark.accessibility.ListBaseAccImpl")]

/**
 *  The ListBase class is the base class for all components that support
 *  selection. 
 *
 *  <p><b>Note: </b>The Spark list-based controls (the Spark ListBase class and its subclasses
 *  such as ButtonBar, ComboBox, DropDownList, List, and TabBar) do not support the BasicLayout class
 *  as the value of the <code>layout</code> property. 
 *  Do not use BasicLayout with the Spark list-based controls.</p>
 *
 *  @mxml <p>The <code>&lt;s:ListBase&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;s:ListBase
 *
 *    <strong>Properties</strong>
 *    arrowKeysWrapFocus="false"
 *    labelField="label"
 *    labelFunction="null"
 *    requireSelection="false"
 *    selectedIndex="-1"
 *    selectedItem="undefined"
 *    useVirtualLayout="false"
 * 
 *    <strong>Events</strong>
 *    caretChange="<i>No default</i>"
 *    change="<i>No default</i>"
 *    changing="<i>No default</i>"
 *  /&gt;
 *  </pre>
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class ListBase extends SkinnableDataContainer implements IDataProviderEnhance
{
    include "../../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Class constants
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Static constant representing the value "no selection".
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public static const NO_SELECTION:int = -1;
    
    /**
     *  @private
     *  Static constant representing no proposed selection.
     */
    mx_internal static const NO_PROPOSED_SELECTION:int = -2;
    
    /**
     *  @private
     *  Static constant representing no item in focus. 
     */
    private static const NO_CARET:int = -1;
    
    /**
     *  @private
     */
    mx_internal static var CUSTOM_SELECTED_ITEM:int = -3;

    /**
     *  @private
     *  Static constant representing no item in focus. 
     */
    private static const TYPE_MAP:Object = { rollOver: "itemRollOver",
                                             rollOut:  "itemRollOut" };
    

    //--------------------------------------------------------------------------
    //
    //  Class mixins
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Placeholder for mixin by ListBaseAccImpl.
     */
    mx_internal static var createAccessibilityImplementation:Function;

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function ListBase()
    {
        super();
    }
    
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    mx_internal var allowCustomSelectedItem:Boolean = false;
    
    /**
     *  @private
     */
    mx_internal var dispatchChangeAfterSelection:Boolean = false;
    
    /**
     *  @private
     *  Used to keep track of whether selection transitions should play 
     *  in the updateRenderer() code.  See turnOnSelectionTransitionsForOneFrame()
     */
    private var allowSelectionTransitions:Boolean = false;
    
    /**
     *  @private
     *  Used to keep track of whether caret transitions should play 
     *  in the updateRenderer() code.  See turnOnCaretTransitionsForOneFrame()
     */
    private var allowCaretTransitions:Boolean = false;
    
    /**
     *  @private
     *  Used to keep track of whether we are in updateRenderer().  This is 
     *  so we know that any calls to itemSelected() and itemShowingCaret(), 
     *  are called based on a user-action (either interaction or programattic) 
     *  and not through item renderer recycling.
     */
    private var inUpdateRenderer:Boolean;
    
    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  baselinePosition
    //----------------------------------

    /**
     *  @private
     *  The baseline position of a ListBase is calculated for the first item renderer.
     *  If there are no items, one is temporarily added to do the calculation.
     */
    override public function get baselinePosition():Number
    {
        if (!validateBaselinePosition())
            return NaN;
        
        // Fabricate temporary data provider if necessary.
        var isNull:Boolean = dataProvider == null;
        var isEmpty:Boolean = dataProvider != null && dataProvider.length == 0;
         
        if (isNull || isEmpty)
        {
            var originalProvider:IList = isEmpty ? dataProvider : null;
			//TODO (jmclean) seems odd to me double check
            dataProvider = new mx.collections.ArrayList([ {} ]);
            validateNow();
        }
        
        if (!dataGroup || dataGroup.numElements == 0)
            return super.baselinePosition;
        
        // Obtain reference to newly generated item element which will be used
        // to compute the baseline.
        var listItem:Object = dataGroup ? dataGroup.getElementAt(0) : undefined;
        if (!listItem)
            return super.baselinePosition;
        
        // Compute baseline position of item relative to our list component.
        if ("baselinePosition" in listItem)
            var result:Number = getSkinPartPosition(IVisualElement(listItem)).y + listItem.baselinePosition;
        else    
            super.baselinePosition;

        // Restore the previous state of our list.
        if (isNull || isEmpty)
        {
            if (isNull)
                dataProvider = null;
            else if (isEmpty)
                dataProvider = originalProvider;
                
            validateNow();
        }
        
        return result;
    }
        
    //----------------------------------
    //  dataProvider
    //----------------------------------

    /**
     *  @private
     */
    private var dataProviderChanged:Boolean;
    
    [Inspectable(category="Data")]
    
    /**
     *  @private
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function set dataProvider(value:IList):void
    {
        if (dataProvider)
            dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, dataProvider_collectionChangeHandler);
    
        dataProviderChanged = true;
        doingWholesaleChanges = true;
        
        // ensure that our listener is added before the dataGroup which adds a listener during
        // the base class setter if the dataGroup already exists.  If the dataGroup isn't
        // created yet, then we still be first.
        if (value)
            value.addEventListener(CollectionEvent.COLLECTION_CHANGE, dataProvider_collectionChangeHandler, false, 0, true);

        super.dataProvider = value;
        invalidateProperties();
    }
    
    //----------------------------------
    //  layout
    //----------------------------------

    /**
     *  @private
     */
    override public function set layout(value:LayoutBase):void
    {
        if (value && useVirtualLayout)
            value.useVirtualLayout = true;

        super.layout = value;
    }

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  arrowKeysWrapFocus
    //---------------------------------- 
    
    /**
     *  If <code>true</code>, using arrow keys to navigate within
     *  the component wraps when it hits either end.
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var arrowKeysWrapFocus:Boolean;

    //----------------------------------
    //  caretIndex
    //----------------------------------
    
    /**
     *  @private
     */
    mx_internal var _caretIndex:Number = NO_CARET; 
    
    [Bindable("caretChange")]

    /**
     *  Item that is currently in focus. 
     *
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get caretIndex():Number
    {
        return _caretIndex;
    }
    
    /**
     *  @private
     */
    mx_internal var doingWholesaleChanges:Boolean = false;
    
    //----------------------------------
    //  caretItem
    //---------------------------------- 

    /**
     *  @private
     *  This private variable differs from selectedItem in that
     *  the value is not computed, it's cached each time setCurrentCaretIndex() is called.  
     *  It's used by List/dataProviderRefreshed() to provide a little scroll position and 
     *  selection/caret stability after a dataProvider refresh.
     */
    mx_internal var caretItem:* = undefined;


    //----------------------------------
    //  isFirstRow
    //----------------------------------

    /**
    *  Returns if the selectedIndex is equal to the first row.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function get isFirstRow():Boolean
    {
        if (dataProvider && dataProvider.length > 0)
        {
            if (selectedIndex == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }


    //----------------------------------
    //  isLastRow
    //----------------------------------

    /**
    *  Returns if the selectedIndex is equal to the last row.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function get isLastRow():Boolean
    {
        if (dataProvider && dataProvider.length > 0)
        {
            if (selectedIndex == dataProvider.length - 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }


    //----------------------------------
    //  labelField
    //----------------------------------

    /**
     *  @private
     */
    private var _labelField:String = "label";
    
    /**
     *  @private
     */
    private var labelFieldOrFunctionChanged:Boolean; 
    
    [Inspectable(category="Data", defaultValue="label")]

    /**
     *  The name of the field in the data provider items to display 
     *  as the label. 
     * 
     *  If labelField is set to an empty string (""), no field will 
     *  be considered on the data provider to represent label.
     * 
     *  The <code>labelFunction</code> property overrides this property.
     *
     *  @default "label" 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get labelField():String
    {
        return _labelField;
    }
    
    /**
     *  @private
     */
    public function set labelField(value:String):void
    {
        if (value == _labelField)
            return;
            
        _labelField = value;
        labelFieldOrFunctionChanged = true;
        invalidateProperties();
    }
    
    //----------------------------------
    //  labelFunction
    //----------------------------------
    
    /**
     *  @private
     */
    private var _labelFunction:Function; 
    
    [Inspectable(category="Data")]
    
    /**
     *  A user-supplied function to run on each item to determine its label.  
     *  The <code>labelFunction</code> property overrides 
     *  the <code>labelField</code> property.
     *
     *  <p>You can supply a <code>labelFunction</code> that finds the 
     *  appropriate fields and returns a displayable string. The 
     *  <code>labelFunction</code> is also good for handling formatting and 
     *  localization. </p>
     *
     *  <p>The label function takes a single argument which is the item in 
     *  the data provider and returns a String.</p>
     *  <pre>
     *  myLabelFunction(item:Object):String</pre>
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get labelFunction():Function
    {
        return _labelFunction;
    }
    
    /**
     *  @private
     */
    public function set labelFunction(value:Function):void
    {
        if (value == _labelFunction)
            return;
            
        _labelFunction = value;
        labelFieldOrFunctionChanged = true;
        invalidateProperties(); 
    }


    //----------------------------------
    //  preventSelection
    //----------------------------------

    /**
    *  @private
    */
    private var _preventSelection:Boolean = false;


    /**
    *  If <code>true</code> items will be prevented from being selected.  The <code>selectedIndex</code> value should always be -1.
    *  When this is set to <code>true</code>, it will set the <code>requireSelection</code> to false.
    *  Click events will continue to be called.
    *
    *  @default false
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function get preventSelection():Boolean
    {
        return _preventSelection;
    }

    public function set preventSelection(newValue:Boolean):void
    {
        if (newValue == _preventSelection)
        {
            return;
        }


        if (newValue == true)
        {
            //Make sure to disable requireSelection since these two properties are polar opposites.
            requireSelection = false;

            //Remove any previous selection and allow it to update before enabling the prevent selection.
            setSelectedIndex(NO_SELECTION, false);
            validateNow();
        }

        _preventSelection = newValue;
    }


    //----------------------------------
    //  requireSelection
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the requireSelection property.
     */
    private var _requireSelection:Boolean = false;
    
    /**
     *  @private
     *  Flag that is set when requireSelection has changed.
     */
    private var requireSelectionChanged:Boolean = false;

    [Inspectable(category="General", defaultValue="false")]
    
    /**
     *  If <code>true</code>, a data item must always be selected in the control.
     *  If the value is <code>true</code>, the <code>selectedIndex</code> property 
     *  is always set to a value between 0 and (<code>dataProvider.length</code> - 1).
     * 
     * <p>The default value is <code>false</code> for most subclasses, except TabBar. In that case, the default is <code>true</code>.</p>
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get requireSelection():Boolean
    {
        return _requireSelection;
    }

    /**
     *  @private
     */
    public function set requireSelection(value:Boolean):void
    {
        if (value == _requireSelection)
            return;
            
        _requireSelection = value;
        
        // We only need to update if the value is changing 
        // from false to true
        if (value == true)
        {
            //Make sure to disable preventSelection since these two properties are polar opposites.
            preventSelection = false;

            requireSelectionChanged = true;
            invalidateProperties();
        }
    }
    
    //----------------------------------
    //  selectedIndex
    //----------------------------------

    /**
     *  @private
     *  The proposed selected index. This is a temporary variable that is
     *  used until the selected index is committed.
     */
    mx_internal var _proposedSelectedIndex:int = NO_PROPOSED_SELECTION;
    
	/** 
	 *  @private
	 *  Flag that is set when the selectedIndex has been adjusted due to
	 *  items being added or removed. When this flag is true, the value
	 *  of the selectedIndex has changed, but the actual selected item
	 *  is the same. 
     *  This flag can also be set if the selectedItem has changed to ensure
     *  a valueCommit is dispatched even if the selectedIndex has not changed.
     *  This flag is cleared in commitProperties().
	 */
	mx_internal var selectedIndexAdjusted:Boolean = false;
	
    /** 
     *  @private
     *  Flag that is set when the caretIndex has been adjusted due to
     *  items being added or removed. This flag is cleared in 
     *  commitProperties().
     */
    mx_internal var caretIndexAdjusted:Boolean = false;
    
    /**
     *  @private
     *  Keeps track of whether the caret should change when selection changes. 
     *  By default it is true
     */
    mx_internal var changeCaretOnSelection:Boolean = true;
    
    /**
     *  @private
     *  Internal storage for the selectedIndex property.
     */
    mx_internal var _selectedIndex:int = NO_SELECTION;
    
    [Bindable("change")]
    [Bindable("valueCommit")]
    [Inspectable(category="General", defaultValue="-1")]
    
    /**
     *  The 0-based index of the selected item, or -1 if no item is selected.
     *  Setting the <code>selectedIndex</code> property deselects the currently selected
     *  item and selects the data item at the specified index.
     *
     *  <p>The value is always between -1 and (<code>dataProvider.length</code> - 1). 
     *  If items at a lower index than <code>selectedIndex</code> are 
     *  removed from the component, the selected index is adjusted downward
     *  accordingly.</p>
     *
     *  <p>If the selected item is removed, the selected index is set to:</p>
     *
     *  <ul>
     *    <li>-1 if <code>requireSelection</code> = <code>false</code> 
     *     or there are no remaining items.</li>
     *    <li>0 if <code>requireSelection</code> = <code>true</code> 
     *     and there is at least one item.</li>
     *  </ul>
     *
     *  <p>When the user changes the <code>selectedIndex</code> property by interacting with the control,
     *  the control dispatches the <code>change</code> and <code>changing</code> events. 
     *  When you change the value of the <code>selectedIndex</code> property programmatically,
     *  it dispatches the <code>valueCommit</code> event.</p>
     *
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get selectedIndex():int
    {
        if (_proposedSelectedIndex != NO_PROPOSED_SELECTION)
            return _proposedSelectedIndex;
            
        return _selectedIndex;
    }
    
    /**
     *  @private
     */
    public function set selectedIndex(value:int):void
    {
        setSelectedIndex(value, false);
    }
    
    /**
     *  <p>The <code>rowIndex</code> is the index in the data provider
     *  of the item containing the selected cell.</p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     * 
     *  @param dispatchChangeEvent if true, the component will dispatch a "change" event if the
     *  rowIndex has changed. Otherwise, it will dispatch a "valueCommit" event. 
     * 
     *  @param changeCaret if true, the caret will be set to the selectedIndex as a side-effect of calling 
     *  this method.  If false, caretIndex won't change.
     *
     *  @langversion 3.0
     *  @playerversion Flash 11.1
     *  @playerversion AIR 3.4
     *  @productversion Flex 4.10
     */
    public function setSelectedIndex(rowIndex:int, dispatchChangeEvent:Boolean = false, changeCaret:Boolean = true):void
    {
        if (rowIndex == selectedIndex)
        {
            // this should short-circuit, but we should check to make sure 
            // that caret doesn't need to be changed either, as that's a side
            // effect of setting selectedIndex
            if (changeCaret)
                setCurrentCaretIndex(selectedIndex);
            
            return;
        }
        
        if (dispatchChangeEvent)
            dispatchChangeAfterSelection = (dispatchChangeAfterSelection || dispatchChangeEvent);
        changeCaretOnSelection = changeCaret;
        _proposedSelectedIndex = rowIndex;
        invalidateProperties();
    }

    //----------------------------------
    //  selectedItem
    //----------------------------------
    
    /**
     *  @private
     */
    mx_internal var _pendingSelectedItem:*;

    /**
     *  @private
     */
    private var _selectedItem:*;
    
    [Bindable("change")]
    [Bindable("valueCommit")]
    [Inspectable(category="General", defaultValue="null")]
    
    /**
     *  The item that is currently selected. 
     *  Setting this property deselects the currently selected 
     *  item and selects the newly specified item.
     *
     *  <p>Setting <code>selectedItem</code> to an item that is not 
     *  in this component results in no selection, 
     *  and <code>selectedItem</code> being set to <code>undefined</code>.</p>
     * 
     *  <p>If the selected item is removed, the selected item is set to:</p>
     *
     *  <ul>
     *    <li><code>undefined</code> if <code>requireSelection</code> = <code>false</code> 
     *      or there are no remaining items.</li>
     *    <li>The first item if <code>requireSelection</code> = <code>true</code> 
     *      and there is at least one item.</li>
     *  </ul>
     *
     *  <p>When the user changes the <code>selectedItem</code> property by interacting with the control,
     *  the control dispatches the <code>change</code> and <code>changing</code> events. 
     *  When you change the value of the <code>selectedItem</code> property programmatically,
     *  it dispatches the <code>valueCommit</code> event.</p>
     *
     *  @default undefined
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get selectedItem():*
    {
        if (_pendingSelectedItem !== undefined)
            return _pendingSelectedItem;
            
        if (allowCustomSelectedItem && selectedIndex == CUSTOM_SELECTED_ITEM)
            return _selectedItem;
        
        if (selectedIndex < 0 || dataProvider == null)
           return undefined;
           
        return dataProvider.length > selectedIndex ? dataProvider.getItemAt(selectedIndex) : undefined;
    }
    
    /**
     *  @private
     */
    public function set selectedItem(value:*):void
    {
        setSelectedItem(value, false);
    }

    /**
     *  @private
     *  Used internally to specify whether the selectedItem changed programmatically or due to 
     *  user interaction. 
     * 
     *  @param dispatchChangeEvent if true, the component will dispatch a "change" event if the
     *  value has changed. Otherwise, it will dispatch a "valueCommit" event. 
     */
    mx_internal function setSelectedItem(value:*, dispatchChangeEvent:Boolean = false):void
    {
        if (selectedItem === value)
            return;
        
        if (dispatchChangeEvent)
            dispatchChangeAfterSelection = (dispatchChangeAfterSelection || dispatchChangeEvent);
		
        // ensure that a "valueCommit" is dispatched even if the selectedIndex did not change.
        selectedIndexAdjusted = true;
	
        _pendingSelectedItem = value;
        invalidateProperties();
    }
    
    //----------------------------------
    //  useVirtualLayout
    //----------------------------------

    /**
     *  @private
     */
    private var _useVirtualLayout:Boolean = false;
    
    /**
     *  Sets the value of the <code>useVirtualLayout</code> property
     *  of the layout associated with this control.  
     *  If the layout is subsequently replaced and the value of this 
     *  property is <code>true</code>, then the new layout's 
     *  <code>useVirtualLayout</code> property is set to <code>true</code>.
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get useVirtualLayout():Boolean
    {
        return (layout) ? layout.useVirtualLayout : _useVirtualLayout;
    }

    /**
     *  @private
     *  Note: this property deviates a little from the conventional delegation pattern.
     *  If the user explicitly sets ListBase.useVirtualLayout=false and then sets
     *  the layout property to a layout with useVirtualLayout=true, the layout's value
     *  for this property trumps the ListBase.  The convention dictates opposite
     *  however in this case, always honoring the layout's useVirtalLayout property seems 
     *  less likely to cause confusion.
     */
    public function set useVirtualLayout(value:Boolean):void
    {
        if (value == useVirtualLayout)
            return;
            
        _useVirtualLayout = value;
        if (layout)
            layout.useVirtualLayout = value;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    override protected function initializeAccessibility():void
    {
        if (ListBase.createAccessibilityImplementation != null)
            ListBase.createAccessibilityImplementation(this);
    }
    
    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        var e:IndexChangeEvent; 
        var changedSelection:Boolean = false;
        
        super.commitProperties();
        
        if (dataProviderChanged)
        {
            dataProviderChanged = false;
            doingWholesaleChanges = false;
        
            if (selectedIndex >= 0 && dataProvider && selectedIndex < dataProvider.length)
               itemSelected(selectedIndex, true);
            else if (requireSelection)
               _proposedSelectedIndex = 0;
            else
               setSelectedIndex(-1, false);
        }
            
        if (requireSelectionChanged)
        {
            requireSelectionChanged = false;
            
            if (requireSelection &&
                    selectedIndex == NO_SELECTION &&
                    dataProvider &&
                    dataProvider.length > 0)
            {
                // Set the proposed selected index here to make sure
                // commitSelection() is called below.
                _proposedSelectedIndex = 0;
            }
        }
        
        if (_pendingSelectedItem !== undefined)
        {
            if (dataProvider)
                _proposedSelectedIndex = dataProvider.getItemIndex(_pendingSelectedItem);
            else
                _proposedSelectedIndex = NO_SELECTION;
            
            if (allowCustomSelectedItem && _proposedSelectedIndex == -1 && _pendingSelectedItem != null)
            {
                _proposedSelectedIndex = CUSTOM_SELECTED_ITEM;
                _selectedItem = _pendingSelectedItem;
            }
              
            _pendingSelectedItem = undefined;
        }
        
        if (_proposedSelectedIndex != NO_PROPOSED_SELECTION)
            changedSelection = commitSelection();
        
        // If the selectedIndex has been adjusted to account for items that
        // have been added or removed, or the selectedItem has changed because of a dp collection
        // event which didn't cause the selectedIndex to change, send out a "change" event so any 
        // bindings to selectedIndex/selectedItem are updated correctly.
        if (selectedIndexAdjusted)
        {
            selectedIndexAdjusted = false;
            if (!changedSelection)
            {
                dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
            }
        }
        
        if (caretIndexAdjusted)
        {
            caretIndexAdjusted = false;
            if (!changedSelection)
            {
                // Put the new caretIndex renderer into the
                // caret state and dispatch an "caretChange" 
                // event to update any bindings. Additionally, update 
                // the backing variable. 
                itemShowingCaret(selectedIndex, true); 
                _caretIndex = selectedIndex; 
                
                e = new IndexChangeEvent(IndexChangeEvent.CARET_CHANGE); 
                e.oldIndex = caretIndex; 
                e.newIndex = caretIndex;
                dispatchEvent(e);  
            }
        }
        
        if (labelFieldOrFunctionChanged)
        {
            // Cycle through all instantiated renderers to push the correct text 
            // in to the renderer by setting its label property
            if (dataGroup)
            {
                var itemIndex:int;
                
                // if virtual layout, only loop through the indices in view
                // otherwise, loop through all of the item renderers
                if (layout && layout.useVirtualLayout)
                {
                    for each (itemIndex in dataGroup.getItemIndicesInView())
                    {
                        updateRendererLabelProperty(itemIndex);
                    }
                }
                else
                {
                    var n:int = dataGroup.numElements;
                    for (itemIndex = 0; itemIndex < n; itemIndex++)
                    {
                        updateRendererLabelProperty(itemIndex);
                    }
                }
            }

            labelFieldOrFunctionChanged = false; 
        }
    }
    
    /**
     *  @private
     */
    private function updateRendererLabelProperty(itemIndex:int):void
    {
        // grab the renderer at that index and re-compute it's label property
        var renderer:IItemRenderer = dataGroup.getElementAt(itemIndex) as IItemRenderer; 
        if (renderer)
            renderer.label = itemToLabel(renderer.data); 
    }
    
    /**
     *  @private
     */
    override protected function partAdded(partName:String, instance:Object):void
    {
        super.partAdded(partName, instance);

        if (instance == dataGroup)
        {
            // Not your typical delegation, see 'set useVirtualLayout'
            if (_useVirtualLayout && dataGroup.layout && dataGroup.layout.virtualLayoutSupported)
                dataGroup.layout.useVirtualLayout = true;
            
            dataGroup.addEventListener(
                RendererExistenceEvent.RENDERER_ADD, dataGroup_rendererAddHandler);
            dataGroup.addEventListener(
                RendererExistenceEvent.RENDERER_REMOVE, dataGroup_rendererRemoveHandler);
        }
    }

    /**
     *  @private
     */
    override protected function partRemoved(partName:String, instance:Object):void
    {        
        super.partRemoved(partName, instance);
        
        if (instance == dataGroup)
        {
            dataGroup.removeEventListener(
                RendererExistenceEvent.RENDERER_ADD, dataGroup_rendererAddHandler);
            dataGroup.removeEventListener(
                RendererExistenceEvent.RENDERER_REMOVE, dataGroup_rendererRemoveHandler);
        }
    }

    /**
     *  @private
     */
    override public function updateRenderer(renderer:IVisualElement, itemIndex:int, data:Object):void
    {
        // We keep track of whether we are in updateRenderer().  This is 
        // so we know that any calls to itemSelected() and itemShowingCaret(), 
        // are called based on a user-action (either interaction or programattic) 
        // and not through item renderer recycling.
        inUpdateRenderer = true;
        
        // We need to deal with transitions appropriately.  If selection transitions 
        // are on for updateRenderer() but caret transitions are not, then we want to 
        // set the caret first (with transitions off) and then set the selection. 
        // We do it in this order for this case because we want the last change 
        // we make to cause a transition (if it's on).
        // Otherwise, we set selection first and then caret.
        if (allowSelectionTransitions && !allowCaretTransitions)
        {
            // no transitions for caret, so turn them off since this is just 
            // due to item renderer recycling
            if (renderer is ItemRenderer)
                ItemRenderer(renderer).playTransitions = false;
            
            itemShowingCaret(itemIndex, isItemIndexShowingCaret(itemIndex));
            
            // turn on transitions for selection
            if (renderer is ItemRenderer)
                ItemRenderer(renderer).playTransitions = true;
            
            itemSelected(itemIndex, isItemIndexSelected(itemIndex));
        }
        else
        {
            // if selection transitions are on, turn them on.  otherwise, turn them off, 
            // so we don't see them for item renderer recycling
            if (renderer is ItemRenderer)
                ItemRenderer(renderer).playTransitions = allowSelectionTransitions;
            
            itemSelected(itemIndex, isItemIndexSelected(itemIndex));
            
            // deal with transitions for caret appropriately
            if (renderer is ItemRenderer)
                ItemRenderer(renderer).playTransitions = allowCaretTransitions;
                
            itemShowingCaret(itemIndex, isItemIndexShowingCaret(itemIndex));
        }
        
        // Now turn the transitions back on by setting playTransitions
        // back to true 
        if (renderer is ItemRenderer)
            ItemRenderer(renderer).playTransitions = true; 
        
        // Now run through and initialize the renderer correctly.  We 
        // call super.updateRenderer() last because super.updateRenderer()
        // sets the data on the item renderer, and that should be done last.
        super.updateRenderer(renderer, itemIndex, data); 
        
        // let us know we're out of updateRenderer()
        inUpdateRenderer = false;
    }
    
    /**
     *  Given a data item, return the correct text a renderer
     *  should display while taking the <code>labelField</code> 
     *  and <code>labelFunction</code> properties into account. 
     *
     *  @param item A data item 
     *  
     *  @return String representing the text to display for the 
     *  data item in the  renderer. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function itemToLabel(item:Object):String
    {
        return LabelUtil.itemToLabel(item, labelField, labelFunction);
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
    *  This will search through a dataprovider checking the given field and for the given value and return the index for the match.
    *  It can start the find from a given startingIndex;
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function findRowIndex(field:String, value:String, startingIndex:int = 0, patternType:String = RegExPatterns.EXACT):int
    {
        var pattern:RegExp; 
        var currentObject:Object = null;
        var dataProviderTotal:int = 0;
        var loopingIndex:int = startingIndex;


        pattern = RegExPatterns.createRegExp(value, patternType);


        if (dataProvider && dataProvider.length > 0)
        {
            dataProviderTotal = dataProvider.length;

            if (startingIndex >= dataProviderTotal)
            {
                return -1;
            }


            for (loopingIndex; loopingIndex < dataProviderTotal; loopingIndex++)
            {
                currentObject = dataProvider.getItemAt(loopingIndex);

                if (currentObject.hasOwnProperty(field) == true && currentObject[field].search(pattern) != -1)
                {
                    return loopingIndex;
                }
            }

        }

        return -1;
    }


    /**
    *  This will search through a dataprovider checking the given field and for the given values and return an array of indices that matched.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function findRowIndices(field:String, values:Array, patternType:String = RegExPatterns.EXACT):Array
    {
        var currentObject:Object = null;
        var regexList:Array = [];
        var matchedIndices:Array = [];
        var dataProviderTotal:uint = 0;
        var valuesTotal:uint = 0;
        var loopingDataProviderIndex:uint = 0;
        var loopingValuesIndex:uint = 0;


        if (dataProvider != null && dataProvider.length > 0 && values != null && values.length > 0)
        {
            dataProviderTotal = dataProvider.length;
            valuesTotal = values.length;


            //Set the regex patterns in an array once.
            for (loopingValuesIndex = 0; loopingValuesIndex < valuesTotal; loopingValuesIndex++)
            {
                regexList.push(RegExPatterns.createRegExp(values[loopingValuesIndex], patternType));
            }


            //Loop through dataprovider
            for (loopingDataProviderIndex; loopingDataProviderIndex < dataProviderTotal; loopingDataProviderIndex++)
            {
                currentObject = dataProvider.getItemAt(loopingDataProviderIndex);

                if (currentObject.hasOwnProperty(field) == false)
                {
                    continue;
                }

                //Loop through regex patterns from the values array.
                for (loopingValuesIndex = 0; loopingValuesIndex < valuesTotal; loopingValuesIndex++)
                {
                    if (currentObject[field].search(regexList[loopingValuesIndex]) != -1)
                    {
                        matchedIndices.push(loopingDataProviderIndex);

                        break;
                    }
                }
            }

        }


        return matchedIndices;
    }


    /**
     *  Called when an item is selected or deselected. 
     *  Subclasses must override this method to display the selection.
     *
     *  @param index The item index that was selected.
     *
     *  @param selected <code>true</code> if the item is selected, 
     *  and <code>false</code> if it is deselected.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function itemSelected(index:int, selected:Boolean):void
    {
        // if this method is called from anywhere besides the updateRenderer(), 
        // then we want transitions for selection to play.  This way if it's called 
        // from the selectedIndex setter or through the keyDown handler or through 
        // commitProperties(), transitions will be enabled for it.
        if (!inUpdateRenderer)
            turnOnSelectionTransitionsForOneFrame();
            
        // Subclasses must override this method to display the selection.
    }
    
    /**
     *  Called when an item is in its caret state or not. 
     *  Subclasses must override this method to display the caret. 
     *
     *  @param index The item index that was put into caret state. 
     *
     *  @param showsCaret <code>true</code> if the item is in the caret state,  
     *  and <code>false</code> if it is not.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function itemShowingCaret(index:int, showsCaret:Boolean):void
    {
        // if this method is called from anywhere besides the updateRenderer(), 
        // then we want transitions for caret to play.  This way if it's called 
        // from the keyDown handler or through 
        // commitProperties(), transitions will be enabled for it.
        if (!inUpdateRenderer)
            turnOnCaretTransitionsForOneFrame();
        
        // Subclasses must override this method to display the caret.
    }
    
    /**
     *  Returns <code>true</code> if the item at the index is selected.
     * 
     *  @param index The index of the item whose selection status is being checked
     *
     *  @return <code>true</code> if the item at that index is selected, 
     *  and <code>false</code> otherwise.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function isItemIndexSelected(index:int):Boolean
    {        
        return index == selectedIndex;
    }
    
    /**
     *  Returns true if the item at the index is the caret item, which is
     *  essentially the item in focus. 
     * 
     *  @param index The index of the item whose caret status is being checked
     *
     *  @return true if the item at that index is the caret item, false otherwise.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    mx_internal function isItemIndexShowingCaret(index:int):Boolean
    {        
        return index == caretIndex;
    }


    /**
    *  This will search through a dataprovider checking the given field and will set the selectedIndex to a matching value.
    *  It can start the search from the startingIndex;
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    *
    */
    public function moveIndexFindRow(field:String, value:String, startingIndex:int = 0, patternType:String = RegExPatterns.EXACT):Boolean
    {
        var indexFound:int = -1;

        indexFound = findRowIndex(field, value, startingIndex, patternType);

        if (indexFound != -1)
        {
            selectedIndex = indexFound;

            return true;
        }

        return false;
    }


    /**
    *  Changes the selectedIndex to the first row of the dataProvider.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexFirstRow():void
    {
        if (dataProvider && dataProvider.length > 0)
        {
            selectedIndex = 0;
        }
    }


    /**
    *  Changes the selectedIndex to the last row of the dataProvider.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexLastRow():void
    {
        if (dataProvider && dataProvider.length > 0)
        {
            selectedIndex = dataProvider.length - 1;
        }
    }


    /**
    *  Changes the selectedIndex to the next row of the dataProvider.  If there isn't a current selectedIndex, it silently returns.
    *  If the selectedIndex is on the first row, it does not wrap around.  However the <code>isFirstRow</code> property returns true.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexNextRow():void
    {
        if (dataProvider && dataProvider.length > 0 && selectedIndex >= 0)
        {
            if (isLastRow == false)
            {
                selectedIndex += 1;
            }
        }
    }


    /**
    *  Changes the selectedIndex to the previous row of the dataProvider.  If there isn't a current selectedIndex, it silently returns.
    *  If the selectedIndex is on the last row, it does not wrap around.  However the <code>isLastRow</code> property returns true.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexPreviousRow():void
    {
        if (dataProvider && dataProvider.length > 0 && selectedIndex >= 0)
        {
            if (isFirstRow == false)
            {
                selectedIndex -= 1;
            }
        }
    }


    /**
     *  @private
     *  Set current caret index. This function takes the item that was
     *  previously the caret item and sets its caret property to false,
     *  then takes the current proposed caret item and sets its 
     *  caret property to true as well as updating the backing variable. 
     * 
     */
    mx_internal function setCurrentCaretIndex(value:Number):void
    {
        if (value == caretIndex)
            return;
        
        itemShowingCaret(caretIndex, false); 
        
        _caretIndex = value;
        
        if (caretIndex != CUSTOM_SELECTED_ITEM)
        {
            itemShowingCaret(_caretIndex, true);
            
            // Track the caretItem (often the same as the selectedItem), so that
            // if the dataProvider is refreshed, we can relocate the caretIndex.
            
            const validIndex:Boolean = dataProvider && (_caretIndex >= 0) && (_caretIndex < dataProvider.length);
            caretItem = (validIndex) ? dataProvider.getItemAt(_caretIndex) : undefined;
        }
    }
    
    /**
     *  @private
     *  The selection validation and commitment workhorse method. 
     *  Called to commit the pending selected index. This method dispatches
     *  the "changing" event, and if the event is not cancelled,
     *  commits the selection change and then dispatches the "change"
     *  event.
     * 
     *  Returns true if the selection was committed, or false if the selection
     *  was cancelled.
     */
    protected function commitSelection(dispatchChangedEvents:Boolean = true):Boolean
    {
        // Step 1: make sure the proposed selected index is in range.
        var maxIndex:int = dataProvider ? dataProvider.length - 1 : -1;
        var oldSelectedIndex:int = _selectedIndex;
        var oldCaretIndex:int = _caretIndex;
        var e:IndexChangeEvent;


        //Prevents an in item from being selected.  Stops the change before it sends out changing events.
        if (_preventSelection == true)
        {
            if (_selectedIndex != NO_SELECTION)
            {
                itemSelected(NO_SELECTION, false);
                _selectedIndex = NO_SELECTION;
            }

            //Cancel the selection change and return false.
            itemSelected(_proposedSelectedIndex, false);
            _proposedSelectedIndex = NO_PROPOSED_SELECTION;
            dispatchChangeAfterSelection = false;

            return false;
        }


        if (!allowCustomSelectedItem || _proposedSelectedIndex != CUSTOM_SELECTED_ITEM)
        {
            if (_proposedSelectedIndex < NO_SELECTION)
                _proposedSelectedIndex = NO_SELECTION;
            if (_proposedSelectedIndex > maxIndex)
                _proposedSelectedIndex = maxIndex;
            if (requireSelection && _proposedSelectedIndex == NO_SELECTION && 
                dataProvider && dataProvider.length > 0)
            {
                _proposedSelectedIndex = NO_PROPOSED_SELECTION;
                return false;
            }
        }
        
        // Caching value of proposed index prevents its being changed in the dispatch
        // of the changing event, if that results in a call into this function
        var tmpProposedIndex:int = _proposedSelectedIndex;

        // Step 2: dispatch the "changing" event. If preventDefault() is called
        // on this event, the selection change will be cancelled.        
        if (dispatchChangeAfterSelection)
        {
            e = new IndexChangeEvent(IndexChangeEvent.CHANGING, false, true);
            e.oldIndex = _selectedIndex;
            e.newIndex = _proposedSelectedIndex;
            if (!dispatchEvent(e))
            {
                // The event was cancelled. Cancel the selection change and return.
                itemSelected(_proposedSelectedIndex, false);
                _proposedSelectedIndex = NO_PROPOSED_SELECTION;
                dispatchChangeAfterSelection = false;
                return false;
            }
        }
        
        // Step 3: commit the selection change and caret change
        _selectedIndex = tmpProposedIndex;
        _proposedSelectedIndex = NO_PROPOSED_SELECTION;
        
        if (oldSelectedIndex != NO_SELECTION)
            itemSelected(oldSelectedIndex, false);
        if (_selectedIndex != NO_SELECTION && _selectedIndex != CUSTOM_SELECTED_ITEM)
            itemSelected(_selectedIndex, true);
        if (changeCaretOnSelection)
            setCurrentCaretIndex(_selectedIndex); 

        // Step 4: dispatch the "change" event and "caretChange" 
        // events based on the dispatchChangeEvents parameter. Overrides may  
        // chose to dispatch the change/caretChange events 
        // themselves, in which case we wouldn't want to dispatch the event 
        // here. 
        if (dispatchChangedEvents)
        {
            // Dispatch the change event
            if (dispatchChangeAfterSelection)
            {
                e = new IndexChangeEvent(IndexChangeEvent.CHANGE);
                e.oldIndex = oldSelectedIndex;
                e.newIndex = _selectedIndex;
                dispatchEvent(e);
                dispatchChangeAfterSelection = false;
            }

            dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
            
            //Dispatch the caretChange event 
            if (changeCaretOnSelection)
            {
                e = new IndexChangeEvent(IndexChangeEvent.CARET_CHANGE); 
                e.oldIndex = oldCaretIndex; 
                e.newIndex = caretIndex; 
                dispatchEvent(e);
            }
        }
        
        // default changeCaretOnSelection back to true
        changeCaretOnSelection = true;
        
        return true;
     }
    
    /**
     *  Adjusts the selected index to account for items being added to or 
     *  removed from this component. This method adjusts the selected index
     *  value and dispatches a <code>valueCommit</code> event. It does not 
     *  dispatch a <code>change</code> event because the change did not 
     *  occur as a direct result of user-interaction.  Moreover, 
     *  it does not dispatch a <code>changing</code> event 
     *  or allow the cancellation of the selection. 
     *  It also does not call the <code>itemSelected()</code> method, 
     *  since the same item is selected; 
     *  the only thing that has changed is the index of the item.
     * 
     *  <p>A <code>valueCommit</code> event is dispatched in the next call to 
     *  the <code>commitProperties()</code> method.</p>
     *
     *  <p>The <code>change</code> and <code>changing</code> events are 
     *  not sent when the <code>selectedIndex</code> is adjusted.</p>
     *
     *  @param newIndex The new index.
     *   
     *  @param add <code>true</code> if an item was added to the component, 
     *  and <code>false</code> if an item was removed.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function adjustSelection(newIndex:int, add:Boolean=false):void
    {
        if (_proposedSelectedIndex != NO_PROPOSED_SELECTION)
            _proposedSelectedIndex = newIndex;
        else
            _selectedIndex = newIndex;
        selectedIndexAdjusted = true;
        invalidateProperties();
    }
    
    /**
     *  Called when an item has been added to this component. Selection
     *  and caret related properties are adjusted accordingly. 
     * 
     *  @param index The index of the item being added. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function itemAdded(index:int):void
    {
        // if doing wholesale changes, we'll handle this more effeciently in commitProperties() with dataProviderChanged == true
        if (doingWholesaleChanges)
            return;
        
        if (selectedIndex == NO_SELECTION)
        {
            // If there's no selection, there's nothing to adjust unless 
            // we requireSelection and need to select what was added
            if (requireSelection)
                adjustSelection(index);
        }
        else if (index <= selectedIndex)
        {
            // If an item is added before the selected item, bump up our
            // selected index backing variable.
            adjustSelection(selectedIndex + 1);
        }
    }
    
    /**
     *  Called when an item has been removed from this component.
     *  Selection and caret related properties are adjusted 
     *  accordingly. 
     * 
     *  @param index The index of the item being removed. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function itemRemoved(index:int):void
    {
        if (selectedIndex == NO_SELECTION || doingWholesaleChanges)
            return;
        
        // If the selected item is being removed, clear the selection (or
        // reset to the first item if requireSelection is true)
        if (index == selectedIndex)
        {
            if (requireSelection && dataProvider && dataProvider.length > 0)
            {       
                if (index == 0)
                {
                    //We can't just set selectedIndex to 0 directly
                    //since the previous value was 0 and the new value is
                    //0, so the setter will return early.  
                    _proposedSelectedIndex = 0;
                    invalidateProperties();
                }
                else 
                    setSelectedIndex(0, false);
            }
            else
                adjustSelection(-1);
        }
        else if (index < selectedIndex)
        {
            // An item below the selected index has been removed, bump
            // the selected index backing variable.
            adjustSelection(selectedIndex - 1);
        }
    }
    
    /**
     *  @private
     *  Default response to dataProvider refresh events: clear the selection and caret.
     */
    mx_internal function dataProviderRefreshed():void
    {
        if (dataProvider && dataProvider.length > 0 && requireSelection == true)
        {
            setSelectedIndex(0, false);
        }
        else
        {
            selectedItem = undefined;
            setSelectedIndex(NO_SELECTION, false);
            // TODO (rfrishbe): probably don't need the setCurrentCaretIndex below
            setCurrentCaretIndex(NO_CARET);
        }
    }
    
    /**
     *  @private
     *  Turns on selection transitions for one frame.  We turn it on for 
     *  one frame to make sure that no matter how the property gets set 
     *  (synchronously in the event handler or asynchronously during validation)
     *  that we make sure selection transitions will play appropriately.
     */
    private function turnOnSelectionTransitionsForOneFrame():void
    {
        // if already on, no need to run this again
        // or if there's no systemManager, then we're not really initialized, so let's
        // just keep transitions off.
        if (allowSelectionTransitions || !systemManager)
            return;
        
        allowSelectionTransitions = true;
        
        // We want to wait one frame after validation has occured before turning off 
        // selection transitions again.  We tried using dataGroup's updateComplete event listener, 
        // but because some validateNows() occur (before all of the event handling code has finished), 
        // this was occuring too early.  We also tried just using callLater or ENTER_FRAME, but that 
        // occurs before the LayoutManager has run, so we add an ENTER_FRAME handler with a 
        // low priority to make sure it occurs after the LayoutManager pass.
        systemManager.addEventListener(Event.ENTER_FRAME, allowSelectionTransitions_enterFrameHandler, false, -100);
    }
    
    /**
     *  @private
     *  After waiting a frame, we want to turn off selection transitions
     */
    private function allowSelectionTransitions_enterFrameHandler(event:Event):void
    {
        event.target.removeEventListener(Event.ENTER_FRAME, allowSelectionTransitions_enterFrameHandler);
        
        allowSelectionTransitions = false;
    }
    
    /**
     *  @private
     *  Turns on caret transitions for one frame.  We turn it on for 
     *  one frame to make sure that no matter how the property gets set 
     *  (synchronously in the event handler or asynchronously during validation)
     *  that we make sure caret transitions will play appropriately.
     */
    private function turnOnCaretTransitionsForOneFrame():void
    {
        // if already on, no need to run this again
        // or if there's no systemManager, then we're not really initialized, so let's
        // just keep transitions off.
        if (allowCaretTransitions || !systemManager)
            return;
        
        allowCaretTransitions = true;
        
        // We want to wait one frame after validation has occured before turning off 
        // selection transitions again.  We tried using dataGroup's updateComplete event listener, 
        // but because some validateNows() occur (before all of the event handling code has finished), 
        // this was occuring too early.  We also tried just using callLater or ENTER_FRAME, but that 
        // occurs before the LayoutManager has run, so we add an ENTER_FRAME handler with a 
        // low priority to make sure it occurs after the LayoutManager pass.
        systemManager.addEventListener(Event.ENTER_FRAME, allowCaretTransitions_enterFrameHandler, false, -100);
    }
    
    /**
     *  @private
     *  After waiting a frame, we want to turn off caret transitions
     */
    private function allowCaretTransitions_enterFrameHandler(event:Event):void
    {
        event.target.removeEventListener(Event.ENTER_FRAME, allowCaretTransitions_enterFrameHandler);
        
        allowCaretTransitions = false;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  Called when an item has been added to this component.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    protected function dataGroup_rendererAddHandler(event:RendererExistenceEvent):void
    {
        var renderer:IVisualElement = event.renderer;
        
        if (!renderer)
            return;
        
        renderer.addEventListener(MouseEvent.ROLL_OVER, item_mouseEventHandler);
        renderer.addEventListener(MouseEvent.ROLL_OUT, item_mouseEventHandler);
    }
    
    /**
     *  @private
     *  Called when an item has been removed from this component.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    protected function dataGroup_rendererRemoveHandler(event:RendererExistenceEvent):void
    {
        var renderer:IVisualElement = event.renderer;
        
        if (!renderer)
            return;
        
        renderer.removeEventListener(MouseEvent.ROLL_OVER, item_mouseEventHandler);
        renderer.removeEventListener(MouseEvent.ROLL_OUT, item_mouseEventHandler);
    }

    /**
     *  @private
     *  Called when an item has been removed from this component.
     */
    private function item_mouseEventHandler(event:MouseEvent):void
    {
        var type:String = event.type;
        type = TYPE_MAP[type];
        if (hasEventListener(type))
        {
            var itemRenderer:IItemRenderer = event.currentTarget as IItemRenderer;
            
            var itemIndex:int = -1;
            if (itemRenderer)
                itemIndex = itemRenderer.itemIndex;
            else
                itemIndex = dataGroup.getElementIndex(event.currentTarget as IVisualElement);
            
            var listEvent:ListEvent = new ListEvent(type, false, false,
                                                    event.localX,
                                                    event.localY,
                                                    event.relatedObject,
                                                    event.ctrlKey,
                                                    event.altKey,
                                                    event.shiftKey,
                                                    event.buttonDown,
                                                    event.delta,
                                                    itemIndex,
                                                    dataProvider.getItemAt(itemIndex),
                                                    itemRenderer);
            dispatchEvent(listEvent);
        }
    }
    
    /**
     *  @private
     *  Called when contents within the dataProvider changes.  
     *
     *  @param event The collection change event
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function dataProvider_collectionChangeHandler(event:Event):void
    {
        if (event is CollectionEvent)
        {
            var ce:CollectionEvent = CollectionEvent(event);

            if (ce.kind == CollectionEventKind.ADD)
            {
                itemAdded(ce.location);
            }
            else if (ce.kind == CollectionEventKind.REMOVE)
            {
                itemRemoved(ce.location);
            }
            else if (ce.kind == CollectionEventKind.RESET)
            {
                // Data provider is being reset, clear out the selection which includes the
                // selectedItem so that any bindings on the selectedItem are triggered.
                selectedItem = undefined;
                if (dataProvider.length == 0)
                {
                    setSelectedIndex(NO_SELECTION, false);
                    // TODO (rfrishbe): probably don't need the setCurrentCaretIndex below
                    setCurrentCaretIndex(NO_CARET);
                }
                else
                {
                    dataProviderChanged = true; 
                    invalidateProperties(); 
                }
            }
            else if (ce.kind == CollectionEventKind.REFRESH)
            {
                dataProviderRefreshed();
            }
            else if (ce.kind == CollectionEventKind.REPLACE ||
                ce.kind == CollectionEventKind.MOVE)
            {
                //These cases are handled by the DataGroup skinpart  
            }
        }
            
    }
}

}
