// Copyright 2007. Adobe Systems Incorporated. All Rights Reserved. package fl.controls { import fl.controls.listClasses.CellRenderer; import fl.controls.listClasses.ICellRenderer; import fl.controls.listClasses.ImageCell; import fl.controls.listClasses.ListData; import fl.controls.listClasses.student_ar_fl_controls_TileListData; import fl.controls.ScrollBar; import fl.controls.ScrollBarDirection; import fl.controls.ScrollPolicy; import fl.controls.SelectableList; import fl.core.InvalidationType; import fl.core.UIComponent; import fl.data.DataProvider; import fl.data.student_ar_fl_controls_TileListCollectionItem; import fl.events.DataChangeEvent; import fl.events.DataChangeType; import fl.events.ListEvent; import fl.events.ScrollEvent; import fl.managers.IFocusManagerComponent; import flash.display.DisplayObject; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.Event; import flash.events.KeyboardEvent; import flash.ui.Keyboard; import flash.utils.Dictionary; //-------------------------------------- // Events //-------------------------------------- //-------------------------------------- // Styles //-------------------------------------- /** * The skin to be used as the background of the student_ar_fl_controls_TileList component. * * @default student_ar_fl_controls_TileList_skin * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="skin", type="Class")] /** * The cell renderer to be used to render each item in the student_ar_fl_controls_TileList component. * * @default fl.contols.listClasses.ImageCell * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="cellRenderer", type="Class")] //-------------------------------------- // Class description //-------------------------------------- /** * The student_ar_fl_controls_TileList class provides a grid of rows and columns that is typically used * to format and display images in a "tiled" format. The default cell renderer for * this component is the ImageCell class. An ImageCell cell renderer displays a * thumbnail image and a single-line label. To render a list-based cell in a * student_ar_fl_controls_TileList component, use the CellRenderer class. * *
To modify the padding that separates the cell border from the image, you
* can globally set the imagePadding
style, or set it on the ImageCell
* class. Like other cell styles, the imagePadding
style cannot be
* set on the student_ar_fl_controls_TileList component instance.
Note: The labelField
is not used if
* the labelFunction
property is set to a callback function.
Note: The labelField
is not used if
* the labelFunction
property is set to a callback function.
Note: The iconField
is not used
* if the iconFunction
property is set to a callback function.
Icons can be classes or they can be symbols from the library that have a class name.
* * @default null * * @includeExample examples/student_ar_fl_controls_TileList.iconField.1.as -noswf * * @see #iconFunction * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get iconField():String { return _iconField; } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set iconField(value:String):void { if (value == _iconField) { return; } _iconField = value; invalidate(InvalidationType.DATA); } /** * Gets or sets the function to be used to obtain the icon for the item. * *Note: The iconField
is not used if the
* iconFunction
property is set to a callback function.
Icons can be classes, or they can be library items that have class names.
* * @default null * * @includeExample examples/student_ar_fl_controls_TileList.iconFunction.1.as -noswf * * @see #iconField * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get iconFunction():Function { return _iconFunction; } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set iconFunction(value:Function):void { if (_iconFunction == value) { return; } _iconFunction = value; invalidate(InvalidationType.DATA); } /** * Gets or sets the item field that provides the source path for a tile. * *Note: The sourceField
is not used if the
* sourceFunction
property is set to a callback function.
Note: The sourceField
is not used if the
* sourceFunction
property is set to a callback function.
Setting the rowCount
property changes the height of the
* list, but the student_ar_fl_controls_TileList component does not maintain this value. It
* is important to set the rowCount
value after setting the
* dataProvider
and rowHeight
values. The only
* exception is if the rowCount
is set with the Property
* inspector; in this case, the property is maintained until the component
* is first drawn.
columnCount
property changes the width of the list,
* but the student_ar_fl_controls_TileList component does not maintain this value. It is important to set the
* columnCount
value after setting the dataProvider
* and rowHeight
values. The only exception is if the rowCount
* is set with the Property inspector; in this case, the property is maintained until the
* component is first drawn.
*
* @default 0
*
* @includeExample examples/student_ar_fl_controls_TileList.columnCount.1.as -noswf
*
* @see #rowCount
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function get columnCount():uint {
var pad:Number = Number(getStyleValue("contentPadding"));
var cols:uint = Math.max(1,(_width-2*pad)/_columnWidth<<0);
var rows:uint = Math.max(1,(_height-2*pad)/_rowHeight<<0);
if (_scrollDirection != ScrollBarDirection.HORIZONTAL) {
if (_scrollPolicy == ScrollPolicy.ON || (_scrollPolicy == ScrollPolicy.AUTO && length > cols*rows)) {
// account for vertical scrollbar:
cols = Math.max(1,(_width-2*pad-15)/_columnWidth<<0);
}
// else we just use the default cols value from above.
} else {
// we might have a partial column visible:
cols = Math.max(1,Math.ceil((_width-2*pad)/_columnWidth));
}
return cols;
}
/**
* @private (setter)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function set columnCount(value:uint):void {
if (value == 0) { return; }
if (componentInspectorSetting) {
__columnCount = value;
return;
}
__columnCount = 0;
var pad:Number = Number(getStyleValue("contentPadding"));
var showScroll:Boolean = (Math.ceil(length/value) > (height/rowHeight)>>0 && _scrollPolicy == ScrollPolicy.AUTO) || _scrollPolicy == ScrollPolicy.ON;
width = columnWidth*value+2*pad+(_scrollDirection == ScrollBarDirection.VERTICAL && showScroll ? 15 : 0);
}
[Inspectable(defaultValue=50)]
/**
* Gets or sets the width that is applied to a column in the list, in pixels.
*
* @default 50
*
* @includeExample examples/student_ar_fl_controls_TileList.columnWidth.1.as -noswf
*
* @see #rowHeight
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function get columnWidth():Number {
return _columnWidth;
}
/**
* @private (setter)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function set columnWidth(value:Number):void {
if (_columnWidth == value) { return; }
_columnWidth = value;
invalidate(InvalidationType.SIZE);
}
/**
* Gets the width of the content area, in pixels. This value is the component width
* minus the combined width of the contentPadding
value and vertical scroll bar,
* if the vertical scroll bar is visible.
*
* @includeExample examples/student_ar_fl_controls_TileList.innerWidth.1.as -noswf
*
* @see #innerHeight
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function get innerWidth():Number {
drawNow();
var contentPadding:Number = getStyleValue("contentPadding") as Number;
return width - contentPadding*2 - (_verticalScrollBar.visible ? _verticalScrollBar.width : 0);
}
/**
* Gets the height of the content area, in pixels. This value is the component height
* minus the combined height of the contentPadding
value and horizontal
* scroll bar height, if the horizontal scroll bar is visible.
*
* @see #innerWidth
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function get innerHeight():Number {
drawNow();
var contentPadding:Number = getStyleValue("contentPadding") as Number;
return height - contentPadding*2 - (_horizontalScrollBar.visible ? _horizontalScrollBar.height : 0);
}
[Inspectable(enumeration="horizontal,vertical", defaultValue="horizontal")]
/**
* Gets or sets a value that indicates whether the student_ar_fl_controls_TileList component scrolls
* horizontally or vertically. A value of ScrollBarDirection.HORIZONTAL
* indicates that the student_ar_fl_controls_TileList component scrolls horizontally; a value of
* ScrollBarDirection.VERTICAL
indicates that the student_ar_fl_controls_TileList component scrolls vertically.
*
* @default ScrollBarDirection.VERTICAL
*
* @includeExample examples/student_ar_fl_controls_TileList.direction.1.as -noswf
*
* @see ScrollBarDirection
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function get direction():String {
return _scrollDirection;
}
/**
* @private (setter)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function set direction(value:String):void {
if (_scrollDirection == value) { return; }
_scrollDirection = value;
invalidate(InvalidationType.SIZE);
}
[Inspectable(enumeration="auto,on,off", defaultValue="auto")]
/**
* Gets or sets the scroll policy for the student_ar_fl_controls_TileList component. This
* value is used to specify the scroll policy for the scroll bar that
* is set by the direction
property.
*
* Note: The student_ar_fl_controls_TileList component supports scrolling only in * one direction. Tiles are adjusted to fit into the viewable area of * the component, so that tiles are hidden in only one direction.
* *The student_ar_fl_controls_TileList component resizes to fit tiles only when the user
* manually sets the size or when the user sets the rowCount
* or columnCount
properties.
When this value is set to ScrollPolicy.AUTO
, the
* scroll bar is visible only when the student_ar_fl_controls_TileList component must scroll
* to show all the items.
labelField
and labelFunction
properties.
*
* @param item The Object to be rendered.
*
* @return The string to be displayed based on the data.
*
* @internal var label:String = mystudent_ar_fl_controls_TileList.itemToLabel(data);
*
* @see #labelField
* @see #labelFunction
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override public function itemToLabel(item:Object):String {
if (_labelFunction != null) {
return String(_labelFunction(item));
} else {
if (item[_labelField] == null) { return ""; }
return String(item[_labelField]);
}
}
// Hide these from the Property inspector and from users.
/**
* @private (hidden)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override public function get verticalScrollPolicy():String {
return null;
}
/**
* @private (setter)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override public function set verticalScrollPolicy(value:String):void {}
/**
* @private (hidden)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override public function get horizontalScrollPolicy():String {
return null;
}
/**
* @private (setter)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override public function set horizontalScrollPolicy(value:String):void {}
/**
* Gets the maximum horizontal scroll position for the current content, in pixels.
*
* @see fl.containers.BaseScrollPane#horizontalScrollPosition
* @see fl.containers.BaseScrollPane#maxVerticalScrollPosition
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override public function get maxHorizontalScrollPosition():Number {
drawNow();
return _maxHorizontalScrollPosition;
}
/**
* @private (setter)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override public function set maxHorizontalScrollPosition(value:Number):void {}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function configUI():void {
super.configUI();
_horizontalScrollPolicy = scrollPolicy;
_verticalScrollPolicy = ScrollPolicy.OFF;
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function setHorizontalScrollPosition(scroll:Number,fireEvent:Boolean=false):void {
invalidate(InvalidationType.SCROLL);
super.setHorizontalScrollPosition(scroll, true);
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function setVerticalScrollPosition(scroll:Number,fireEvent:Boolean=false):void {
invalidate(InvalidationType.SCROLL);
super.setVerticalScrollPosition(scroll, true);
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function draw():void {
// We need to draw the row and column count that are set by component parameters on the first draw.
if (direction == ScrollBarDirection.VERTICAL) {
if (__rowCount > 0) { rowCount = __rowCount; }
if (__columnCount > 0) { columnCount = __columnCount; }
} else {
if (__columnCount > 0) { columnCount = __columnCount; }
if (__rowCount > 0) { rowCount = __rowCount; }
}
var lengthChanged:Boolean = (oldLength != length);
oldLength = length;
if (isInvalid(InvalidationType.STYLES)) {
setStyles();
drawBackground();
// drawLayout is expensive, so only do it if padding has changed:
if (contentPadding != getStyleValue("contentPadding")) {
invalidate(InvalidationType.SIZE,false);
}
// redrawing all the cell renderers is even more expensive, so we really only want to do it if necessary:
if (_cellRenderer != getStyleValue("cellRenderer")) {
// remove all the existing renderers:
_invalidateList();
_cellRenderer = getStyleValue("cellRenderer");
}
}
if (isInvalid(InvalidationType.SIZE, InvalidationType.STATE) || lengthChanged) {
drawLayout();
}
// Apply updatedStyles
if (isInvalid(InvalidationType.RENDERER_STYLES)) {
updateRendererStyles();
}
if (isInvalid(InvalidationType.STYLES,InvalidationType.SIZE,InvalidationType.DATA,InvalidationType.SCROLL,InvalidationType.SELECTED)) {
drawList();
_maxHorizontalScrollPosition = Math.max(0, contentWidth - availableWidth);
}
// Call drawNow on nested components to get around problems with nested render events:
updateChildren();
// not calling super.draw, because we're handling everything here. Instead we'll just call validate();
validate();
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function drawLayout():void {
// figure out our scrolling situation:
_horizontalScrollPolicy = (_scrollDirection == ScrollBarDirection.HORIZONTAL) ? _scrollPolicy : ScrollPolicy.OFF;
_verticalScrollPolicy = (_scrollDirection != ScrollBarDirection.HORIZONTAL) ? _scrollPolicy : ScrollPolicy.OFF;
if (_scrollDirection == ScrollBarDirection.HORIZONTAL) {
var rows:uint = rowCount;
contentHeight = rows*_rowHeight;
contentWidth = _columnWidth*Math.ceil(length/rows);
} else {
var cols:uint = columnCount;
contentWidth = cols*_columnWidth;
contentHeight = _rowHeight*Math.ceil(length/cols);
}
// hand off drawing the layout to BaseScrollPane:
super.drawLayout();
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function drawList():void {
// these vars get reused in different loops:
var i:uint;
var itemIndex:uint;
var item:Object;
var renderer:ICellRenderer;
var rows:uint = rowCount;
var cols:uint = columnCount;
var colW:Number = columnWidth;
var rowH:Number = rowHeight;
var baseCol:Number = 0;
var baseRow:Number = 0;
var col:uint;
var row:uint;
listHolder.x = listHolder.y = contentPadding;
// set horizontal scroll:
contentScrollRect = listHolder.scrollRect;
contentScrollRect.x = Math.floor(_horizontalScrollPosition)%colW;
// set pixel scroll:
contentScrollRect.y = Math.floor(_verticalScrollPosition)%rowH;
listHolder.scrollRect = contentScrollRect;
listHolder.cacheAsBitmap = useBitmapScrolling;
// figure out what we have to render, and where:
var items:Array = [];
if (_scrollDirection == ScrollBarDirection.HORIZONTAL) {
// horizontal scrolling is trickier if we want to keep tiles going left to right, then top to bottom.
// we can use availableWidth / availableHeight from BaseScrollPane here, because we've just called drawLayout, so we know they are accurate.
var fullCols:uint = availableWidth/colW<<0;
var rowLength:uint = Math.max(fullCols,Math.ceil(length/rows));
baseCol = _horizontalScrollPosition/colW<<0;
cols = Math.max(fullCols,Math.min(rowLength-baseCol,cols+1));//(horizontalScrollBar.visible ? 1 : -1))); // need to draw an extra two cols for scrolling.
//rowLength = Math.max(cols-(horizontalScrollBar.visible ? -1 : 0),rowLength);
for (row=0; rowtrue
if the shift key was held down when
* the keyboard key was pressed.
*
* @param ctrlKey true
if the ctrl key was held down when
* the keyboard key was pressed
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void {
var totalRows:uint = Math.max(1, (Math.max(contentHeight,availableHeight)/_rowHeight<<0));
var perRow:uint = Math.ceil(Math.max(columnCount*rowCount,length) / totalRows); // This is wrong.
var totalContentRows:uint = Math.ceil(length / perRow);
var index:int;
var newIndex:int;
switch (code) {
case Keyboard.UP:
index = selectedIndex - perRow; break;
case Keyboard.DOWN:
index = selectedIndex + perRow; break;
case Keyboard.HOME:
index = 0; break;
case Keyboard.END:
index = length-1; break;
case Keyboard.PAGE_DOWN:
newIndex = selectedIndex + perRow * (totalContentRows-1);
if (newIndex >= length) { newIndex -= perRow; }
index = Math.min(length-1, newIndex);
break;
case Keyboard.PAGE_UP:
newIndex = selectedIndex - perRow * (totalContentRows-1);
if (newIndex < 0) { newIndex += perRow; }
index = Math.max(0, newIndex);
break;
}
doKeySelection(index, shiftKey, ctrlKey);
scrollToSelected();
}
/**
* @private (protected)
* Moves the selection in a horizontal direction in response
* to the user selecting items using the left-arrow or right-arrow
* keys and modifiers such as the Shift and Ctrl keys.
*
* Not implemented in List because the default list * is single column and does not scroll horizontally.
* * @param code The key that was pressed (e.g. Keyboard.LEFT) * * @param shiftKeytrue
if the shift key was held down when
* the keyboard key was pressed.
*
* @param ctrlKey true
if the ctrl key was held down when
* the keyboard key was pressed
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function moveSelectionHorizontally(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void {
var totalCols:uint = Math.ceil(Math.max(rowCount*columnCount,length) / rowCount);
var index:int;
switch(code) {
case Keyboard.LEFT:
index = Math.max(0, selectedIndex - 1); break;
case Keyboard.RIGHT:
index = Math.min(length-1, selectedIndex + 1); break;
case Keyboard.HOME:
index = 0; break;
case Keyboard.END:
index = length-1; break;
case Keyboard.PAGE_UP:
var firstIndex:int = selectedIndex - selectedIndex%totalCols;
index = Math.max(0, Math.max(firstIndex, selectedIndex - columnCount));
break;
case Keyboard.PAGE_DOWN:
var lastIndex = selectedIndex - selectedIndex%totalCols + totalCols-1;
index = Math.min(length-1, Math.min(lastIndex, selectedIndex + totalCols)); break;
}
doKeySelection(index, shiftKey, ctrlKey);
scrollToSelected();
}
/**
* @private (protected)
* Changes the selected index, or adds or subtracts the index and
* all indices between when the shift key is used.
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function doKeySelection(newCaretIndex:uint, shiftKey:Boolean, ctrlKey:Boolean):void {
var indices:Array = selectedIndices;
var selChanged:Boolean = false;
if (newCaretIndex < 0 || newCaretIndex > length-1) {
// The index is out of range, do nothing.
} else if (shiftKey && indices.length > 0 && newCaretIndex != indices[0]) {
var firstIndex:uint = indices[0];
indices = [];
var i:int;
if (newCaretIndex < firstIndex) {
for (i=firstIndex; i>=newCaretIndex; i--) {
indices.push(i);
}
} else {
for (i=firstIndex; i<=newCaretIndex; i++) {
indices.push(i);
}
}
selChanged = true;
} else {
indices = [newCaretIndex];
caretIndex = newCaretIndex;
selChanged = true;
}
selectedIndices = indices;
if(selChanged) {
dispatchEvent(new Event(Event.CHANGE));
}
invalidate(InvalidationType.DATA);
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override protected function initializeAccessibility():void {
if (student_ar_fl_controls_TileList.createAccessibilityImplementation != null) {
student_ar_fl_controls_TileList.createAccessibilityImplementation(this);
}
}
}
}