////////////////////////////////////////////////////////////////////////////////
//
//  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 mx.controls.listClasses
{

import mx.collections.ArrayCollection;
import mx.collections.ICollectionView;
import mx.collections.IList;
import mx.collections.ListCollectionView;
import mx.collections.XMLListCollection;
import mx.core.EdgeMetrics;
import mx.core.IUIComponent;
import mx.core.ScrollControlBase;
import mx.core.ScrollPolicy;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.CollectionEvent;
import mx.events.DragEvent;
import mx.utils.UIDUtil;

import org.apache.royale.core.ContainerBaseStrandChildren;
import org.apache.royale.core.IBead;
import org.apache.royale.core.IBeadLayout;
import org.apache.royale.core.IBeadView;
import org.apache.royale.core.IChild;
import org.apache.royale.core.IContainer;
import org.apache.royale.core.IContainerBaseStrandChildrenHost;
import org.apache.royale.core.IDataProviderItemRendererMapper;
import org.apache.royale.core.IFactory;
import org.apache.royale.core.IItemRendererClassFactory;
import org.apache.royale.core.IItemRendererProvider;
import org.apache.royale.core.ILayoutChild;
import org.apache.royale.core.ILayoutHost;
import org.apache.royale.core.ILayoutParent;
import org.apache.royale.core.ILayoutView;
import org.apache.royale.core.IListPresentationModel;
import org.apache.royale.core.IParent;
import org.apache.royale.core.ISelectionModel;
import org.apache.royale.core.IStrandWithPresentationModel;
import org.apache.royale.core.ValuesManager;
import org.apache.royale.events.Event;
import org.apache.royale.events.ValueEvent;
import org.apache.royale.utils.loadBeadFromValuesManager;
import mx.controls.dataGridClasses.DataGridListData;
import mx.events.FlexEvent;

use namespace mx_internal;

	
/**
 *  Dispatched when the user clicks on an item in the control.
 *
 *  @eventType mx.events.ListEvent.ITEM_CLICK
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="itemClick", type="mx.events.ListEvent")]

/**
 *  Dispatched when the user double-clicks on an item in the control.
 *
 *  @eventType mx.events.ListEvent.ITEM_DOUBLE_CLICK
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="itemDoubleClick", type="mx.events.ListEvent")]
	
//--------------------------------------
//  Styles
//--------------------------------------


/**
 *  The colors to use for the backgrounds of the items in the list. 
 *  The value is an array of one or more colors. 
 *  The backgrounds of the list items alternate among the colors in the array. 
 *
 *  <p>For DataGrid controls, all items in a row have the same background color, 
 *  and each row's background color is determined from the array of colors.</p>
 *
 *  <p>For the TileList control, which uses a single list to populate a 
 *  two-dimensional display, the style can result in a checkerboard appearance,
 *  stripes, or other patterns based on the number of columns and rows and
 *  the number of colors specified.  TileList cycles through the colors, placing
 *  the individual item background colors according to the 
 *  layout direction. If you have an even number of colors and an even number of
 *  columns for a TileList layed out horizontally, you will get striping.  If
 *  the number of columns is an odd number, you will get a checkerboard pattern.
 *  </p>
 *
 *  @default undefined
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Royale 0.0
 */
[Style(name="alternatingItemColors", type="Array", arrayType="uint", format="Color", inherit="yes")]

/**
 *  A flag that controls whether items are highlighted as the mouse rolls 
 *  over them.
 *  If <code>true</code>, rows are highlighted as the mouse rolls over them.
 *  If <code>false</code>, rows are highlighted only when selected.
 *
 *  @default true
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Royale 0.9.8
 */
[Style(name="useRollOver", type="Boolean", inherit="no")]

    /**
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion Royale 0.0
     *  @royalesuppresspublicvarwarning
	*/
	public class ListBase extends ScrollControlBase 
        implements IContainerBaseStrandChildrenHost, IContainer, ILayoutParent, 
                    ILayoutView, IItemRendererProvider, IStrandWithPresentationModel
	{  //extends UIComponent
	
	
	
	public function get value():Object
	{
	   return null;
	}
        //----------------------------------
        //  dragEnabled
        //----------------------------------
        
        /**
         *  @private
         *  Storage for the dragEnabled property.
         */
        private var _dragEnabled:Boolean = false;
        
        /**
         *  A flag that indicates whether you can drag items out of
         *  this control and drop them on other controls.
         *  If <code>true</code>, dragging is enabled for the control.
         *  If the <code>dropEnabled</code> property is also <code>true</code>,
         *  you can drag items and drop them within this control
         *  to reorder the items.
         *
         *  @default false
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public function get dragEnabled():Boolean
        {
            return _dragEnabled;
        }
        
        /**
         *  @private
         */
        public function set dragEnabled(value:Boolean):void
        {
            _dragEnabled = value;
        }
        
        //----------------------------------
        //  dragMoveEnabled
        //----------------------------------
        
        /**
         *  @private
         *  Storage for the dragMoveEnabled property.
         */
        private var _dragMoveEnabled:Boolean = false;
        
        [Inspectable(defaultValue="false")]
        
        /**
         *  A flag that indicates whether items can be moved instead
         *  of just copied from the control as part of a drag-and-drop
         *  operation.
         *  If <code>true</code>, and the <code>dragEnabled</code> property
         *  is <code>true</code>, items can be moved.
         *  Often the data provider cannot or should not have items removed
         *  from it, so a MOVE operation should not be allowed during
         *  drag-and-drop.
         *
         *  @default false
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public function get dragMoveEnabled():Boolean
        {
            return _dragMoveEnabled;
        }
        
        /**
         *  @private
         */
        public function set dragMoveEnabled(value:Boolean):void
        {
            _dragMoveEnabled = value;
        }
        
	
	//----------------------------------
        //  menuSelectionMode 
        //----------------------------------
        
        /**
         *  @public
         *  Storage for the menuSelectionMode property.
         */
        public var _menuSelectionMode:Boolean = false;
        
        /**
         *  A flag that indicates whether you can drag items out of
         *  this control and drop them on other controls.
         *  If <code>true</code>, dragging is enabled for the control.
         *  If the <code>menuSelectionMode</code> property is also <code>true</code>,
         *  you can drag items and drop them within this control
         *  to reorder the items.
         *
         *  @default false
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public function get menuSelectionMode():Boolean
        {
            return _menuSelectionMode;
        }
        
        /**
         *  @private
         */
        public function set menuSelectionMode(value:Boolean):void
        {
            _menuSelectionMode = value;
        }
	
        //----------------------------------
        //  dataProvider
        //----------------------------------
        
        [Bindable("collectionChange")]
        [Inspectable(category="Data", defaultValue="undefined")]
        
        /**
         *  Set of data to be viewed.
         *  This property lets you use most types of objects as data providers.
         *  If you set the <code>dataProvider</code> property to an Array, 
         *  it will be converted to an ArrayCollection. If you set the property to
         *  an XML object, it will be converted into an XMLListCollection with
         *  only one item. If you set the property to an XMLList, it will be 
         *  converted to an XMLListCollection.  
         *  If you set the property to an object that implements the 
         *  IList or ICollectionView interface, the object will be used directly.
         *
         *  <p>As a consequence of the conversions, when you get the 
         *  <code>dataProvider</code> property, it will always be
         *  an ICollectionView, and therefore not necessarily be the type of object
         *  you used to  you set the property.
         *  This behavior is important to understand if you want to modify the data 
         *  in the data provider: changes to the original data may not be detected, 
         *  but changes to the ICollectionView object that you get back from the 
         *  <code>dataProvider</code> property will be detected.</p>
         * 
         *  @default null
         *  @see mx.collections.ICollectionView
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         *  @royaleignorecoercion org.apache.royale.core.ISelectionModel
         */
        public function get dataProvider():Object
        {
            return (model as ISelectionModel).dataProvider;
        }
        /**
         *  @royaleignorecoercion org.apache.royale.core.ISelectionModel
         */
        public function set dataProvider(value:Object):void
        {
            if (value is Array)
            {
                value = new ArrayCollection(value as Array);
            }
            else if (value is ICollectionView)
            {
                value = ICollectionView(value);
            }
            else if (value is IList)
            {
                value = new ListCollectionView(IList(value));
            }
            else if (value is XMLList)
            {
                value = new XMLListCollection(value as XMLList);
            }
            else if (value is XML)
            {
                var xl:XMLList = new XMLList();
                xl += value;
                value = new XMLListCollection(xl);
            }
            else
            {
                // convert it to an array containing this one item
                var tmp:Array = [];
                if (value != null)
                    tmp.push(value);
                value = new ArrayCollection(tmp);
            }
            (model as ISelectionModel).dataProvider = value;
        }
        
        
        //----------------------------------
        //  dropEnabled
        //----------------------------------
        
        /**
         *  @private
         *  Storage for the <code>dropEnabled</code> property.
         */
        private var _dropEnabled:Boolean = false;
        
        [Inspectable(defaultValue="false")]
        
        /**
         *  A flag that indicates whether dragged items can be dropped onto the 
         *  control.
         *
         *  <p>If you set this property to <code>true</code>,
         *  the control accepts all data formats, and assumes that
         *  the dragged data matches the format of the data in the data provider.
         *  If you want to explicitly check the data format of the data
         *  being dragged, you must handle one or more of the drag events,
         *  such as <code>dragOver</code>, and call the DragEvent's
         *  <code>preventDefault()</code> method to customize
         *  the way the list class accepts dropped data.</p>
         *
         *  <p>When you set <code>dropEnabled</code> to <code>true</code>, 
         *  Flex automatically calls the <code>showDropFeedback()</code> 
         *  and <code>hideDropFeedback()</code> methods to display the drop indicator.</p>
         *
         *  @default false
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public function get dropEnabled():Boolean
        {
            return _dropEnabled;
        }
        
        /**
         *  @private
         */
        public function set dropEnabled(value:Boolean):void
        {
            _dropEnabled = value;
        }
        
        //----------------------------------
        //  labelField
        //----------------------------------
                
        [Bindable("labelFieldChanged")]
        [Inspectable(category="Data", defaultValue="label")]
        
        /**
         *  The name of the field in the data provider items to display as the label. 
         *  By default the list looks for a property named <code>label</code> 
         *  on each item and displays it.
         *  However, if the data objects do not contain a <code>label</code> 
         *  property, you can set the <code>labelField</code> property to
         *  use a different property in the data object. An example would be 
         *  "FullName" when viewing a set of people names fetched from a database.
         *
         *  @default "label"
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         *  @royaleignorecoercion org.apache.royale.core.ISelectionModel
         */
        public function get labelField():String
        {
            return (model as ISelectionModel).labelField;
        }
        
        /**
         *  @private
         *  @royaleignorecoercion org.apache.royale.core.ISelectionModel
         */
        public function set labelField(value:String):void
        {
            (model as ISelectionModel).labelField = value;
        }
        
        //----------------------------------
        //  labelFunction
        //----------------------------------
        
        private var _labelFunction:Function;
        
        /**
         *  The name of the field in the data provider items to display as the label. 
         *  By default the list looks for a property named <code>label</code> 
         *  on each item and displays it.
         *  However, if the data objects do not contain a <code>label</code> 
         *  property, you can set the <code>labelField</code> property to
         *  use a different property in the data object. An example would be 
         *  "FullName" when viewing a set of people names fetched from a database.
         *
         *  @default "label"
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         *  @royaleignorecoercion org.apache.royale.core.ISelectionModel
         */
        public function get labelFunction():Function
        {
            return _labelFunction;
        }
        
        /**
         *  @private
         *  @royaleignorecoercion org.apache.royale.core.ISelectionModel
         */
        public function set labelFunction(value:Function):void
        {
            _labelFunction = value;
        }

    //----------------------------------
    //  selectedIndex
    //----------------------------------

    [Bindable("change")]
    [Bindable("valueCommit")]
    [Inspectable(category="General", defaultValue="-1")]

    /**
     *  The index in the data provider of the selected item.
     * 
     *  <p>The default value is -1 (no selected item).</p>
     *
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     *  @royaleignorecoercion org.apache.royale.core.ISelectionModel
     */
    public function get selectedIndex():int
    {
        return (model as ISelectionModel).selectedIndex;
    }

    /**
     *  @private
     *  @royaleignorecoercion org.apache.royale.core.ISelectionModel
     */
    public function set selectedIndex(value:int):void
    {
       // if (!collection || collection.length == 0)
       // {
        (model as ISelectionModel).selectedIndex = value;
         //   bSelectionChanged = true;
         //   bSelectedIndexChanged = true;
          //  invalidateDisplayList();
            return;
       // }
        //commitSelectedIndex(value);
    }
	
    //----------------------------------
    //  selectedIndices
    //----------------------------------
    
    [Bindable("change")]
    [Bindable("valueCommit")]
    [Inspectable(category="General")]
    
    /**
     *  An array of indices in the data provider of the selected items. The
     *  items are in the reverse order that the user selected the items.
     *  @default [ ]
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get selectedIndices():Array
    {
        // TODO
        trace("selectedIndices not implemented");
        return null;
    }
    
    /**
     *  @private
     */
    public function set selectedIndices(indices:Array):void
    {
        // TODO
        trace("selectedIndices not implemented");
    }
    
    //----------------------------------
    //  selectedItem
    //----------------------------------
    
    [Bindable("change")]
    [Bindable("valueCommit")]
    
    /**
     *  The selected item in the data provider.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get selectedItem():Object
    {
        return (model as ISelectionModel).selectedItem;
    }
    
    /**
     *  @private
     */
    public function set selectedItem(item:Object):void
    {
        (model as ISelectionModel).selectedItem = item;
    }
    
    //----------------------------------
    //  selectedItems
    //----------------------------------
    
    [Bindable("change")]
    [Bindable("valueCommit")]
    
    /**
     *  An array of references to the selected items in the data provider. The
     *  items are in the reverse order that the user selected the items.
     *  @default [ ]
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get selectedItems():Array
    {
        // TODO
        trace("selectedItems not implemented");
        return null;
    }
    
    /**
     *  @private
     */
    public function set selectedItems(items:Array):void
    {
        // TODO
        trace("selectedItems not implemented");
    }
    
	//----------------------------------
    //  variableRowHeight
    //----------------------------------

    /**
     *  @private
     *  Storage for the variableRowHeight property.
     */
    private var _variableRowHeight:Boolean = false;

    [Inspectable(category="General")]

    /**
     *  A flag that indicates whether the individual rows can have different
     *  height. This property is ignored by TileList and HorizontalList.
     *  If <code>true</code>, individual rows can have different height values.
     * 
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get variableRowHeight():Boolean
    {
        return _variableRowHeight;
    }

    /**
     *  @private
     */
    public function set variableRowHeight(value:Boolean):void
    {
        _variableRowHeight = value;
       // itemsSizeChanged = true;

       // invalidateDisplayList();

       // dispatchEvent(new Event("variableRowHeightChanged"));
    }
	//----------------------------------
    //  iconFunction
    //----------------------------------

    /**
     *  @private
     *  Storage for iconFunction property.
     */
    private var _iconFunction:Function;

    [Bindable("iconFunctionChanged")]
    [Inspectable(category="Data")]

    /**
     *  A user-supplied function to run on each item to determine its icon.  
     *  By default the list does not try to display icons with the text 
     *  in the rows.  However, by specifying an icon function, you can specify 
     *  a Class for a graphic that will be created and displayed as an icon 
     *  in the row.  This property is ignored by DataGrid.
     *
     *  <p>The iconFunction takes a single argument which is the item
     *  in the data provider and returns a Class, as the following example shows:</p>
     * 
     *  <pre>iconFunction(item:Object):Class</pre>
     * 
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Royale 0.9.8
     */
    public function get iconFunction():Function
    {
        return _iconFunction;
    }

    /**
     *  @private
     */
    public function set iconFunction(value:Function):void
    {
        _iconFunction = value;

        itemsSizeChanged = true;
        invalidateDisplayList();

        dispatchEvent(new Event("iconFunctionChanged"));
    }
    //----------------------------------
    //  allowMultipleSelection
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the allowMultipleSelection property.
     */
    private var _allowMultipleSelection:Boolean = false;
    
    [Inspectable(category="General", enumeration="false,true", defaultValue="false")]
    
    /**
     *  A flag that indicates whether you can allow more than one item to be
     *  selected at the same time.
     *  If <code>true</code>, users can select multiple items.
     *  There is no option to disallow discontiguous selection.
     *  Standard complex selection options are always in effect 
     *  (Shift-click, Ctrl-click).
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get allowMultipleSelection():Boolean
    {
        return _allowMultipleSelection;
    }
    
    /**
     *  @private
     */
    public function set allowMultipleSelection(value:Boolean):void
    {
        _allowMultipleSelection = value;
    }
//----------------------------------
    //  showDataTips
    //----------------------------------

    /**
     *  @private
     *  Storage for the showDataTips property.
     */
    private var _showDataTips:Boolean = false;

    [Bindable("showDataTipsChanged")]
    [Inspectable(category="Data", defaultValue="false")]

    /**
     *  A flag that indicates whether dataTips are displayed for text in the rows.
     *  If <code>true</code>, dataTips are displayed. DataTips
     *  are tooltips designed to show the text that is too long for the row.
     *  If you set a dataTipFunction, dataTips are shown regardless of whether the
     *  text is too long for the row.
     * 
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get showDataTips():Boolean
    {
        return _showDataTips;
    }

    /**
     *  @private
     */
    public function set showDataTips(value:Boolean):void
    {
        _showDataTips = value;

       // itemsSizeChanged = true;
        invalidateDisplayList();

        dispatchEvent(new Event("showDataTipsChanged"));
    }
	 //----------------------------------
    //  rowCount
    //----------------------------------

    /**
     *  @private
     *  Storage for the rowCount property.
     */
    private var _rowCount:int = -1;

    /**
     *  @private
     */
    private var rowCountChanged:Boolean = true;

    /**
     *  Number of rows to be displayed.
     *  If the height of the component has been explicitly set,
     *  this property might not have any effect.
     *
     *  <p>For a DataGrid control, the <code>rowCount</code> property does   
     *  not include the header row. </p>
     * 
     *  @default 4
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get rowCount():int
    {
        return _rowCount;
    }

    /**
     *  @private
     */
    public function set rowCount(value:int):void
    {
        explicitRowCount = value;

        if (_rowCount != value)
        {

            setRowCount(value);
            rowCountChanged = true;
            invalidateProperties();

            invalidateSize();
           // itemsSizeChanged = true;
            invalidateDisplayList();

            dispatchEvent(new Event("rowCountChanged"));
        }
    }
	/**
     *  Sets the <code>rowCount</code> property without causing
     *  invalidation or setting the <code>explicitRowCount</code>
     *  property, which permanently locks in the number of rows.
     *
     *  @param v The row count.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function setRowCount(v:int):void
    {
        //trace("setRowCount " + v);
        _rowCount = v;
    }
	
        /**
         *  Constructor.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion Royale 0.0
         */
		public function ListBase()
		{
			super();            
			rowHeight = 22; //match Flex?
		}
        
        private var _DCinitialized:Boolean = true;
        
        /**
         * @private
         */
        override public function addedToParent():void
        {
            if (!_DCinitialized)
            {
                ValuesManager.valuesImpl.init(this);
                _DCinitialized = true;
            }
            
            super.addedToParent();

            // Load the layout bead if it hasn't already been loaded.
            loadBeadFromValuesManager(IBeadLayout, "iBeadLayout", this);

            // Even though super.addedToParent dispatched "beadsAdded", DataContainer still needs its data mapper
            // and item factory beads. These beads are added after super.addedToParent is called in case substitutions
            // were made; these are just defaults extracted from CSS.
            loadBeadFromValuesManager(IDataProviderItemRendererMapper, "iDataProviderItemRendererMapper", this);
            loadBeadFromValuesManager(IItemRendererClassFactory, "iItemRendererClassFactory", this);
            
            dispatchEvent(new Event("initComplete"));
        }
        
        /*
        * IItemRendererProvider
        */
        
        private var _itemRenderer:IFactory;
        
        /**
         *  The class or factory used to display each item.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion Royale 0.0
         */
        public function get itemRenderer():IFactory
        {
            return _itemRenderer;
        }
        public function set itemRenderer(value:IFactory):void
        {
            _itemRenderer = value;
        }
        
        private var _strandChildren:ContainerBaseStrandChildren;
        
        /**
         * @private
         */
        public function get strandChildren():IParent
        {
            if (_strandChildren == null) {
                _strandChildren = new ContainerBaseStrandChildren(this);
            }
            return _strandChildren;
        }
        
    /**
     *  Refresh all rows on next update.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Royale 0.9.4
     */
     public function invalidateList():void
    {
	// not implemented
       // itemsSizeChanged = true;
       // invalidateDisplayList();
    } 

        public function scrollToIndex(index:int):Boolean
        {

            trace("ListBase:scrollToIndex not implemented");
			return false;
        }
        
        /**
         *  @private
         */
        public function childrenAdded():void
        {
            dispatchEvent(new ValueEvent("childrenAdded"));
        }
        
        /**
         * Returns the ILayoutHost which is its view. From ILayoutParent.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion Royale 0.8
         *  @royaleignorecoercion org.apache.royale.core.ILayoutHost
         */
        public function getLayoutHost():ILayoutHost
        {
            return view as ILayoutHost;
        }
        
        /**
         * @private
         */
        private var _presentationModel:IListPresentationModel;
        
        /**
         *  The DataGrid's presentation model
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion Royale 0.9
         *  @royaleignorecoercion org.apache.royale.core.IListPresentationModel
         *  @royaleignorecoercion org.apache.royale.core.IBead
         */
        public function get presentationModel():IBead
        {
            if (_presentationModel == null) {
                var bead:IBead = getBeadByType(IListPresentationModel);
                if (bead)
                    _presentationModel = bead as IListPresentationModel;
                else
                {
                    var c:Class = ValuesManager.valuesImpl.getValue(this, "iListPresentationModel");
                    if (c) {
                        _presentationModel = new c() as IListPresentationModel;
                        addBead(_presentationModel as IBead);
                    }
                }
            }
            
            return _presentationModel;
        }
        
        /*
        * The following functions are for the SWF-side only and re-direct element functions
        * to the content area, enabling scrolling and clipping which are provided automatically
        * in the JS-side. GroupBase handles event dispatching if necessary.
        */
        
        /**
         * @private
         */
        COMPILE::SWF
        override public function addElement(c:IChild, dispatchEvent:Boolean = true):void
        {
            var contentView:IParent = getLayoutHost().contentView as IParent;
            if (c == contentView)
            {
                super.addElement(c);
                return;
            }
            if (contentView == this)
                return super.addElement(c, dispatchEvent);
            contentView.addElement(c, dispatchEvent);
            if (dispatchEvent)
                this.dispatchEvent(new ValueEvent("childrenAdded", c));
        }
        
        /**
         * @private
         */
        COMPILE::SWF
        override public function addElementAt(c:IChild, index:int, dispatchEvent:Boolean = true):void
        {
            var contentView:IParent = getLayoutHost().contentView as IParent;
            if (contentView == this)
                return super.addElementAt(c, index, dispatchEvent);
            contentView.addElementAt(c, index, dispatchEvent);
            if (dispatchEvent)
                this.dispatchEvent(new ValueEvent("childrenAdded", c));
        }
        
        /**
         * @private
         */
        COMPILE::SWF
        override public function getElementIndex(c:IChild):int
        {
            var layoutHost:ILayoutHost = view as ILayoutHost;
            var contentView:IParent = layoutHost.contentView as IParent;
            if (contentView == this)
                return super.getElementIndex(c);
            return contentView.getElementIndex(c);
        }
        
        /**
         * @private
         */
        COMPILE::SWF
        override public function removeElement(c:IChild, dispatchEvent:Boolean = true):void
        {
            var layoutHost:ILayoutHost = view as ILayoutHost;
            var contentView:IParent = layoutHost.contentView as IParent;
            contentView.removeElement(c, dispatchEvent);
            //TODO This should possibly be ultimately refactored to be more PAYG
            if(dispatchEvent)
                this.dispatchEvent(new ValueEvent("childrenRemoved", c));
        }
        
      /**
       *  Returns the item renderer for a given item in the data provider,
       *  if there is one.  Since item renderers only exist for items
       *  that are within the set of viewable rows, this method
       *  returns <code>null</code> if the item is not visible.
       *  For a data grid, this returns the first column's renderer.
       *
       *  @param item The data provider item.
       *
       *  @return The item renderer or <code>null</code> if the item is not 
       *  currently displayed.
       *  
       *  @langversion 3.0
       *  @playerversion Flash 9
       *  @playerversion AIR 1.1
       *  @productversion Royale 0.9.4
       */
      public function itemToItemRenderer(item:Object):IListItemRenderer
      {
	      // not implemented
          //return visibleData[itemToUID(item)];
	      return null;
      }
            
       /**
        *  Hides the drop indicator under the mouse pointer that indicates that a
        *  drag and drop operation is allowed.
        *
        *  @param event A DragEvent object that contains information about the
        *  mouse location.
        *  
        *  @langversion 3.0
        *  @playerversion Flash 9
        *  @playerversion AIR 1.1
        *  @productversion Flex 3
        */
       public function hideDropFeedback(event:DragEvent):void
       {
           //To Do
           trace("hideDropFeedback is not implemented");
       }

      /**
       *  Determines if an item is being displayed by a renderer.
       *
       *  @param item A data provider item.
       *  @return <code>true</code> if the item is being displayed.
       *  
       *  @langversion 3.0
       *  @playerversion Flash 9
       *  @playerversion AIR 1.1
       *  @productversion Flex 3
       */
        public function isItemVisible(item:Object):Boolean
        {
            return itemToItemRenderer(item) != null;
        }

        /**
         * @private
         */
        COMPILE::SWF
        override public function get numElements():int
        {
            // the view getter below will instantiate the view which can happen
            // earlier than we would like (when setting mxmlDocument) so we
            // see if the view bead exists on the strand.  If not, nobody
            // has added any children so numElements must be 0
            if (!getBeadByType(IBeadView))
                return 0;
            var layoutHost:ILayoutHost = view as ILayoutHost;
            var contentView:IParent = layoutHost.contentView as IParent;
            if (contentView == this)
                return super.numElements;
            return contentView.numElements;
        }
        
        /**
         * @private
         */
        COMPILE::SWF
        override public function getElementAt(index:int):IChild
        {
            var layoutHost:ILayoutHost = view as ILayoutHost;
            var contentView:IParent = layoutHost.contentView as IParent;
            if (contentView == this)
                    return super.getElementAt(index);
            return contentView.getElementAt(index);
        }
        
        /**
         * @private
         */
        [SWFOverride(returns="flash.display.DisplayObject")]
        COMPILE::SWF
        override public function getChildAt(index:int):IUIComponent
        {
            return getElementAt(index) as IUIComponent;
        }
        
        /*
        * IStrandPrivate
        *
        * These "internal" function provide a backdoor way for proxy classes to
        * operate directly at strand level. While these function are available on
        * both SWF and JS platforms, they really only have meaning on the SWF-side. 
        * Other subclasses may provide use on the JS-side.
        *
        * @see org.apache.royale.core.IContainer#strandChildren
        */
        
        /**
         * @private
         * @suppress {undefinedNames}
         * Support strandChildren.
         */
        public function get $numElements():int
        {
            return super.numElements;
        }
        
        /**
         * @private
         * @suppress {undefinedNames}
         * Support strandChildren.
         */
        public function $addElement(c:IChild, dispatchEvent:Boolean = true):void
        {
            super.addElement(c, dispatchEvent);
        }
        
        /**
         * @private
         * @suppress {undefinedNames}
         * Support strandChildren.
         */
        public function $addElementAt(c:IChild, index:int, dispatchEvent:Boolean = true):void
        {
            super.addElementAt(c, index, dispatchEvent);
        }
        
        /**
         * @private
         * @suppress {undefinedNames}
         * Support strandChildren.
         */
        public function $removeElement(c:IChild, dispatchEvent:Boolean = true):void
        {
            super.removeElement(c, dispatchEvent);
        }
        
        /**
         * @private
         * @suppress {undefinedNames}
         * Support strandChildren.
         */
        public function $getElementIndex(c:IChild):int
        {
            return super.getElementIndex(c);
        }
        
        /**
         * @private
         * @suppress {undefinedNames}
         * Support strandChildren.
         */
        public function $getElementAt(index:int):IChild
        {
            return super.getElementAt(index);
        }
        
        //----------------------------------
        //  explicitColumnCount
        //----------------------------------
        
        /**
         *  The column count requested by explicitly setting the
         *  <code>columnCount</code> property.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        protected var explicitColumnCount:int = -1;
        
        //----------------------------------
        //  explicitColumnWidth
        //----------------------------------
        
        /**
         *  The column width requested by explicitly setting the 
         *  <code>columnWidth</code>.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        protected var explicitColumnWidth:Number;
        
        //----------------------------------
        //  explicitRowHeight
        //----------------------------------
        
        /**
         *  The row height requested by explicitly setting
         *  <code>rowHeight</code>.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        protected var explicitRowHeight:Number;
        
        //----------------------------------
        //  explicitRowCount
        //----------------------------------
        
        /**
         *  The row count requested by explicitly setting
         *  <code>rowCount</code>.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        protected var explicitRowCount:int = -1;
        
        //----------------------------------
        //  defaultColumnCount
        //----------------------------------
        
        /**
         *  The default number of columns to display.  This value
         *  is used if the calculation for the number of
         *  columns results in a value less than 1 when
         *  trying to calculate the columnCount based on size or
         *  content.
         *
         *  @default 4
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        protected var defaultColumnCount:int = 4;
        
        //----------------------------------
        //  defaultRowCount
        //----------------------------------
        
        /**
         *  The default number of rows to display.  This value
         *  is used  if the calculation for the number of
         *  columns results in a value less than 1 when
         *  trying to calculate the rowCount based on size or
         *  content.
         *
         *  @default 4
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        protected var defaultRowCount:int = 4;
        
        //----------------------------------
        //  rowHeight
        //----------------------------------
        
        /**
         *  @private
         *  Storage for the rowHeight property.
         */
        private var _rowHeight:Number;
        
        /**
         *  @private
         */
        private var rowHeightChanged:Boolean = false;
        
        [Inspectable(category="General")]
        
        /**
         *  The height of the rows in pixels.
         *  Unless the <code>variableRowHeight</code> property is
         *  <code>true</code>, all rows are the same height.  
         *  If not specified, the row height is based on
         *  the font size and other properties of the renderer.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public function get rowHeight():Number
        {
            return _rowHeight;
        }
        
        /**
         *  @private
         *  @royaleignorecoercion org.apache.royale.core.IListPresentationModel
         */
        public function set rowHeight(value:Number):void
        {
            explicitRowHeight = value;
            
            if (_rowHeight != value)
            {
                _rowHeight = value;
                
                (presentationModel as IListPresentationModel).rowHeight = value;
                /*
                invalidateSize();
                itemsSizeChanged = true;
                invalidateDisplayList();
                
                dispatchEvent(new Event("rowHeightChanged"));
                */
            }
        }
        
        //----------------------------------
        //  columnWidth
        //----------------------------------
        
        /**
         *  @private
         *  Storage for the columnWidth property.
         */
        private var _columnWidth:Number;
        
        /**
         *  @private
         */
        private var columnWidthChanged:Boolean = false;
        
        /**
         *  The width of the control's columns.
         *  This property is used by TileList and HorizontalList controls;
         *  It has no effect on DataGrid controls, where you set the individual
         *  DataGridColumn widths.
         *  
         * @default 50
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public function get columnWidth():Number
        {
            return _columnWidth;
        }
        
        /**
         *  @private
         */
        public function set columnWidth(value:Number):void
        {
            explicitColumnWidth = value;
            
            if (_columnWidth != value)
            {
                _columnWidth = value;
                
                /*
                invalidateSize();
                itemsSizeChanged = true;
                invalidateDisplayList();
                
                dispatchEvent(new Event("columnWidthChanged"));*/
            }
        }
        
        /**
         *  @royaleignorecoercion org.apache.royale.core.ILayoutChild
         */
        override protected function measure():void
        {
            super.measure();
            
            var cc:int = explicitColumnCount < 1 ?
                defaultColumnCount :
                explicitColumnCount;
            
            var rc:int = explicitRowCount < 1 ?
                defaultRowCount :
                explicitRowCount;
            
            if (!isNaN(explicitRowHeight))
            {
                measuredHeight = explicitRowHeight * rc // + o.top + o.bottom;
                //measuredMinHeight = explicitRowHeight * Math.min(rc, 2) +
                //    o.top + o.bottom;
            }
            else
            {
                if (isNaN(rowHeight) && numChildren > 0)
                {
                    rowHeight = (getElementAt(0) as ILayoutChild).height;
                }
                measuredHeight = rowHeight * rc // + o.top + o.bottom;
                //measuredMinHeight = rowHeight * Math.min(rc, 2) +
                //    o.top + o.bottom;
            }
            
            if (!isNaN(explicitColumnWidth))
            {
                measuredWidth = explicitColumnWidth * cc // + o.left + o.right;
                //measuredMinWidth = explicitColumnWidth * Math.min(cc, 1) +
                //    o.left + o.right;
            }
            else
            {
                if (isNaN(columnWidth) && numChildren > 0)
                {
                    columnWidth = (getElementAt(0) as ILayoutChild).width;
                }
                measuredWidth = columnWidth * cc // + o.left + o.right;
                //measuredMinWidth = columnWidth * Math.min(cc, 1) +
                //    o.left + o.right;
            }
        }
        
        /**
         *  Determines the UID for a data provider item.  All items
         *  in a data provider must either have a unique ID (UID)
         *  or one will be generated and associated with it.  This
         *  means that you cannot have an object or scalar value
         *  appear twice in a data provider. 
         *
         *  <p>For example, the following
         *  data provider is not supported because the value "foo"
         *  appears twice and the UID for a string is the string itself:</p>
         *
         *  <pre>var sampleDP:Array = ["foo", "bar", "foo"]</pre>
         *
         *  <p>Simple dynamic objects can appear twice if they are two
         *  separate instances. The following is supported because
         *  each of the instances will be given a different UID because
         *  they are different objects:</p>
         *
         *  <pre>var sampleDP:Array = [{label: "foo"}, {label: "foo"}]</pre>
         *
         *  <p>Note that the following is not supported because the same instance
         *  appears twice.</p>
         *
         *  <pre>
         *  var foo:Object = {label: "foo"};
         *  sampleDP:Array = [foo, foo];</pre>
         *
         *  @param data The data provider item.
         *
         *  @return The UID as a string.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        protected function itemToUID(data:Object):String
        {
            if (data == null)
                return "null";
            return UIDUtil.getUID(data);
        }

        //--------------------------------------------------------------------------
        //
        //  Methods: Item fields
        //
        //--------------------------------------------------------------------------
        
        /**
         *  Returns the string the renderer would display for the given data object
         *  based on the labelField and labelFunction properties.
         *  If the method cannot convert the parameter to a string, it returns a
         *  single space.
         *
         *  @param data Object to be rendered.
         *
         *  @return The string to be displayed based on the data.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public function itemToLabel(data:Object):String
        {
            if (data == null)
                return " ";
            
            /*
            if (labelFunction != null)
                return labelFunction(data);
            */
            
            if (data is XML)
            {
                try
                {
                    if ((data as XML)[labelField].length() != 0)
                        data = (data as XML)[labelField];
                    //by popular demand, this is a default XML labelField
                    //else if (data.@label.length() != 0)
                    //  data = data.@label;
                }
                catch(e:Error)
                {
                }
            }
            else if (data is Object)
            {
                try
                {
                    if (data[labelField] != null)
                        data = data[labelField];
                }
                catch(e:Error)
                {
                }
            }
            
            if (data is String)
                return String(data);
            
            try
            {
                return data.toString();
            }
            catch(e:Error)
            {
            }
            
            return " ";
        }
		
	//----------------------------------
    //  columnCount
    //----------------------------------

    /**
     *  @private
     *  Storage for the columnCount property.
     */
    private var _columnCount:int = -1;
    
    /**
     *  @private
     */
    private var columnCountChanged:Boolean = true;

    /**
     *  The number of columns to be displayed in a TileList control or items 
     *  in a HorizontalList control.
     *  For the DataGrid it is the number of visible columns.
     *  <b>Note</b>: Setting this property has no effect on a DataGrid control,
     *  which bases the number of columns on the control width and the
     *  individual column widths.
     * 
     *  @default 4
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get columnCount():int
    {
        return _columnCount;
    }

    /**
     *  @private
     */
    public function set columnCount(value:int):void
    {
        explicitColumnCount = value;

        if (_columnCount != value)
        {
            _columnCount = value;
            columnCountChanged = true;
            invalidateProperties();

            invalidateSize();
            itemsSizeChanged = true;
            invalidateDisplayList();

            dispatchEvent(new Event("columnCountChanged"));
        }
    }

    

	//----------------------------------
    //  dataTipField
    //----------------------------------

    /**
     *  @private
     *  Storage for the dataTipField property.
     */
    private var _dataTipField:String = "label";

    [Bindable("dataTipFieldChanged")]
    [Inspectable(category="Data", defaultValue="label")]

    /**
     *  Name of the field in the data provider items to display as the 
     *  data tip. By default, the list looks for a property named 
     *  <code>label</code> on each item and displays it.
     *  However, if the data objects do not contain a <code>label</code> 
     *  property, you can set the <code>dataTipField</code> property to
     *  use a different property in the data object. An example would be 
     *  "FullName" when viewing a
     *  set of people's names retrieved from a database.
     * 
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Royale 0.9.8
     */
    public function get dataTipField():String
    {
        return _dataTipField;
    }

    /**
     *  @private
     */
    public function set dataTipField(value:String):void
    {
        _dataTipField = value;

        itemsSizeChanged = true;
        invalidateDisplayList();

        dispatchEvent(new Event("dataTipFieldChanged"));
    }
	 //----------------------------------
    //  dataTipFunction
    //----------------------------------

    /**
     *  @private
     *  Storage for the dataTipFunction property.
     */
	protected var itemsSizeChanged:Boolean = false;
    private var _dataTipFunction:Function;

    [Bindable("dataTipFunctionChanged")]
    [Inspectable(category="Data")]

    /**
     *  User-supplied function to run on each item to determine its dataTip.  
     *  By default, the list looks for a property named <code>label</code> 
     *  on each data provider item and displays it.
     *  However, some items do not have a <code>label</code> property 
     *  nor do they have another property that can be used for displaying 
     *  in the rows. An example is a data set that has lastName and firstName 
     *  fields, but you want to display full names. You can supply a 
     *  <code>dataTipFunction</code> that finds the appropriate
     *  fields and return a displayable string. The 
     *  <code>dataTipFunction</code> is also good for handling formatting
     *  and localization.
     *
     *  <p>The dataTipFunction takes a single argument which is the item
     *  in the data provider and returns a String, as the following example shows:</p>
     * 
     *  <pre>myDataTipFunction(item:Object):String</pre>
     * 
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get dataTipFunction():Function
    {
        return _dataTipFunction;
    }

    /**
     *  @private
     */
    public function set dataTipFunction(value:Function):void
    {
        _dataTipFunction = value;

        itemsSizeChanged = true;
        invalidateDisplayList();

        dispatchEvent(new Event("dataTipFunctionChanged"));
    }
    
    //----------------------------------
    //  listData
    //----------------------------------

    /**
     *  @private
     *  Storage for the listData property.
     */
    private var _listData:BaseListData;

    [Bindable("dataChange")]
    [Inspectable(environment="none")]

    /**
     *  
     *  When a component is used as a drop-in item renderer or drop-in
     *  item editor, Flex initializes the <code>listData</code> property
     *  of the component with the additional data from the list control.
     *  The component can then use the <code>listData</code> property
     *  and the <code>data</code> property to display the appropriate
     *  information as a drop-in item renderer or drop-in item editor.
     *
     *  <p>You do not set this property in MXML or ActionScript;
     *  Flex sets it when the component is used as a drop-in item renderer
     *  or drop-in item editor.</p>
     *
     *  @see mx.controls.listClasses.IDropInListItemRenderer
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get listData():BaseListData
    {
        return _listData;
    }

    /**
     *  @private
     */
    public function set listData(value:BaseListData):void
    {
        _listData = value;
    }
	
    //----------------------------------
    //  data
    //----------------------------------

    /**
     *  @private
     *  Storage for the data property.
     */
    private var _data:Object = null;

    [Bindable("dataChange")]
    [Inspectable(environment="none")]

    /**
     *  The item in the data provider this component should render when
     *  this component is used as an item renderer or item editor.
     *  The list class sets this property on each renderer or editor
     *  and the component displays the data.  ListBase-derived classes
     *  support this property for complex situations like having a
     *  List of DataGrids or a DataGrid where one column is a List.
     *
     *  <p>The list classes use the <code>listData</code> property
     *  in addition to the <code>data</code> property to determine what
     *  to display.
     *  If the list class is in a DataGrid it expects the <code>dataField</code>
     *  property of the column to map to a property in the data
     *  and sets <code>selectedItem</code> value to that property.
     *  If it is in a List or TileList control, it expects the 
     *  <code>labelField</code> property of the list to map to a property 
     *  in the data, and sets <code>selectedItem</code> value to that property.
     *  Otherwise it sets the <code>selectedItem</code> to the data itself.</p>
     * 
     *  <p>This property uses the data provider but does not set it. 
     *  In all cases, you must set the data provider in some other way.</p>
     *
     *  <p>You do not set this property in MXML.</p>
     *
     *  @see mx.core.IDataRenderer
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get data():Object
    {
        return _data;
    }

    /**
     *  @private
     */
    public function set data(value:Object):void
    {
        _data = value;

        if (_listData && _listData is DataGridListData)
            selectedItem = _data[DataGridListData(_listData).dataField];
        else if (_listData is ListData && ListData(_listData).labelField in _data)
            selectedItem = _data[ListData(_listData).labelField];
        else
            selectedItem = _data;

        dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
    }
	
	public function measureHeightOfItems(index:int = -1, count:int = 0):Number
    {
        return NaN;
    }
	
	public function measureWidthOfItems(index:int = -1, count:int = 0):Number
    {
        return NaN;
    }
    

    }
}
