scaffold.libs_as.feathers.controls.List.as Maven / Gradle / Ivy
/*
Feathers
Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved.
This program is free software. You can redistribute and/or modify it in
accordance with the terms of the accompanying license agreement.
*/
package feathers.controls
{
import feathers.controls.renderers.DefaultListItemRenderer;
import feathers.controls.renderers.IListItemRenderer;
import feathers.controls.supportClasses.ListDataViewPort;
import feathers.core.IFocusContainer;
import feathers.core.PropertyProxy;
import feathers.data.ListCollection;
import feathers.events.CollectionEventType;
import feathers.layout.HorizontalAlign;
import feathers.layout.ILayout;
import feathers.layout.ISpinnerLayout;
import feathers.layout.IVariableVirtualLayout;
import feathers.layout.VerticalAlign;
import feathers.layout.VerticalLayout;
import feathers.skins.IStyleProvider;
import flash.geom.Point;
import flash.ui.Keyboard;
import starling.events.Event;
import starling.events.KeyboardEvent;
/**
* Dispatched when the selected item changes.
*
* The properties of the event object have the following values:
*
* Property Value
* bubbles
false
* currentTarget
The Object that defines the
* event listener that handles the event. For example, if you use
* myButton.addEventListener()
to register an event listener,
* myButton is the value of the currentTarget
.
* data
null
* target
The Object that dispatched the event;
* it is not always the Object listening for the event. Use the
* currentTarget
property to always access the Object
* listening for the event.
*
*
* @eventType starling.events.Event.CHANGE
*/
[Event(name="change",type="starling.events.Event")]
/**
* Dispatched when the the user taps or clicks an item renderer in the list.
* The touch must remain within the bounds of the item renderer on release,
* and the list must not have scrolled, to register as a tap or a click.
*
* The properties of the event object have the following values:
*
* Property Value
* bubbles
false
* currentTarget
The Object that defines the
* event listener that handles the event. For example, if you use
* myButton.addEventListener()
to register an event listener,
* myButton is the value of the currentTarget
.
* data
The item associated with the item
* renderer that was triggered.
* target
The Object that dispatched the event;
* it is not always the Object listening for the event. Use the
* currentTarget
property to always access the Object
* listening for the event.
*
*
* @eventType starling.events.Event.TRIGGERED
*/
[Event(name="triggered",type="starling.events.Event")]
/**
* Dispatched when an item renderer is added to the list. When the layout is
* virtualized, item renderers may not exist for every item in the data
* provider. This event can be used to track which items currently have
* renderers.
*
* The properties of the event object have the following values:
*
* Property Value
* bubbles
false
* currentTarget
The Object that defines the
* event listener that handles the event. For example, if you use
* myButton.addEventListener()
to register an event listener,
* myButton is the value of the currentTarget
.
* data
The item renderer that was added.
* target
The Object that dispatched the event;
* it is not always the Object listening for the event. Use the
* currentTarget
property to always access the Object
* listening for the event.
*
*
* @eventType feathers.events.FeathersEventType.RENDERER_ADD
*/
[Event(name="rendererAdd",type="starling.events.Event")]
/**
* Dispatched when an item renderer is removed from the list. When the layout is
* virtualized, item renderers may not exist for every item in the data
* provider. This event can be used to track which items currently have
* renderers.
*
* The properties of the event object have the following values:
*
* Property Value
* bubbles
false
* currentTarget
The Object that defines the
* event listener that handles the event. For example, if you use
* myButton.addEventListener()
to register an event listener,
* myButton is the value of the currentTarget
.
* data
The item renderer that was removed.
* target
The Object that dispatched the event;
* it is not always the Object listening for the event. Use the
* currentTarget
property to always access the Object
* listening for the event.
*
*
* @eventType feathers.events.FeathersEventType.RENDERER_REMOVE
*/
[Event(name="rendererRemove",type="starling.events.Event")]
/**
* Displays a one-dimensional list of items. Supports scrolling, custom
* item renderers, and custom layouts.
*
* Layouts may be, and are highly encouraged to be, virtual,
* meaning that the List is capable of creating a limited number of item
* renderers to display a subset of the data provider instead of creating a
* renderer for every single item. This allows for optimal performance with
* very large data providers.
*
* The following example creates a list, gives it a data provider, tells
* the item renderer how to interpret the data, and listens for when the
* selection changes:
*
*
* var list:List = new List();
*
* list.dataProvider = new ListCollection(
* [
* { text: "Milk", thumbnail: textureAtlas.getTexture( "milk" ) },
* { text: "Eggs", thumbnail: textureAtlas.getTexture( "eggs" ) },
* { text: "Bread", thumbnail: textureAtlas.getTexture( "bread" ) },
* { text: "Chicken", thumbnail: textureAtlas.getTexture( "chicken" ) },
* ]);
*
* list.itemRendererFactory = function():IListItemRenderer
* {
* var renderer:DefaultListItemRenderer = new DefaultListItemRenderer();
* renderer.labelField = "text";
* renderer.iconSourceField = "thumbnail";
* return renderer;
* };
*
* list.addEventListener( Event.CHANGE, list_changeHandler );
*
* this.addChild( list );
*
* @see ../../../help/list.html How to use the Feathers List component
* @see ../../../help/default-item-renderers.html How to use the Feathers default item renderer
* @see ../../../help/item-renderers.html Creating custom item renderers for the Feathers List and GroupedList components
* @see feathers.controls.GroupedList
* @see feathers.controls.SpinnerList
*/
public class List extends Scroller implements IFocusContainer
{
/**
* @private
*/
private static const HELPER_POINT:Point = new Point();
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollPolicy.AUTO
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_POLICY_AUTO:String = "auto";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollPolicy.ON
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_POLICY_ON:String = "on";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollPolicy.OFF
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_POLICY_OFF:String = "off";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollBarDisplayMode.FLOAT
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_BAR_DISPLAY_MODE_FLOAT:String = "float";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollBarDisplayMode.FIXED
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_BAR_DISPLAY_MODE_FIXED:String = "fixed";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollBarDisplayMode.FIXED_FLOAT
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_BAR_DISPLAY_MODE_FIXED_FLOAT:String = "fixedFloat";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollBarDisplayMode.NONE
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const SCROLL_BAR_DISPLAY_MODE_NONE:String = "none";
/**
* @private
* DEPRECATED: Replaced by feathers.layout.RelativePosition.RIGHT
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const VERTICAL_SCROLL_BAR_POSITION_RIGHT:String = "right";
/**
* @private
* DEPRECATED: Replaced by feathers.layout.RelativePosition.LEFT
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const VERTICAL_SCROLL_BAR_POSITION_LEFT:String = "left";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollInteractionMode.TOUCH
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const INTERACTION_MODE_TOUCH:String = "touch";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollInteractionMode.MOUSE
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const INTERACTION_MODE_MOUSE:String = "mouse";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.ScrollInteractionMode.TOUCH_AND_SCROLL_BARS
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const INTERACTION_MODE_TOUCH_AND_SCROLL_BARS:String = "touchAndScrollBars";
/**
* @private
* DEPRECATED: Replaced by feathers.layout.Direction.VERTICAL
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const MOUSE_WHEEL_SCROLL_DIRECTION_VERTICAL:String = "vertical";
/**
* @private
* DEPRECATED: Replaced by feathers.layout.Direction.HORIZONTAL
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const MOUSE_WHEEL_SCROLL_DIRECTION_HORIZONTAL:String = "horizontal";
/**
* @private
* DEPRECATED: Replaced by feathers.controls.DecelerationRate.NORMAL
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const DECELERATION_RATE_NORMAL:Number = 0.998;
/**
* @private
* DEPRECATED: Replaced by feathers.controls.DecelerationRate.FAST
.
*
* DEPRECATION WARNING: This constant is deprecated
* starting with Feathers 3.0. It will be removed in a future version of
* Feathers according to the standard
* Feathers deprecation policy.
*/
public static const DECELERATION_RATE_FAST:Number = 0.99;
/**
* The default IStyleProvider
for all List
* components.
*
* @default null
* @see feathers.core.FeathersControl#styleProvider
*/
public static var globalStyleProvider:IStyleProvider;
/**
* Constructor.
*/
public function List()
{
super();
this._selectedIndices.addEventListener(Event.CHANGE, selectedIndices_changeHandler);
}
/**
* @private
* The guts of the List's functionality. Handles layout and selection.
*/
protected var dataViewPort:ListDataViewPort;
/**
* @private
*/
override protected function get defaultStyleProvider():IStyleProvider
{
return List.globalStyleProvider;
}
/**
* @private
*/
override public function get isFocusEnabled():Boolean
{
return (this._isSelectable || this._minHorizontalScrollPosition != this._maxHorizontalScrollPosition ||
this._minVerticalScrollPosition != this._maxVerticalScrollPosition) &&
this._isEnabled && this._isFocusEnabled;
}
/**
* @private
*/
protected var _isChildFocusEnabled:Boolean = true;
/**
* @copy feathers.core.IFocusContainer#isChildFocusEnabled
*
* @default true
*
* @see #isFocusEnabled
*/
public function get isChildFocusEnabled():Boolean
{
return this._isEnabled && this._isChildFocusEnabled;
}
/**
* @private
*/
public function set isChildFocusEnabled(value:Boolean):void
{
this._isChildFocusEnabled = value;
}
/**
* @private
*/
protected var _layout:ILayout;
/**
* The layout algorithm used to position and, optionally, size the
* list's items.
*
* By default, if no layout is provided by the time that the list
* initializes, a vertical layout with options targeted at touch screens
* is created.
*
* The following example tells the list to use a horizontal layout:
*
*
* var layout:HorizontalLayout = new HorizontalLayout();
* layout.gap = 20;
* layout.padding = 20;
* list.layout = layout;
*
* @default null
*/
public function get layout():ILayout
{
return this._layout;
}
/**
* @private
*/
public function set layout(value:ILayout):void
{
if(this._layout == value)
{
return;
}
if(!(this is SpinnerList) && value is ISpinnerLayout)
{
throw new ArgumentError("Layouts that implement the ISpinnerLayout interface should be used with the SpinnerList component.");
}
if(this._layout)
{
this._layout.removeEventListener(Event.SCROLL, layout_scrollHandler);
}
this._layout = value;
if(this._layout is IVariableVirtualLayout)
{
this._layout.addEventListener(Event.SCROLL, layout_scrollHandler);
}
this.invalidate(INVALIDATION_FLAG_LAYOUT);
}
/**
* @private
*/
protected var _dataProvider:ListCollection;
/**
* The collection of data displayed by the list. Changing this property
* to a new value is considered a drastic change to the list's data, so
* the horizontal and vertical scroll positions will be reset, and the
* list's selection will be cleared.
*
* The following example passes in a data provider and tells the item
* renderer how to interpret the data:
*
*
* list.dataProvider = new ListCollection(
* [
* { text: "Milk", thumbnail: textureAtlas.getTexture( "milk" ) },
* { text: "Eggs", thumbnail: textureAtlas.getTexture( "eggs" ) },
* { text: "Bread", thumbnail: textureAtlas.getTexture( "bread" ) },
* { text: "Chicken", thumbnail: textureAtlas.getTexture( "chicken" ) },
* ]);
*
* list.itemRendererFactory = function():IListItemRenderer
* {
* var renderer:DefaultListItemRenderer = new DefaultListItemRenderer();
* renderer.labelField = "text";
* renderer.iconSourceField = "thumbnail";
* return renderer;
* };
*
* Warning: A list's data provider cannot contain duplicate
* items. To display the same item in multiple item renderers, you must
* create separate objects with the same properties. This limitation
* exists because it significantly improves performance.
*
* Warning: If the data provider contains display objects,
* concrete textures, or anything that needs to be disposed, those
* objects will not be automatically disposed when the list is disposed.
* Similar to how starling.display.Image
cannot
* automatically dispose its texture because the texture may be used
* by other display objects, a list cannot dispose its data provider
* because the data provider may be used by other lists. See the
* dispose()
function on ListCollection
to
* see how the data provider can be disposed properly.
*
* @default null
*
* @see feathers.data.ListCollection#dispose()
*/
public function get dataProvider():ListCollection
{
return this._dataProvider;
}
/**
* @private
*/
public function set dataProvider(value:ListCollection):void
{
if(this._dataProvider == value)
{
return;
}
if(this._dataProvider)
{
this._dataProvider.removeEventListener(CollectionEventType.ADD_ITEM, dataProvider_addItemHandler);
this._dataProvider.removeEventListener(CollectionEventType.REMOVE_ITEM, dataProvider_removeItemHandler);
this._dataProvider.removeEventListener(CollectionEventType.REPLACE_ITEM, dataProvider_replaceItemHandler);
this._dataProvider.removeEventListener(CollectionEventType.RESET, dataProvider_resetHandler);
this._dataProvider.removeEventListener(Event.CHANGE, dataProvider_changeHandler);
}
this._dataProvider = value;
if(this._dataProvider)
{
this._dataProvider.addEventListener(CollectionEventType.ADD_ITEM, dataProvider_addItemHandler);
this._dataProvider.addEventListener(CollectionEventType.REMOVE_ITEM, dataProvider_removeItemHandler);
this._dataProvider.addEventListener(CollectionEventType.REPLACE_ITEM, dataProvider_replaceItemHandler);
this._dataProvider.addEventListener(CollectionEventType.RESET, dataProvider_resetHandler);
this._dataProvider.addEventListener(Event.CHANGE, dataProvider_changeHandler);
}
//reset the scroll position because this is a drastic change and
//the data is probably completely different
this.horizontalScrollPosition = 0;
this.verticalScrollPosition = 0;
//clear the selection for the same reason
this.selectedIndex = -1;
this.invalidate(INVALIDATION_FLAG_DATA);
}
/**
* @private
*/
protected var _isSelectable:Boolean = true;
/**
* Determines if items in the list may be selected. By default only a
* single item may be selected at any given time. In other words, if
* item A is selected, and the user selects item B, item A will be
* deselected automatically. Set allowMultipleSelection
* to true
to select more than one item without
* automatically deselecting other items.
*
* The following example disables selection:
*
*
* list.isSelectable = false;
*
* @default true
*
* @see #allowMultipleSelection
*/
public function get isSelectable():Boolean
{
return this._isSelectable;
}
/**
* @private
*/
public function set isSelectable(value:Boolean):void
{
if(this._isSelectable == value)
{
return;
}
this._isSelectable = value;
if(!this._isSelectable)
{
this.selectedIndex = -1;
}
this.invalidate(INVALIDATION_FLAG_SELECTED);
}
/**
* @private
*/
protected var _selectedIndex:int = -1;
/**
* The index of the currently selected item. Returns -1
if
* no item is selected.
*
* The following example selects an item by its index:
*
*
* list.selectedIndex = 2;
*
* The following example clears the selected index:
*
*
* list.selectedIndex = -1;
*
* The following example listens for when selection changes and
* requests the selected index:
*
*
* function list_changeHandler( event:Event ):void
* {
* var list:List = List( event.currentTarget );
* var index:int = list.selectedIndex;
*
* }
* list.addEventListener( Event.CHANGE, list_changeHandler );
*
* @default -1
*
* @see #selectedItem
* @see #allowMultipleSelection
* @see #selectedItems
* @see #selectedIndices
*/
public function get selectedIndex():int
{
return this._selectedIndex;
}
/**
* @private
*/
public function set selectedIndex(value:int):void
{
if(this._selectedIndex == value)
{
return;
}
if(value >= 0)
{
this._selectedIndices.data = new [value];
}
else
{
this._selectedIndices.removeAll();
}
this.invalidate(INVALIDATION_FLAG_SELECTED);
}
/**
* The currently selected item. Returns null
if no item is
* selected.
*
* The following example changes the selected item:
*
*
* list.selectedItem = list.dataProvider.getItemAt(0);
*
* The following example clears the selected item:
*
*
* list.selectedItem = null;
*
* The following example listens for when selection changes and
* requests the selected item:
*
*
* function list_changeHandler( event:Event ):void
* {
* var list:List = List( event.currentTarget );
* var item:Object = list.selectedItem;
*
* }
* list.addEventListener( Event.CHANGE, list_changeHandler );
*
* @default null
*
* @see #selectedIndex
* @see #allowMultipleSelection
* @see #selectedItems
* @see #selectedIndices
*/
public function get selectedItem():Object
{
if(!this._dataProvider || this._selectedIndex < 0 || this._selectedIndex >= this._dataProvider.length)
{
return null;
}
return this._dataProvider.getItemAt(this._selectedIndex);
}
/**
* @private
*/
public function set selectedItem(value:Object):void
{
if(!this._dataProvider)
{
this.selectedIndex = -1;
return;
}
this.selectedIndex = this._dataProvider.getItemIndex(value);
}
/**
* @private
*/
protected var _allowMultipleSelection:Boolean = false;
/**
* If true
multiple items may be selected at a time. If
* false
, then only a single item may be selected at a
* time, and if the selection changes, other items are deselected. Has
* no effect if isSelectable
is false
.
*
* In the following example, multiple selection is enabled:
*
*
* list.allowMultipleSelection = true;
*
* @default false
*
* @see #isSelectable
* @see #selectedIndices
* @see #selectedItems
*/
public function get allowMultipleSelection():Boolean
{
return this._allowMultipleSelection;
}
/**
* @private
*/
public function set allowMultipleSelection(value:Boolean):void
{
if(this._allowMultipleSelection == value)
{
return;
}
this._allowMultipleSelection = value;
this.invalidate(INVALIDATION_FLAG_SELECTED);
}
/**
* @private
*/
protected var _selectedIndices:ListCollection = new ListCollection(new []);
/**
* The indices of the currently selected items. Returns an empty Vector.<int>
* if no items are selected. If allowMultipleSelection
is
* false
, only one item may be selected at a time.
*
* The following example selects two items by their indices:
*
*
* list.selectedIndices = new <int>[ 2, 3 ];
*
* The following example clears the selected indices:
*
*
* list.selectedIndices = null;
*
* The following example listens for when selection changes and
* requests the selected indices:
*
*
* function list_changeHandler( event:Event ):void
* {
* var list:List = List( event.currentTarget );
* var indices:Vector.<int> = list.selectedIndices;
*
* }
* list.addEventListener( Event.CHANGE, list_changeHandler );
*
* @see #allowMultipleSelection
* @see #selectedItems
* @see #selectedIndex
* @see #selectedItem
*/
public function get selectedIndices():Vector.
{
return this._selectedIndices.data as Vector.;
}
/**
* @private
*/
public function set selectedIndices(value:Vector.):void
{
var oldValue:Vector. = this._selectedIndices.data as Vector.;
if(oldValue == value)
{
return;
}
if(!value)
{
if(this._selectedIndices.length == 0)
{
return;
}
this._selectedIndices.removeAll();
}
else
{
if(!this._allowMultipleSelection && value.length > 0)
{
value.length = 1;
}
this._selectedIndices.data = value;
}
this.invalidate(INVALIDATION_FLAG_SELECTED);
}
/**
* The currently selected item. The getter returns an empty
* Vector.<Object>
if no item is selected. If any
* items are selected, the getter creates a new
* Vector.<Object>
to return a list of selected
* items.
*
* The following example selects two items:
*
*
* list.selectedItems = new <Object>[ list.dataProvider.getItemAt(2) , list.dataProvider.getItemAt(3) ];
*
* The following example clears the selected items:
*
*
* list.selectedItems = null;
*
* The following example listens for when selection changes and
* requests the selected items:
*
*
* function list_changeHandler( event:Event ):void
* {
* var list:List = List( event.currentTarget );
* var items:Vector.<Object> = list.selectedItems;
*
* }
* list.addEventListener( Event.CHANGE, list_changeHandler );
*
* @see #allowMultipleSelection
* @see #selectedIndices
* @see #selectedIndex
* @see #selectedItem
*/
public function get selectedItems():Vector.