blob: 7b2ff26f1acc5365ef58ad5c9d4f080daac6369f [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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 flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.ui.Keyboard;
import flash.utils.Dictionary;
import flash.utils.clearInterval;
import flash.utils.setInterval;
import mx.collections.ArrayCollection;
import mx.collections.CursorBookmark;
import mx.collections.ICollectionView;
import mx.collections.IList;
import mx.collections.IViewCursor;
import mx.collections.ItemResponder;
import mx.collections.ItemWrapper;
import mx.collections.ListCollectionView;
import mx.collections.ModifiedCollectionView;
import mx.collections.XMLListCollection;
import mx.collections.errors.CursorError;
import mx.collections.errors.ItemPendingError;
import mx.controls.dataGridClasses.DataGridListData;
import mx.core.DragSource;
import mx.core.EdgeMetrics;
import mx.core.EventPriority;
import mx.core.FlexShape;
import mx.core.IDataRenderer;
import mx.core.IFactory;
import mx.core.IFlexDisplayObject;
import mx.core.IInvalidating;
import mx.core.ILayoutDirectionElement;
import mx.core.IUIComponent;
import mx.core.IUID;
import mx.core.IUITextField;
import mx.core.ScrollControlBase;
import mx.core.ScrollPolicy;
import mx.core.SpriteAsset;
import mx.core.mx_internal;
import mx.effects.IEffect;
import mx.effects.IEffectTargetHost;
import mx.effects.Tween;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.DragEvent;
import mx.events.EffectEvent;
import mx.events.FlexEvent;
import mx.events.ListEvent;
import mx.events.MoveEvent;
import mx.events.SandboxMouseEvent;
import mx.events.ScrollEvent;
import mx.events.ScrollEventDetail;
import mx.events.ScrollEventDirection;
import mx.events.TweenEvent;
import mx.managers.DragManager;
import mx.managers.IFocusManagerComponent;
import mx.managers.ISystemManager;
import mx.skins.halo.ListDropIndicator;
import mx.styles.StyleProxy;
import mx.utils.ObjectUtil;
import mx.utils.UIDUtil;
use namespace mx_internal;
//--------------------------------------
// Events
//--------------------------------------
/**
* Dispatched when the <code>selectedIndex</code> or <code>selectedItem</code> property
* changes as a result of user interaction.
*
* @eventType mx.events.ListEvent.CHANGE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="change", type="mx.events.ListEvent")]
/**
* Dispatched when the <code>data</code> property changes.
*
* <p>When you use a component as an item renderer,
* the <code>data</code> property contains the data to display.
* You can listen for this event and update the component
* when the <code>data</code> property changes.</p>
*
* @eventType mx.events.FlexEvent.DATA_CHANGE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="dataChange", type="mx.events.FlexEvent")]
/**
* Dispatched when the user rolls the mouse pointer over an item in the control.
*
* @eventType mx.events.ListEvent.ITEM_ROLL_OVER
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="itemRollOver", type="mx.events.ListEvent")]
/**
* Dispatched when the user rolls the mouse pointer out of an item in the control.
*
* @eventType mx.events.ListEvent.ITEM_ROLL_OUT
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="itemRollOut", type="mx.events.ListEvent")]
/**
* 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
//--------------------------------------
include "../../styles/metadata/PaddingStyles.as"
/**
* 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 Flex 3
*/
[Style(name="alternatingItemColors", type="Array", arrayType="uint", format="Color", inherit="yes")]
/**
* The skin to use to indicate where a dragged item can be dropped.
* When a ListBase-derived component is a potential drop target in a
* drag-and-drop operation, a call to the <code>showDropFeedback()</code>
* method makes an instance of this class and positions it one pixel above
* the itemRenderer for the item where, if the drop occurs, is the item after
* the dropped item.
*
* @default mx.controls.listClasses.ListDropIndicator
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="dropIndicatorSkin", type="Class", inherit="no")]
/**
* The number of pixels between the bottom of the row
* and the bottom of the renderer in the row.
*
* @default 2
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="paddingBottom", type="Number", format="Length", inherit="no")]
/**
* The number of pixels between the top of the row
* and the top of the renderer in the row.
*
* @default 2
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="paddingTop", type="Number", format="Length", inherit="no")]
/**
* The color of the background of a renderer when the user rolls over it.
*
* The default value for the Halo theme is <code>0xB2E1FF</code>.
* The default value for the Spark theme is <code>0xCEDBEF</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="rollOverColor", type="uint", format="Color", inherit="yes")]
/**
* The color of the background of a renderer when the user selects it.
*
* The default value for the Halo theme is <code>0x7FCEFF</code>.
* The default value for the Spark theme is <code>0xA8C6EE</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="selectionColor", type="uint", format="Color", inherit="yes")]
/**
* The color of the background of a renderer when the component is disabled.
*
* @default 0xDDDDDD
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="selectionDisabledColor", type="uint", format="Color", inherit="yes")]
/**
* The duration of the selection effect.
* When an item is selected an effect plays as the background is colored.
* Set to 0 to disable the effect.
*
* @default 250
*
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="selectionDuration", type="Number", format="Time", inherit="no")]
/**
* The easingFunction for the selection effect.
* When an item is selected an effect plays as the background is colored.
* The default is a linear fade in of the color. An easingFunction can be used
* for controlling the selection effect.
*
* @default undefined
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="selectionEasingFunction", type="Function", inherit="no")]
/**
* The color of the text of a renderer when the user rolls over a it.
*
* The default value for the Halo theme is <code>0x2B333C</code>.
* The default value for the Spark theme is <code>0x000000</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="textRollOverColor", type="uint", format="Color", inherit="yes")]
/**
* The color of the text of a renderer when the user selects it.
*
* The default value for the Halo theme is <code>0x2B333C</code>.
* The default value for the Spark theme is <code>0x000000</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="textSelectedColor", type="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 Flex 3
*/
[Style(name="useRollOver", type="Boolean", inherit="no")]
/**
* The vertical alignment of a renderer in a row.
* Possible values are <code>"top"</code>, <code>"middle"</code>,
* and <code>"bottom"</code>.
* The DataGrid positions the renderers in a row based on this style
* and the <code>paddingTop</code> and <code>paddingBottom</code> styles.
* if the item in the columns for a row have different heights
* Other list classes do not use <code>verticalAlign</code> but
* the item renderers can examine this style property
* and adjust their layout based on it.
*
* @default "top"
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="verticalAlign", type="String", enumeration="bottom,middle,top", inherit="no")]
//--------------------------------------
// Other metadata
//--------------------------------------
[AccessibilityClass(implementation="mx.accessibility.ListBaseAccImpl")]
/**
* The ListBase class is the base class for controls that represent lists
* of items that can have one or more selected and can scroll through the
* items. Items are supplied using the <code>dataProvider</code> property
* and displayed via item renderers.
*
* <p>In a model/view architecture, the ListBase-derived class represents
* the view, and the dataProvider object represents the model.</p>
*
* @mxml
*
* <p>The ListBase class inherits all of the tag properties of its superclasses,
* and adds the following tag properties:</p>
*
* <pre>
* &lt;mx:<i>tagname</i>
* <b>Properties</b>
* allowDragSelection="false|true"
* allowMultipleSelection="false|true"
* columnCount="4"
* columnWidth="NaN"
* dataProvider="null"
* dataTipField="label"
* dataTipFunction="null"
* dragEnabled="false|true"
* dragMoveEnabled="false|true"
* dropEnabled="false|true"
* iconField="null"
* iconFunction="null"
* itemRenderer="null"
* labelField="label"
* labelFunction="null"
* menuSelectionMode="false|true"
* offscreenExtraRowsOrColumns="0"
* rowCount="-1"
* rowHeight="NaN"
* selectable="true|false"
* selectedIndex="-1"
* selectedIndices="null"
* selectedItem="null"
* selectedItems="null"
* showDataTips="false|true"
* variableRowHeight="false|true"
* wordWrap="false|true"
*
* <b>Styles</b>
* alternatingItemColors="undefined"
* itemsChangeEffect="undefined"
* dropIndicatorSkin="ListDropIndicator"
* focusAlpha="0.5"
* focusRoundedCorners="tl tr bl br"
* paddingBottom="2"
* paddingLeft="2"
* paddingRight="0"
* paddingTop="2"
* rollOverColor="0xEEFEE6"
* selectionColor="0x7FCEFF"
* selectionDisabledColor="0xDDDDDD"
* selectionDuration="250"
* selectionEasingFunction="undefined"
* textRollOverColor="0x2B333C"
* textSelectedColor="0x2B333C"
* useRollOver="true|false"
* verticalAlign="top|middle|bottom"
*
* <b>Events</b>
* change="<i>No default</i>"
* dataChange="<i>No default</i>"
* itemClick="<i>No default</i>"
* itemDoubleClick="<i>No default</i>"
* itemRollOut="<i>No default</i>"
* itemRollOver="<i>No default</i>"
* /&gt;
* </pre>
*
* @see mx.collections.ICollectionView
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public class ListBase extends ScrollControlBase
implements IDataRenderer, IFocusManagerComponent,
IListItemRenderer, IDropInListItemRenderer,
IEffectTargetHost
{
include "../../core/Version.as";
//--------------------------------------------------------------------------
//
// Class constants
//
//--------------------------------------------------------------------------
/**
* @private
* Anything in this list of styles will trigger a full repaint.
*/
private var IS_ITEM_STYLE:Object =
{
alternatingItemColors: true,
backgroundColor: true,
backgroundDisabledColor: true,
color: true,
rollOverColor: true,
selectionColor: true,
selectionDisabledColor: true,
styleName: true,
textColor:true,
textRollOverColor: true,
textSelectedColor: true
};
/**
* @private
* Mouse movement threshold for determining when to start a drag.
*/
mx_internal static const DRAG_THRESHOLD:int = 4;
//--------------------------------------------------------------------------
//
// Class mixins
//
//--------------------------------------------------------------------------
/**
* @private
* Placeholder for mixin by ListBaseAccImpl.
*/
mx_internal static var createAccessibilityImplementation:Function;
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function ListBase()
{
super();
tabEnabled = true;
tabFocusEnabled = true;
factoryMap = new Dictionary(true);
addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
addEventListener(MouseEvent.CLICK, mouseClickHandler);
addEventListener(MouseEvent.DOUBLE_CLICK, mouseDoubleClickHandler);
invalidateProperties();
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* An ICollectionView that represents the data provider.
* When you set the <code>dataProvider</code> property,
* Flex wraps the data provider as necessary to
* support the ICollectionView interface and
* sets this property to the result.
* The ListBase class then uses this property to access
* data in the provider.
* When you get the <code>dataProvider</code> property,
* Flex returns this value.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var collection:ICollectionView;
/**
* The main IViewCursor used to fetch items from the
* data provider and pass the items to the renderers.
* At the end of any sequence of code, it must always
* be positioned at the topmost visible item being displayed.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var iterator:IViewCursor
/**
* A flag that indicates that a page fault as occurred and that
* the iterator's position is not valid (not positioned at the topmost
* item being displayed).
* If the component gets a page fault (an ItemPending error),
* it sets <code>iteratorValid</code> to <code>false</code>. Code that
* normally handles the rendering of items checks this flag and does not
* run until the page of data comes in from the server.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var iteratorValid:Boolean = true;
/**
* The most recent seek that caused a page fault.
* If there are multiple page faults, only the most recent one
* is of interest, as that is where to position the iterator
* and start rendering rows again.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var lastSeekPending:ListBaseSeekPending;
/**
* A hash table of data provider item renderers currently in view.
* The table is indexed by the data provider item's UID and is used
* to quickly get the renderer used to display a particular item.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get visibleData():Object
{
return listContent.visibleData;
}
/**
* An internal display object that parents all of the item renderers,
* selection and highlighting indicators and other supporting graphics.
* This is roughly equivalent to the <code>contentPane</code> in the
* Container class, and is used for managing scrolling.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var listContent:ListBaseContentHolder;
//----------------------------------
// listContentStyleFilters
//----------------------------------
/**
* The set of styles to pass from the ListBase to the listContent.
* @see mx.styles.StyleProxy
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get listContentStyleFilters():Object
{
return _listContentStyleFilters;
}
private static var _listContentStyleFilters:Object = null;
/**
* The layer in <code>listContent</code> where all selection
* and highlight indicators are drawn.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var selectionLayer:Sprite;
/**
* An Array of Arrays that contains
* the itemRenderer instances that render each data provider item.
* This is a two-dimensional row major array
* (array of rows that are arrays of columns).
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get listItems():Array
{
return listContent ? listContent.listItems : [];
}
/**
* An array of ListRowInfo objects that cache row heights and
* other tracking information for the rows in listItems.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get rowInfo():Array
{
return listContent.rowInfo;
}
/**
* A hash map of item renderers to their respective ListRowInfo object.
* The ListRowInfo object is indexed by the DisplayObject name of the
* item renderer.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var rowMap:Object = {};
/**
* A map of item renderers by factory.
* This property is a Dictionary indexed by itemRenderers
* where the values are IFactory.
*
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var factoryMap:Dictionary;
/**
* A stack of unused item renderers.
* Most list classes recycle renderers they've already created
* as they scroll out of the displayable area; doing so
* saves time during scrolling.
* The recycled renderers are stored here.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var freeItemRenderers:Array = [];
/**
* A map of free item renderers by factory.
* This property is a Dictionary indexed by factories
* where the values are Dictionaries of itemRenderers.
*
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var freeItemRenderersByFactory:Dictionary;
/**
* A hash map of currently unused item renderers that may be
* used again in the near future. Used when running data effects.
* The map is indexed by the data provider item's UID.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var reservedItemRenderers:Object = {};
/**
* A hash map of item renderers that are not subject
* to the layout algorithms of the list.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var unconstrainedRenderers:Dictionary = new Dictionary();
/**
* A dictionary mapping item renderers to the ItemWrappers
* used to supply their data. Only applicable if a data
* effect is running.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var dataItemWrappersByRenderer:Dictionary = new Dictionary(true);
/**
* A flag that indicates if a data effect should be initiated
* the next time the display is updated.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var runDataEffectNextUpdate:Boolean = false;
/**
* A flag indicating if a data change effect is currently running.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var runningDataEffect:Boolean = false;
/**
* The effect that plays when changes occur in the data
* provider for the control, set through the itemsChangeEffect
* style.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var cachedItemsChangeEffect:IEffect = null;
/**
* The collection view that temporarily preserves previous
* data provider state to facilitate running data change effects.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var modifiedCollectionView:ModifiedCollectionView;
/**
* A copy of the value normally stored in <code>collection</code>
* used while running data changes effects. This value should be
* null when a data change effect is not running.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var actualCollection:ICollectionView;
/**
* The target number of extra rows of item renderers to be used in
* the layout of the control. Half of these rows are created
* above the visible onscreen rows; half are created below.
*
* Typically this property is set indirectly when you set the
* <code>offscreenExtraRowsOrColumns</code> property.
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var offscreenExtraRows:int = 0;
/**
* The number of offscreen rows currently above the topmost visible
* row. This value will be &lt;= <code>offscreenExtraRows</code> / 2.
* It is used when computing the relationship of <code>listItems</code> and
* <code>rowInfo</code> Arrays to items in the data provider (in conjunction
* with <code>verticalScrollPosition</code> property).
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var offscreenExtraRowsTop:int = 0;
/**
* The number of offscreen rows currently below the bottom visible
* item renderer. This value will be &lt;= <code>offscreenExtraRows</code> / 2.
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var offscreenExtraRowsBottom:int = 0;
/**
* The target number of extra columns of item renderers used in the
* layout of the control. Half of these columns are created to
* the left of the visible onscreen columns; half are created
* to the right.
*
* Typically this property will be set indirectly when you set the
* <code>offscreenExtraRowsOrColumns</code> property.
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var offscreenExtraColumns:int = 0;
/**
* The number of offscreen columns currently to the left of the
* leftmost visible column.
* This value will be &lt;= <code>offscreenExtraColumns</code> / 2.
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var offscreenExtraColumnsLeft:int = 0;
/**
* The number of offscreen columns currently to the right of the
* right visible column.
* This value will be &lt;= <code>offscreenExtraColumns</code> / 2.
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var offscreenExtraColumnsRight:int = 0;
/**
* A copy of the value normally stored in <code>iterator</code>
* used while running data changes effects.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var actualIterator:IViewCursor;
/**
* @private
* A flag indicating whether layout code in makeRowsAndColumns()
* should be allowed to "steal" renderers. This is needed for
* data effects (preserving renderers across multiple layout passes)
* but specifically bad for incremental scrolling in the degenerate
* case where there are duplicate items in the data provider.
*/
mx_internal var allowRendererStealingDuringLayout:Boolean = true;
/**
* The UID of the item that is current rolled over or under the caret.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var highlightUID:String;
/**
* The renderer that is currently rolled over or under the caret.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var highlightItemRenderer:IListItemRenderer;
/**
* The DisplayObject that contains the graphics that indicates
* which renderer is highlighted.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var highlightIndicator:Sprite;
/**
* The UID of the item under the caret.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var caretUID:String;
/**
* The renderer for the item under the caret. In the selection
* model, there is an anchor, a caret and a highlighted item. When
* the mouse is being used for selection, the item under the mouse is
* highlighted as the mouse rolls over the item.
* When the mouse is clicked with no modifier keys (Shift or Ctrl), the
* set of selected items is cleared and the item under the highlight is
* selected and becomes the anchor. The caret is unused in mouse
* selection. If there is an anchor and another item is selected while
* using the Shift key, the old set of selected items is cleared, and
* all items between the item and the anchor are selected. Clicking
* items while using the Ctrl key toggles the selection of individual
* items and does not move the anchor.
*
* <p>When selecting items using the keyboard, if the arrow keys are used
* with no modifier keys, the old selection is cleared and the new item
* is selected and becomes the anchor and the caret, and a caret indicator
* is shown around the selection highlight. If the user uses arrow keys
* with the Shift key, the old selection is cleared and the items between
* the anchor and the new item are selected. The caret moves to the new
* item. If arrow keys are used with the Ctrl key, just the caret moves.
* The user can use the Space key to toggle selection of the item under
* the caret.</p>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var caretItemRenderer:IListItemRenderer;
/**
* The DisplayObject that contains the graphics that indicate
* which renderer is the caret.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var caretIndicator:Sprite;
/**
* A hash table of ListBaseSelectionData objects that track which
* items are currently selected. The table is indexed by the UID
* of the items.
*
* @see mx.controls.listClasses.ListBaseSelectionData
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var selectedData:Object = {};
/**
* A hash table of selection indicators. This table allows the component
* to quickly find and remove the indicators when the set of selected
* items is cleared. The table is indexed by the item's UID.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var selectionIndicators:Object = {};
/**
* A hash table of selection tweens. This allows the component to
* quickly find and clean up any tweens in progress if the set
* of selected items is cleared. The table is indexed by the item's UID.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var selectionTweens:Object = {};
/**
* A bookmark to the item under the caret. A bookmark allows the
* component to quickly seek to a position in the collection of items.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var caretBookmark:CursorBookmark;
/**
* A bookmark to the item that is the anchor. A bookmark allows the
* component to quickly seek to a position in the collection of items.
* This property is used when selecting a set of items between the anchor
* and the caret or highlighted item, and when finding the selected item
* after a Sort or Filter is applied.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var anchorBookmark:CursorBookmark;
/**
* A flag that indicates whether to show caret.
* This property is usually set
* to <code>false</code> when mouse activity is detected and set back to
* <code>true</code> when the keyboard is used for selection.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var showCaret:Boolean;
/**
* The most recently calculated index where the drag item
* should be added to the drop target.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var lastDropIndex:int;
/**
* A flag that indicates whether the <code>columnWidth</code>
* and <code>rowHeight</code> properties need to be calculated.
* This property is set if a style changes that can affect the
* measurements of the renderer, or if the data provider is changed.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var itemsNeedMeasurement:Boolean = true;
/**
* A flag that indicates that the size of the renderers may have changed.
* The component usually responds by re-applying the data items to all of
* the renderers on the next <code>updateDisplayList()</code> call.
* There is an assumption that re-applying the items will invalidate the
* item renderers and cause them to re-measure.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var itemsSizeChanged:Boolean = false;
/**
* A flag that indicates that the renderer changed.
* The component usually responds by destroying all existing renderers
* and redrawing all of the renderers on the next
* <code>updateDisplayList()</code> call.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var rendererChanged:Boolean = false;
/**
* A flag that indicates that the a data change effect has
* just completed.
* The component usually responds by cleaning up various
* internal data structures on the next
* <code>updateDisplayList()</code> call.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var dataEffectCompleted:Boolean = false;
/**
* A flag that indicates whether the value of the <code>wordWrap</code>
* property has changed since the last time the display list was updated.
* This property is set when you change the <code>wordWrap</code>
* property value, and is reset
* to <code>false</code> by the <code>updateDisplayList()</code> method.
* The component usually responds by re-applying the data items to all of
* the renderers on the next <code>updateDisplayList()</code> call.
* This is different from itemsSizeChanged because it further indicates
* that re-applying the data items to the renderers may not invalidate them
* since the only thing that changed was whether or not the renderer should
* factor in wordWrap into its size calculations.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var wordWrapChanged:Boolean = false;
/**
* A flag that indicates if keyboard selection was interrupted by
* a page fault. The component responds by suspending the rendering
* of items until the page of data arrives.
* The <code>finishKeySelection()</code> method will be called
* when the paged data arrives.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var keySelectionPending:Boolean = false;
/**
* @private
* Cached style value.
*/
mx_internal var cachedPaddingTop:Number;
/**
* @private
* Cached style value.
*/
mx_internal var cachedPaddingBottom:Number;
/**
* @private
* Cached style value.
*/
mx_internal var cachedVerticalAlign:String;
/**
* @private
*/
private var oldUnscaledWidth:Number;
/**
* @private
*/
private var oldUnscaledHeight:Number;
/**
* @private
*/
private var horizontalScrollPositionPending:Number;
/**
* @private
*/
private var verticalScrollPositionPending:Number;
/**
* @private
*/
private var mouseDownPoint:Point;
/**
* @private
*/
private var bSortItemPending:Boolean = false;
// these three keep track of the key selection that caused
// the page fault
private var bShiftKey:Boolean = false;
private var bCtrlKey:Boolean = false;
private var lastKey:uint = 0;
private var bSelectItem:Boolean = false;
/**
* @private
* true if we don't know for sure what index we're on in the database
*/
private var approximate:Boolean = false;
// if false, pixel scrolling only in horizontal direction
mx_internal var bColumnScrolling:Boolean = true;
// either "horizontal", "vertical", "grid" Used to determine how
// to measure the list.
mx_internal var listType:String = "grid";
// mx_internal for automation delegate access
mx_internal var bSelectOnRelease:Boolean;
private var mouseDownItem:IListItemRenderer;
private var mouseDownIndex:int; // For drag and drop
mx_internal var bSelectionChanged:Boolean = false;
mx_internal var bSelectedIndexChanged:Boolean = false;
private var bSelectedItemChanged:Boolean = false;
private var bSelectedItemsChanged:Boolean = false;
private var bSelectedIndicesChanged:Boolean = false;
/**
* @private
* Dirty flag for the cache style value cachedPaddingTop.
*/
private var cachedPaddingTopInvalid:Boolean = true;
/**
* @private
* Dirty flag for the cache style value cachedPaddingBottom.
*/
private var cachedPaddingBottomInvalid:Boolean = true;
/**
* @private
* Dirty flag for the cache style value cachedVerticalAlign.
*/
private var cachedVerticalAlignInvalid:Boolean = true;
/**
* @private
* The first ListBaseSelectionData in a link list of ListBaseSelectionData.
* This represents the item that was most recently selected.
* ListBaseSelectionData instances are linked together and keep track of the
* order the user selects an item. This order is reflected in selectedIndices
* and selectedItems.
*/
private var firstSelectionData:ListBaseSelectionData;
/**
* @private
* The last ListBaseSelectionData in a link list of ListBaseSelectionData.
* This represents the item that was first selected.
* ListBaseSelectionData instances are linked together and keep track of the
* order the user selects an item. This order is reflected in selectedIndices
* and selectedItems.
*/
private var lastSelectionData:ListBaseSelectionData;
/**
* The first proposed selectedItem. Because the loop where it is used
* can be called several times becaouse of IPEs, we have to store stuff like
* this outside the loop
*/
private var firstSelectedItem:Object;
/**
* A map of proposed selectedItems to the original order
* they were proposed. Because the loop where it is used
* can be called several times becaouse of IPEs, we have to store stuff like
* this outside the loop
*/
private var proposedSelectedItemIndexes:Dictionary;
/**
* The renderer that is or was rolled over or under the caret.
* In DG, this is always column 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal var lastHighlightItemRenderer:IListItemRenderer;
/**
* The renderer that is or was rolled over or under the caret.
* In DG, this is the actual item
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal var lastHighlightItemRendererAtIndices:IListItemRenderer;
/**
* The last coordinate send in ITEM_ROLL_OVER
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private var lastHighlightItemIndices:Point;
/**
* Temporary array to manage order of selectedItems
*/
private var selectionDataArray:Array;
mx_internal var dragScrollingInterval:int = 0;
/**
* @private
* An Array of Shapes that are used as clip masks for the list items
*/
mx_internal var itemMaskFreeList:Array;
/**
* @private
* An array of item renderers being tracked for MoveEvents while
* data change effects are running.
*/
private var trackedRenderers:Array = [];
/**
* @private
* A flag used to avoid tracking renderers for MoveEvents when
* running updateDisplayList.
*/
private var rendererTrackingSuspended:Boolean = false;
/**
* @private
* Whether the mouse button is pressed
*/
mx_internal var isPressed:Boolean = false;
/**
* A separate IViewCursor used to find indices of items and
* other things. The collectionIterator can be at any
* place within the set of items.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal var collectionIterator:IViewCursor;
mx_internal var dropIndicator:IFlexDisplayObject;
/**
* diagnostics
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function get rendererArray():Array
{
return listItems;
}
mx_internal var lastDragEvent:DragEvent;
//--------------------------------------------------------------------------
//
// Overridden properties: UIComponent
//
//--------------------------------------------------------------------------
//----------------------------------
// 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;
var isNull:Boolean = dataProvider == null;
var isEmpty:Boolean = dataProvider != null && dataProvider.length == 0;
var originalProvider:Object = dataProvider;
if (isNull || isEmpty)
{
dataProvider = [ null ];
validateNow();
}
if (!listItems || listItems.length == 0)
return super.baselinePosition;
var listItem:IUIComponent = listItems[0][0] as IUIComponent;
if (!listItem)
return super.baselinePosition;
var contentHolder:ListBaseContentHolder =
ListBaseContentHolder(listItem.parent);
var result:Number = contentHolder.y + listItem.y + listItem.baselinePosition;
if (isNull || isEmpty)
{
dataProvider = originalProvider;
validateNow();
}
return result;
}
//----------------------------------
// enabled
//----------------------------------
[Inspectable(category="General")]
/**
* @private
*/
override public function set enabled(value:Boolean):void
{
super.enabled = value;
var ui:IFlexDisplayObject = border as IFlexDisplayObject;
if (ui)
{
if (ui is IUIComponent)
IUIComponent(ui).enabled = value;
if (ui is IInvalidating)
IInvalidating(ui).invalidateDisplayList();
}
itemsSizeChanged = true;
invalidateDisplayList();
}
//----------------------------------
// showInAutomationHierarchy
//----------------------------------
/**
* @private
*/
override public function set showInAutomationHierarchy(value:Boolean):void
{
//do not allow value changes
}
//--------------------------------------------------------------------------
//
// Overridden properties: ScrollControlBase
//
//--------------------------------------------------------------------------
//----------------------------------
// horizontalScrollPolicy
//----------------------------------
/**
* @private
*/
override public function set horizontalScrollPolicy(value:String):void
{
super.horizontalScrollPolicy = value;
itemsSizeChanged = true;
invalidateDisplayList();
}
//----------------------------------
// horizontalScrollPosition
//----------------------------------
[Bindable("scroll")]
[Bindable("viewChanged")]
[Inspectable(defaultValue="0")]
/**
* @private
*/
override public function get horizontalScrollPosition():Number
{
if (!isNaN(horizontalScrollPositionPending))
return horizontalScrollPositionPending;
return super.horizontalScrollPosition;
}
/**
* @private
*/
override public function set horizontalScrollPosition(value:Number):void
{
// if not init or no data;
if (listItems.length == 0 || !dataProvider || !isNaN(horizontalScrollPositionPending))
{
horizontalScrollPositionPending = value;
if (dataProvider)
invalidateDisplayList();
return;
}
horizontalScrollPositionPending = NaN;
// trace("set horizontalScrollPosition " + value + " " + super.horizontalScrollPosition);
var oldValue:int = super.horizontalScrollPosition;
super.horizontalScrollPosition = value;
removeClipMask();
if (oldValue != value)
{
// we're going to get a full repaint soon so don't bother here.
if (itemsSizeChanged)
return;
var deltaPos:int = value - oldValue;
var direction:Boolean = (deltaPos > 0);
deltaPos = Math.abs(deltaPos);
if (bColumnScrolling && deltaPos >= columnCount)
{
clearIndicators();
clearVisibleData();
makeRowsAndColumnsWithExtraColumns(oldUnscaledWidth, oldUnscaledHeight);
drawRowBackgrounds();
}
else
{
scrollHorizontally(value, deltaPos, direction);
}
}
addClipMask(false);
}
mx_internal function set $horizontalScrollPosition(value:Number):void
{
var oldValue:int = super.horizontalScrollPosition;
if (oldValue != value)
super.horizontalScrollPosition = value;
}
//----------------------------------
// verticalScrollPolicy
//----------------------------------
/**
* @private
*/
override public function set verticalScrollPolicy(value:String):void
{
super.verticalScrollPolicy = value;
itemsSizeChanged = true;
invalidateDisplayList();
}
//----------------------------------
// verticalScrollPosition
//----------------------------------
[Bindable("scroll")]
[Bindable("viewChanged")]
/**
* @private
*/
override public function get verticalScrollPosition():Number
{
if (!isNaN(verticalScrollPositionPending))
return verticalScrollPositionPending;
return super.verticalScrollPosition;
}
/**
* @private
*/
override public function set verticalScrollPosition(value:Number):void
{
if (listItems.length == 0 || !dataProvider || !isNaN(verticalScrollPositionPending))
{
verticalScrollPositionPending = value;
if (dataProvider)
invalidateDisplayList();
return;
}
verticalScrollPositionPending = NaN;
var oldValue:int = super.verticalScrollPosition;
super.verticalScrollPosition = value;
removeClipMask();
var oldoffscreenExtraRowsTop:int = offscreenExtraRowsTop;
var oldoffscreenExtraRowsBottom:int = offscreenExtraRowsBottom;
// trace("set verticalScrollPosition", oldValue, value);
if (oldValue != value)
{
var deltaPos:int = value - oldValue;
var direction:Boolean = (deltaPos > 0);
deltaPos = Math.abs(deltaPos);
if (deltaPos >= (rowInfo.length - offscreenExtraRows) || !iteratorValid)
{
clearIndicators();
clearVisibleData();
makeRowsAndColumnsWithExtraRows(oldUnscaledWidth, oldUnscaledHeight);
}
else
{
scrollVertically(value, deltaPos, direction);
adjustListContent(oldUnscaledWidth,oldUnscaledHeight);
}
// if variable rowheight, we have to recalibrate the scrollbars thumb size
// on each scroll, otherwise you can't scroll down to a bunch of fat rows
// at the bottom of a list.
if (variableRowHeight)
configureScrollBars();
drawRowBackgrounds();
}
// if needed, add a clip mask to the items in the last row of the list
addClipMask((offscreenExtraRowsTop != oldoffscreenExtraRowsTop) || (offscreenExtraRowsBottom != oldoffscreenExtraRowsBottom));
}
mx_internal function set $verticalScrollPosition(value:Number):void
{
var oldValue:int = super.verticalScrollPosition;
if (oldValue != value)
super.verticalScrollPosition = value;
}
private function makeRowsAndColumnsWithExtraRows(unscaledWidth:Number,unscaledHeight:Number):void
{
var lastPrefixRow:ListRowInfo;
var lastOnscreenRow:ListRowInfo;
var lastOffscreenRow:ListRowInfo;
var onscreenRowIndex:int;
var pt:Point;
var desiredExtraRowsTop:int = offscreenExtraRows / 2;
var desiredExtraRowsBottom:int = offscreenExtraRows / 2;
offscreenExtraRowsTop = Math.min(desiredExtraRowsTop, verticalScrollPosition);
var index:int = scrollPositionToIndex(horizontalScrollPosition, verticalScrollPosition - offscreenExtraRowsTop);
seekPositionSafely(index);
var cursorPos:CursorBookmark = iterator.bookmark;
// if necessary, make the rows that will eventually be offscreen, above visible rows
if (offscreenExtraRowsTop > 0)
makeRowsAndColumns(0, 0, listContent.width, listContent.height, 0, 0, true, offscreenExtraRowsTop);
var curY:Number = offscreenExtraRowsTop > 0 ? rowInfo[offscreenExtraRowsTop-1].y + rowHeight : 0;
// make onscreen items
pt = makeRowsAndColumns(0, curY, listContent.width, curY + listContent.heightExcludingOffsets, 0, offscreenExtraRowsTop);
// if necessary, and possible, make offscreen rows below visible rows.
if (desiredExtraRowsBottom > 0 && !iterator.afterLast)
{
// watch out for boundary condition
if (offscreenExtraRowsTop + pt.y - 1 < 0)
curY = 0;
else
curY = rowInfo[offscreenExtraRowsTop + pt.y - 1].y + rowInfo[offscreenExtraRowsTop + pt.y - 1].height;
var currentRows:int = listItems.length;
pt = makeRowsAndColumns(0, curY, listContent.width, curY, 0, offscreenExtraRowsTop + pt.y, true, desiredExtraRowsBottom);
// Guard against a couple edge cases here, where we don't make as many rows as we want to
// First case -- we made blank rows, but pt.y == desiredExtraRowsBottom
// This can happen in List.makeRowsAndColumns()
if (pt.y == desiredExtraRowsBottom)
{
while ((pt.y > 0) && listItems[listItems.length - 1] && (listItems[listItems.length - 1].length == 0))
{
pt.y--;
listItems.pop();
rowInfo.pop();
}
}
// Second case -- we made blank rows, but we know how many we made
// This can happen in TileList.makeRowsAndColumns()
// (Really, the behavior should be identical...but it isn't at the moment).
else if (pt.y < desiredExtraRowsBottom)
{
var extraEmptyRows:int = listItems.length - (currentRows + pt.y);
if (extraEmptyRows)
for (var i:int = 0; i < extraEmptyRows; i++)
{
listItems.pop();
rowInfo.pop();
}
}
offscreenExtraRowsBottom = pt.y;
}
else
offscreenExtraRowsBottom = 0;
// adjust the ListContent offsets so that the first visible row is exactly at the top of the screen, etc.
var oldContentHeight:Number = listContent.heightExcludingOffsets;
listContent.topOffset = -offscreenExtraRowsTop * rowHeight;
listContent.bottomOffset = (offscreenExtraRowsBottom > 0) ?
listItems[listItems.length-1][0].y + rowHeight - oldContentHeight + listContent.topOffset :
0;
seekPositionIgnoreError(iterator, cursorPos);
// make sure list content is moved to the appropriate place.
// might be able to optimize and not do this every time
adjustListContent(unscaledWidth,unscaledHeight);
}
private function makeRowsAndColumnsWithExtraColumns(unscaledWidth:Number,unscaledHeight:Number):void
{
// NOTE: this function only works correctly for fixed column width
//if we scrolled more than the number of scrollable rows
var desiredOffscreenColumnsLeft:int = offscreenExtraColumns / 2;
var desiredOffscreenColumnsRight:int = offscreenExtraColumns / 2;
if (horizontalScrollPosition > collection.length - columnCount)
super.horizontalScrollPosition = Math.max(0, collection.length - columnCount);
offscreenExtraColumnsLeft = Math.min(desiredOffscreenColumnsLeft,horizontalScrollPosition);
var index:int = scrollPositionToIndex(horizontalScrollPosition - offscreenExtraColumnsLeft, verticalScrollPosition);
seekPositionSafely(index);
var cursorPos:CursorBookmark = iterator.bookmark;
// if we are maintaining an extra column buffer, make extra columns
if (offscreenExtraColumnsLeft > 0)
makeRowsAndColumns(0, 0, 0, listContent.height, 0, 0, true, offscreenExtraColumnsLeft);
var curX:Number = offscreenExtraColumnsLeft ? listItems[0][offscreenExtraColumnsLeft-1].x + columnWidth : 0;
var pt:Point = makeRowsAndColumns(curX, 0, curX + listContent.widthExcludingOffsets, listContent.height, offscreenExtraColumnsLeft, 0);
if (desiredOffscreenColumnsRight > 0 && !iterator.afterLast)
{
if (offscreenExtraColumnsLeft + pt.x - 1 < 0)
curX = 0;
else
curX = listItems[0][offscreenExtraColumnsLeft + pt.x - 1].x + columnWidth;
var currentColumns:int = listItems[0].length;
pt = makeRowsAndColumns(curX, 0, curX, listContent.height,
offscreenExtraColumnsLeft + pt.x, 0, true,
desiredOffscreenColumnsRight);
if (pt.x < desiredOffscreenColumnsRight)
{
var extraEmptyColumns:int = listItems[0].length - (currentColumns + pt.x);
if (extraEmptyColumns)
{
for (var i:int = 0; i < listItems.length; i++)
for (var j:int = 0; j < extraEmptyColumns; j++)
listItems[i].pop();
}
}
offscreenExtraColumnsRight = pt.x; // I *think* this is always true
}
else
offscreenExtraColumnsRight = 0;
var oldContentWidth:Number = listContent.widthExcludingOffsets;
listContent.leftOffset = -offscreenExtraColumnsLeft * columnWidth;
listContent.rightOffset = (offscreenExtraColumnsRight > 0) ?
listItems[0][listItems[0].length-1].x + columnWidth - oldContentWidth + listContent.leftOffset :
0;
iterator.seek(cursorPos, 0);
adjustListContent(unscaledWidth, unscaledHeight);
}
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// allowDragSelection
//----------------------------------
/**
* A flag that indicates whether drag-selection is enabled.
* Drag-Selection is the ability to select an item by dragging
* into it as opposed to normal selection where you can't have
* the mouse button down when you mouse over the item you want
* to select. This feature is used in ComboBox dropdowns
* to support pressing the mouse button when the mouse is over the
* dropdown button then dragging the mouse into the dropdown to select
* an item.
*
* @default false
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var allowDragSelection:Boolean = false;
//----------------------------------
// 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;
}
//----------------------------------
// anchorIndex
//----------------------------------
/**
* The offset of the item in the data provider that is the selection
* anchor point.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var anchorIndex:int = -1;
//----------------------------------
// caretIndex
//----------------------------------
/**
* The offset of the item in the data provider that is the selection
* caret point.
*
* @see mx.controls.listClasses.ListBase#caretItemRenderer
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var caretIndex:int = -1;
//----------------------------------
// 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)
{
setColumnCount(value);
columnCountChanged = true;
invalidateProperties();
invalidateSize();
itemsSizeChanged = true;
invalidateDisplayList();
dispatchEvent(new Event("columnCountChanged"));
}
}
/**
* Internal version for setting columnCount
* without invalidation or notification.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function setColumnCount(value:int):void
{
_columnCount = value;
}
//----------------------------------
// 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)
{
setColumnWidth(value);
invalidateSize();
itemsSizeChanged = true;
invalidateDisplayList();
dispatchEvent(new Event("columnWidthChanged"));
}
}
/**
* Internal version of setting columnWidth
* without invalidation or notification.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function setColumnWidth(value:Number):void
{
_columnWidth = value;
}
//----------------------------------
// data
//----------------------------------
/**
* @private
* Storage for the data property.
*/
private var _data:Object;
[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));
}
//----------------------------------
// 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
*/
public function get dataProvider():Object
{
// if we are running a data change effect, return the true
// data provider, rather than the ModifiedCollectionView wrapper.
if (actualCollection)
return actualCollection;
return collection;
}
/**
* @private
*/
public function set dataProvider(value:Object):void
{
if (collection)
{
collection.removeEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
}
if (value is Array)
{
collection = new ArrayCollection(value as Array);
}
else if (value is ICollectionView)
{
collection = ICollectionView(value);
}
else if (value is IList)
{
collection = new ListCollectionView(IList(value));
}
else if (value is XMLList)
{
collection = new XMLListCollection(value as XMLList);
}
else if (value is XML)
{
var xl:XMLList = new XMLList();
xl += value;
collection = new XMLListCollection(xl);
}
else
{
// convert it to an array containing this one item
var tmp:Array = [];
if (value != null)
tmp.push(value);
collection = new ArrayCollection(tmp);
}
// get an iterator for the displaying rows. The CollectionView's
// main iterator is left unchanged so folks can use old DataSelector
// methods if they want to
iterator = collection.createCursor();
collectionIterator = collection.createCursor(); //IViewCursor(collection);
// trace("ListBase added change listener");
collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler, false, 0, true);
clearSelectionData();
var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
event.kind = CollectionEventKind.RESET;
collectionChangeHandler(event);
dispatchEvent(event);
itemsNeedMeasurement = true;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
}
//----------------------------------
// 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 Flex 3
*/
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.
*/
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"));
}
//----------------------------------
// 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;
//----------------------------------
// 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
{
if (_dragEnabled && !value)
{
removeEventListener(DragEvent.DRAG_START, dragStartHandler, false);
removeEventListener(DragEvent.DRAG_COMPLETE,
dragCompleteHandler, false);
}
_dragEnabled = value;
if (value)
{
addEventListener(DragEvent.DRAG_START, dragStartHandler, false,
EventPriority.DEFAULT_HANDLER);
addEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler,
false, EventPriority.DEFAULT_HANDLER);
}
}
//----------------------------------
// dragImage
//----------------------------------
/**
* Gets an instance of a class that displays the visuals
* during a drag and drop operation.
*
* @default mx.controls.listClasses.ListItemDragProxy
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get dragImage():IUIComponent
{
var image:ListItemDragProxy = new ListItemDragProxy();
image.owner = this;
image.moduleFactory = moduleFactory;
return image;
}
//----------------------------------
// dragImageOffsets
//----------------------------------
/**
* Gets the offset of the drag image for drag and drop.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get dragImageOffsets():Point
{
var pt:Point = new Point;
var n:int = listItems.length;
for (var i:int = 0; i < n; i++)
{
if (selectedData[rowInfo[i].uid])
{
pt.x = listItems[i][0].x;
pt.y = listItems[i][0].y;
}
}
return pt;
}
//----------------------------------
// 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;
}
//----------------------------------
// 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
{
if (_dropEnabled && !value)
{
removeEventListener(DragEvent.DRAG_ENTER, dragEnterHandler, false);
removeEventListener(DragEvent.DRAG_EXIT, dragExitHandler, false);
removeEventListener(DragEvent.DRAG_OVER, dragOverHandler, false);
removeEventListener(DragEvent.DRAG_DROP, dragDropHandler, false);
}
_dropEnabled = value;
if (value)
{
addEventListener(DragEvent.DRAG_ENTER, dragEnterHandler, false,
EventPriority.DEFAULT_HANDLER);
addEventListener(DragEvent.DRAG_EXIT, dragExitHandler, false,
EventPriority.DEFAULT_HANDLER);
addEventListener(DragEvent.DRAG_OVER, dragOverHandler, false,
EventPriority.DEFAULT_HANDLER);
addEventListener(DragEvent.DRAG_DROP, dragDropHandler, false,
EventPriority.DEFAULT_HANDLER);
}
}
//----------------------------------
// 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;
//----------------------------------
// 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;
//----------------------------------
// 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;
//----------------------------------
// iconField
//----------------------------------
/**
* @private
* Storage for iconField property.
*/
private var _iconField:String = "icon";
[Bindable("iconFieldChanged")]
[Inspectable(category="Data", defaultValue="")]
/**
* The name of the field in the data provider object that determines what to
* display as the icon. By default, the list class does not try to display
* icons with the text in the rows. However, by specifying an icon
* field, you can specify a graphic that is created and displayed as an
* icon in the row. This property is ignored by DataGrid.
*
* <p>The renderers will look in the data provider object for a property of
* the name supplied as the iconField. If the value of the property is a
* Class, it will instantiate that class and expect it to be an instance
* of an IFlexDisplayObject. If the value of the property is a String,
* it will look to see if a Class exists with that name in the application,
* and if it can't find one, it will also look for a property on the
* document with that name and expect that property to map to a Class.</p>
*
* @default null
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get iconField():String
{
return _iconField;
}
/**
* @private
*/
public function set iconField(value:String):void
{
_iconField = value;
itemsSizeChanged = true;
invalidateDisplayList();
dispatchEvent(new Event("iconFieldChanged"));
}
//----------------------------------
// 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 Flex 3
*/
public function get iconFunction():Function
{
return _iconFunction;
}
/**
* @private
*/
public function set iconFunction(value:Function):void
{
_iconFunction = value;
itemsSizeChanged = true;
invalidateDisplayList();
dispatchEvent(new Event("iconFunctionChanged"));
}
//----------------------------------
// itemRenderer
//----------------------------------
/**
* @private
* Storage for the itemRenderer property.
*/
private var _itemRenderer:IFactory;
[Inspectable(category="Data")]
/**
* The custom item renderer for the control.
* You can specify a drop-in, inline, or custom item renderer.
*
* <p>The default item renderer depends on the component class.
* The TileList and HorizontalList class use
* TileListItemRenderer, The List class uses ListItemRenderer.
* The DataGrid class uses DataGridItemRenderer from DataGridColumn.</p>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get itemRenderer():IFactory
{
return _itemRenderer;
}
/**
* @private
*/
public function set itemRenderer(value:IFactory):void
{
_itemRenderer = value;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
itemsSizeChanged = true;
itemsNeedMeasurement = true;
rendererChanged = true;
dispatchEvent(new Event("itemRendererChanged"));
}
//----------------------------------
// labelField
//----------------------------------
/**
* @private
* Storage for labelField property.
*/
private var _labelField:String = "label";
[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
*/
public function get labelField():String
{
return _labelField;
}
/**
* @private
*/
public function set labelField(value:String):void
{
_labelField = value;
itemsSizeChanged = true;
invalidateDisplayList();
dispatchEvent(new Event("labelFieldChanged"));
}
//----------------------------------
// labelFunction
//----------------------------------
/**
* @private
* Storage for labelFunction property.
*/
private var _labelFunction:Function;
[Bindable("labelFunctionChanged")]
[Inspectable(category="Data")]
/**
* A user-supplied function to run on each item to determine its label.
* By default, the list looks for a property named <code>label</code>
* on each data provider item and displays it.
* However, some data sets do not have a <code>label</code> property
* nor do they have another property that can be used for displaying.
* An example is a data set that has lastName and firstName fields
* but you want to display full names.
*
* <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>For most components, 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>
*
* <p>The method signature for the DataGrid and DataGridColumn classes is:</p>
* <pre>
* myLabelFunction(item:Object, column:DataGridColumn):String</pre>
*
* <p>where <code>item</code> contains the DataGrid item object, and
* <code>column</code> specifies the DataGrid column.</p>
*
* @default null
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get labelFunction():Function
{
return _labelFunction;
}
/**
* @private
*/
public function set labelFunction(value:Function):void
{
_labelFunction = value;
itemsSizeChanged = true;
invalidateDisplayList();
dispatchEvent(new Event("labelFunctionChanged"));
}
//----------------------------------
// 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;
}
//----------------------------------
// menuSelectionMode
//----------------------------------
/**
* A flag that indicates whether menu-style selection
* should be used.
* In a Menu, dragging from
* one renderer into another selects the new one
* and un-selects the old.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var menuSelectionMode:Boolean = false;
//----------------------------------
// offscreenExtraRowsOrColumns
//----------------------------------
/**
* @private
* Storage for offscreenExtraRowsOrColumns property
*/
private var _offscreenExtraRowsOrColumns:int = 0;
/**
* A flag indicating that the number of offscreen rows or columns
* may have changed.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var offscreenExtraRowsOrColumnsChanged:Boolean = false;
/**
* The target number of extra rows or columns of item renderers to be used
* in the layout of the control. Half of these rows/columns are created
* above or to the left of the visible onscreen rows/columns;
* half are created below or to the right.
*
* <p>Whether rows or columns are created is dependent on the control and its
* properties. Generally rows will be used, except for TileBase components
* where <code>direction</code> is set to <code>TileBaseDirection.VERTICAL</code>.
* In that case, columns are created.</p>
*
* <p>You set this property to a non-zero value primarily
* when applying data effects to the List or TileList controls.
* Changes that affect
* the data provider element corresponding to the currently visible items, or
* changes that affect the data provider element for the specified number of
* items before or after the visible items, trigger the data effect.
* Data provider elements outside this range may not be
* animated perfectly by the data effect.</p>
*
* <p>This property is useful because data effects work by first determining
* a 'before' layout of the list-based control, then determining an 'after' layout,
* and finally setting the properties of the effect to create an animation
* from the before layout to the after layout.
* Since many effects cause currently invisible items to become visible,
* or currently visible items to become invisible, this property configures the control
* to create the offscreen item renderers so that they already exist when the data effect plays. </p>
*
* <p>A reasonable value for this property might be the number
* of rows visible onscreen. Setting it to a very large value may
* cause performance problems when used with a data provider that contains
* a large number of elements.</p>
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get offscreenExtraRowsOrColumns():int
{
return _offscreenExtraRowsOrColumns;
}
public function set offscreenExtraRowsOrColumns(value:int):void
{
value = Math.max(value, 0);
// round up to even number
if (value % 2)
value++;
if (_offscreenExtraRowsOrColumns == value)
return;
_offscreenExtraRowsOrColumns = value;
offscreenExtraRowsOrColumnsChanged = true;
invalidateProperties();
}
//----------------------------------
// nullItemRenderer
//----------------------------------
/**
* @private
* Storage for the nullItemRenderer property.
*/
private var _nullItemRenderer:IFactory;
[Inspectable(category="Data")]
/**
* The custom item renderer for the control.
* You can specify a drop-in, inline, or custom item renderer.
*
* <p>The default item renderer depends on the component class.
* The TileList and HorizontalList class use
* TileListItemRenderer, The List class uses ListItemRenderer.
* The DataGrid class uses DataGridItemRenderer from DataGridColumn.</p>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get nullItemRenderer():IFactory
{
return _nullItemRenderer;
}
/**
* @private
*/
public function set nullItemRenderer(value:IFactory):void
{
_nullItemRenderer = value;
invalidateSize();
invalidateDisplayList();
itemsSizeChanged = true;
rendererChanged = true;
dispatchEvent(new Event("nullItemRendererChanged"));
}
//----------------------------------
// 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;
}
//----------------------------------
// 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
*/
public function set rowHeight(value:Number):void
{
explicitRowHeight = value;
if (_rowHeight != value)
{
setRowHeight(value);
invalidateSize();
itemsSizeChanged = true;
invalidateDisplayList();
dispatchEvent(new Event("rowHeightChanged"));
}
}
/**
* Sets the <code>rowHeight</code> property without causing invalidation or
* setting of <code>explicitRowHeight</code> which
* permanently locks in the height of the rows.
*
* @param v The row height, in pixels.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function setRowHeight(v:Number):void
{
_rowHeight = v;
}
//----------------------------------
// selectable
//----------------------------------
/**
* @private
* Storage for the selectable property.
*/
private var _selectable:Boolean = true;
[Inspectable(defaultValue="true")]
/**
* A flag that indicates whether the list shows selected items
* as selected.
* If <code>true</code>, the control supports selection.
* The Menu class, which subclasses ListBase, sets this property to
* <code>false</code> by default, because it doesn't show the chosen
* menu item as selected.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get selectable():Boolean
{
return _selectable;
}
/**
* @private
*/
public function set selectable(value:Boolean):void
{
_selectable = value;
}
//----------------------------------
// selectedIndex
//----------------------------------
/**
* @private
* Storage for the selectedIndex property.
*/
mx_internal var _selectedIndex:int = -1;
[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
*/
public function get selectedIndex():int
{
return _selectedIndex;
}
/**
* @private
*/
public function set selectedIndex(value:int):void
{
if (!collection || collection.length == 0)
{
_selectedIndex = value;
bSelectionChanged = true;
bSelectedIndexChanged = true;
invalidateDisplayList();
return;
}
commitSelectedIndex(value);
}
//----------------------------------
// selectedIndices
//----------------------------------
private var _selectedIndices:Array;
[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
{
if (bSelectedIndicesChanged)
return _selectedIndices;
return copySelectedItems(false);
}
/**
* @private
*/
public function set selectedIndices(indices:Array):void
{
// trace("queueing indices");
if (!collection || collection.length == 0)
{
_selectedIndices = indices;
bSelectedIndicesChanged = true;
bSelectionChanged = true;
invalidateDisplayList();
return;
}
commitSelectedIndices(indices);
}
//----------------------------------
// selectedItem
//----------------------------------
/**
* @private
* Storage for the selectedItem property.
*/
private var _selectedItem:Object;
[Bindable("change")]
[Bindable("valueCommit")]
[Inspectable(category="General", defaultValue="null")]
/**
* A reference to the selected item in the data provider.
*
* @default null
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get selectedItem():Object
{
return _selectedItem;
}
/**
* @private
*/
public function set selectedItem(data:Object):void
{
if (!collection || collection.length == 0)
{
_selectedItem = data;
bSelectedItemChanged = true;
bSelectionChanged = true;
invalidateDisplayList();
return;
}
commitSelectedItem(data);
}
//----------------------------------
// selectedItems
//----------------------------------
private var _selectedItems:Array;
[Bindable("change")]
[Bindable("valueCommit")]
[Inspectable(category="General")]
/**
* 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
{
return bSelectedItemsChanged ? _selectedItems : copySelectedItems();
}
/**
* @private
*/
public function set selectedItems(items:Array):void
{
if (!collection || collection.length == 0)
{
_selectedItems = items;
bSelectedItemsChanged = true;
bSelectionChanged = true;
invalidateDisplayList();
return;
}
commitSelectedItems(items);
}
//----------------------------------
// selectedItemsCompareFunction
//----------------------------------
/**
* @private
* Storage for labelFunction property.
*/
private var _selectedItemsCompareFunction:Function;
[Bindable("selectedItemsCompareFunctionChanged")]
[Inspectable(category="Data")]
/**
* A function used to compare items in the <code>selectedItems</code> property
* against items in the data provider.
* If there is a match, the item in the data provider
* becomes part of the selection.
* By default, or if <code>selectedItemsCompareFunction</code> is set to <code>null</code>,
* the default comparision function is used, which uses
* strict equality (===).
* Note that earlier releases of
* Flex used simple equality (==) so there could be behavioral
* differences in certain cases.
* A common compare function might simply compare UIDs of objects
* or test that a particular property matches.
*
* <p>The compare function takes two arguments.
* The first argument is the object in the data provider.
* The second argument is an object in <code>selectedItems</code> property.
* The function returns <code>true</code> if the data provider item should be selected.</p>
*
* <pre>
* myCompareFunction(itemInDataProvider:Object, itemInSelectedItems):Boolean</pre>
*
* <p>The default value is <code>null</code>, which uses strict equality.</p>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get selectedItemsCompareFunction():Function
{
return _selectedItemsCompareFunction;
}
/**
* @private
*/
public function set selectedItemsCompareFunction(value:Function):void
{
_selectedItemsCompareFunction = value;
dispatchEvent(new Event("selectedItemsCompareFunctionChanged"));
}
//----------------------------------
// 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"));
}
//----------------------------------
// value
//----------------------------------
[Bindable("change")]
[Bindable("valueCommit")]
/**
* The selected item, or the data or label field of the selected item.
* If the selected item is a Number or String
* the value is the item. If the item is an object, the value is
* the data property if it exists, or the label property if it exists.
*
* <p>Note: Using <code>selectedItem</code> is often preferable. This
* property exists for backward compatibility with older applications.</p>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get value():Object
{
var item:Object = selectedItem;
if (!item)
return null;
if (typeof(item) != "object")
return item;
return item.data != null ? item.data : item.label;
}
//----------------------------------
// variableRowHeight
//----------------------------------