first commit

This commit is contained in:
2020-10-20 00:58:15 +02:00
commit 7f1b9bfca5
222 changed files with 56918 additions and 0 deletions

View File

@ -0,0 +1,454 @@
/*
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
*/
package com.yahoo.astra.fl.controls.carouselClasses
{
import com.yahoo.astra.fl.controls.Carousel;
import com.yahoo.astra.layout.modes.BoxLayout;
import fl.controls.listClasses.ICellRenderer;
import fl.core.InvalidationType;
import fl.core.UIComponent;
import fl.events.ComponentEvent;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
/**
* A Carousel renderer that displays items in a horizontal row or a vertical
* column. Resizes so that all cell renderers are displayed.
*
* @see com.yahoo.astra.fl.controls.Carousel
* @author Josh Tynjala
*/
public class BoxCarouselRenderer extends UIComponent implements ICarouselLayoutRenderer
{
//--------------------------------------
// Constructor
//--------------------------------------
/**
* Constructor.
*/
public function BoxCarouselRenderer()
{
super();
this.scrollRect = new Rectangle();
}
//--------------------------------------
// Properties
//--------------------------------------
/**
* @private
* The active cell renderers being used by this layout renderer.
*/
protected var renderers:Array = [];
/**
* @private
* Storage for the carousel property.
*/
private var _carousel:Carousel;
/**
* @inheritDoc
*/
public function get carousel():Carousel
{
return this._carousel;
}
/**
* @private
*/
public function set carousel(value:Carousel):void
{
this._carousel = value;
this.invalidate(InvalidationType.DATA);
}
/**
* @private
* Storage for the direction property.
*/
private var _direction:String = "horizontal";
/**
* The direction in which item renderers are positioned.
* May be <code>"vertical"</code> or <code>"horizontal"</code>.
*/
public function get direction():String
{
return this._direction;
}
/**
* @private
*/
public function set direction(value:String):void
{
this._direction = value;
this.invalidate(InvalidationType.STATE);
}
/**
* @private
* Storage for the horizontalGap property.
*/
private var _horizontalGap:Number = 0;
/**
* The number of extra pixels placed between each cell renderer
* when <code>direction</code> is set to <code>"horizontal"</code>.
*/
public function get horizontalGap():Number
{
return this._horizontalGap;
}
/**
* @private
*/
public function set horizontalGap(value:Number):void
{
this._horizontalGap = value;
this.invalidate(InvalidationType.STATE);
}
/**
* @private
* Storage for the verticalGap property.
*/
private var _verticalGap:Number = 0;
/**
* The number of extra pixels placed between each cell renderer
* when <code>direction</code> is set to <code>"vertical"</code>.
*/
public function get verticalGap():Number
{
return this._verticalGap;
}
/**
* @private
*/
public function set verticalGap(value:Number):void
{
this._verticalGap = value;
this.invalidate(InvalidationType.STATE);
}
/**
* @private
* Storage for the horizontalAlign property.
*/
private var _horizontalAlign:String = "center";
/**
* When <code>direction</code> is set to <code>"horizontal"</code>,
* this value indicates the alignment of the selected item. Accepted
* values include <code>"left"</code>, <code>"center"</code>, and
* <code>"right"</code>
*
* @default "center"
*/
public function get horizontalAlign():String
{
return this._horizontalAlign;
}
/**
* @private
*/
public function set horizontalAlign(value:String):void
{
this._horizontalAlign = value;
this.invalidate(InvalidationType.STATE);
}
/**
* @private
* Storage for the verticalAlign property.
*/
private var _verticalAlign:String = "middle";
/**
* When <code>direction</code> is set to <code>"vertical"</code>,
* this value indicates the alignment of the selected item. Accepted
* values include <code>"top"</code>, <code>"middle"</code>, and
* <code>"bottom"</code>
*
* @default "middle"
*/
public function get verticalAlign():String
{
return this._verticalAlign;
}
/**
* @private
*/
public function set verticalAlign(value:String):void
{
this._verticalAlign = value;
this.invalidate(InvalidationType.STATE);
}
/**
* @private
* Storage for the displayedItemCount property.
*/
private var _displayedItemCount:int = 0;
/**
* Sets a specific number of items to display in the carousel at one
* time and resizes the carousel to make them all visible. This property
* is useful for developers who want to display carousel items in
* "pages" with a specific number of items per page.</p>
*
* <p>The default value is <code>0</code> (zero), which means that no
* changes to the width and height will be made. Some items may only
* be partially visible (cut off).</p>
*/
public function get displayedItemCount():int
{
return this._displayedItemCount;
}
/**
* @private
*/
public function set displayedItemCount(value:int):void
{
this._displayedItemCount = value;
this.invalidate(InvalidationType.DATA);
}
/**
* @private
* Storage for the forceCreationOfAllRenderers property.
*/
private var _drawAllRenderers:Boolean = false;
/**
* Forces the creation of a renderer for every item in the Carousel,
* regardless of whether each particular item is currently visible.
* Useful for cases where the renderer displays externally-loaded
* content. Network requests for images and other data may cause delays
* in rendering, even when something has been loaded once and the
* cache is already primed.
*
* <p>The visual effect of such rendering delays is often compared to
* "flickering".</p>
*/
public function get drawAllRenderers():Boolean
{
return this._drawAllRenderers;
}
/**
* @private
*/
public function set drawAllRenderers(value:Boolean):void
{
this._drawAllRenderers = value;
this.invalidate(InvalidationType.DATA);
}
/**
* @private
* Storage for the clickToSelect property.
*/
private var _clickToSelect:Boolean = true;
/**
* If true, clicking on an item renderer will select its item. If false,
* selection must be changed by setting selectedIndex or selectedItem on
* the Carousel from an external interaction.
*/
public function get clickToSelect():Boolean
{
return this._clickToSelect;
}
/**
* @private
*/
public function set clickToSelect(value:Boolean):void
{
this._clickToSelect = value;
//no need to validate
}
//--------------------------------------
// Public Methods
//--------------------------------------
/**
* @private
*/
public function cleanUp():void
{
//nothing to clean up in this implementation
var rendererCount:int = this.renderers.length;
for(var i:int = 0; i < rendererCount; i++)
{
var renderer:Sprite = Sprite(this.renderers[i]);
renderer.removeEventListener(MouseEvent.CLICK, rendererClickHandler);
}
}
//--------------------------------------
// Protected Methods
//--------------------------------------
/**
* @private
*/
override protected function draw():void
{
var oldWidth:Number = this.width;
var oldHeight:Number = this.height;
if(this.carousel.length == 0 || this.carousel.selectedIndex < 0)
{
//nothing to draw
this._width = 0;
this._height = 0;
}
else
{
this.renderers = this.createRenderers();
this.layoutRenderers(this.renderers);
this.calculateDimensions(this.renderers);
}
var scrollRect:Rectangle = this.scrollRect;
scrollRect.width = this.width;
scrollRect.height = this.height;
this.scrollRect = scrollRect;
super.draw();
if(this.displayedItemCount > 0 && (oldWidth != this.width || oldHeight != this.height))
{
this.dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE));
}
}
/**
* @private
* Under certain conditions, this renderer will update its own width and
* height to ensure that a specific number of renderers are displayed.
*/
protected function calculateDimensions(renderers:Array):void
{
var selectedRenderer:DisplayObject = DisplayObject(this.carousel.itemToCellRenderer(this.carousel.selectedItem));
if(this.displayedItemCount > 0)
{
if(this.direction == "horizontal")
{
this._width = selectedRenderer.width * this.displayedItemCount + this.horizontalGap * (this.displayedItemCount - 1);
this._height = selectedRenderer.height;
}
else
{
this._width = selectedRenderer.width;
this._height = selectedRenderer.height * this.displayedItemCount + this.verticalGap * (this.displayedItemCount - 1);
}
}
}
/**
* @private
* Creates the required renderers.
*/
protected function createRenderers():Array
{
this.carousel.astra_carousel_internal::invalidateCellRenderers();
var renderers:Array = [];
var rendererCount:int = this.carousel.length;
for(var i:int = 0; i < rendererCount; i++)
{
var item:Object = this.carousel.dataProvider.getItemAt(i);
var renderer:ICellRenderer = this.carousel.astra_carousel_internal::createCellRenderer(item);
Sprite(renderer).addEventListener(MouseEvent.CLICK, rendererClickHandler, false, 0, true);
if(renderer is UIComponent)
{
UIComponent(renderer).drawNow();
}
renderers.push(renderer);
}
this.carousel.astra_carousel_internal::validateCellRenderers();
return renderers;
}
/**
* @private
* Determines the number of renderers that will be displayed.
*/
protected function calculateRendererCount():int
{
var rendererCount:int = this.carousel.length;
if(rendererCount > 0 && !this.drawAllRenderers)
{
var firstItem:Object = this.carousel.dataProvider.getItemAt(0);
var firstRenderer:DisplayObject = this.carousel.astra_carousel_internal::createCellRenderer(firstItem);
var totalDisplayedItemCount:int = this.displayedItemCount;
if(this.displayedItemCount == 0)
{
if(this.direction == "horizontal")
{
totalDisplayedItemCount = Math.ceil(this.width / firstRenderer.width);
}
else
{
totalDisplayedItemCount = Math.ceil(this.height / firstRenderer.height);
}
}
rendererCount = totalDisplayedItemCount;
}
return Math.min(this.carousel.length, rendererCount);
}
/**
* @private
* Positions the renderers.
*/
protected function layoutRenderers(renderers:Array):void
{
var boxLayout:BoxLayout = new BoxLayout();
boxLayout.direction = this.direction;
boxLayout.verticalGap = this.verticalGap;
boxLayout.horizontalGap = this.horizontalGap;
boxLayout.layoutObjects(renderers, new Rectangle(0, 0, this.width, this.height));
}
/**
* @private
* Updates the carousel's selection when an item is clicked.
*/
protected function rendererClickHandler(event:MouseEvent):void
{
if(!this.clickToSelect)
{
return;
}
var renderer:ICellRenderer = ICellRenderer(event.currentTarget);
this.carousel.selectedItem = renderer.data;
this.carousel.dispatchEvent(new Event(Event.CHANGE));
}
}
}

View File

@ -0,0 +1,189 @@
/*
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
*/
package com.yahoo.astra.fl.controls.carouselClasses
{
import fl.containers.UILoader;
import fl.controls.listClasses.CellRenderer;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
//--------------------------------------
// Styles
//--------------------------------------
/**
* The padding that separates the edge of the cell from the edge of the text,
* in pixels.
*
* @default 3
*/
[Style(name="textPadding", type="Number", format="Length")]
/**
* The padding that separates the edge of the cell from the edge of the image,
* in pixels.
*
* @default 1
*/
[Style(name="imagePadding", type="Number", format="Length")]
/**
* The TextFormat object to use to render the component label when an item is selected.
*
* @default TextFormat("_sans", 12, 0x000000, false, false, false, '', '', TextFormatAlign.LEFT, 0, 0, 0, 0)
*
* @see flash.text.TextFormat TextFormat
*/
[Style(name="selectedTextFormat", type="flash.text.TextFormat")]
/**
* The default cell renderer for the Carousel control.
*
* @see com.yahoo.astra.fl.controls.Carousel
* @author Josh Tynjala
*/
public class CarouselCellRenderer extends CellRenderer
{
//--------------------------------------
// Static Properties
//--------------------------------------
/**
* @private
*/
private static var defaultStyles:Object =
{
imagePadding: 1,
textPadding: 3,
upSkin: "CarouselCellRenderer_upSkin",
overSkin: "CarouselCellRenderer_overSkin",
downSkin: "CarouselCellRenderer_downSkin",
disabledSkin: "CarouselCellRenderer_disabledSkin",
selectedUpSkin: "CarouselCellRenderer_selectedUpSkin",
selectedOverSkin: "CarouselCellRenderer_selectedOverSkin",
selectedDownSkin: "CarouselCellRenderer_selectedDownSkin",
selectedDisabledSkin: "CarouselCellRenderer_selectedDisabledSkin",
selectedTextFormat: new TextFormat("_sans", 12, 0x000000, false, false, false, "", "", TextFormatAlign.CENTER, 0, 0, 0, 0)
}
//--------------------------------------
// Static Methods
//--------------------------------------
/**
* @copy fl.core.UIComponent#getStyleDefinition()
*
* @see fl.core.UIComponent#getStyle()
* @see fl.core.UIComponent#setStyle()
* @see fl.managers.StyleManager
*/
public static function getStyleDefinition():Object
{
return mergeStyles(defaultStyles, CellRenderer.getStyleDefinition());
}
//--------------------------------------
// Constructor
//--------------------------------------
/**
* Constructor.
*/
public function CarouselCellRenderer()
{
super();
this.setStyle("textFormat", new TextFormat("_sans", 12, 0x000000, null, null, null, null, null, TextFormatAlign.CENTER, 0, 0, 0, 0));
}
//--------------------------------------
// Properties
//--------------------------------------
/**
* @private
*/
protected var loader:UILoader;
//--------------------------------------
// Protected Methods
//--------------------------------------
/**
* @private
*/
override protected function configUI():void
{
super.configUI();
if(!this.loader)
{
this.loader = new UILoader();
this.loader.scaleContent = true;
this.loader.maintainAspectRatio = true;
this.addChild(this.loader);
}
}
/**
* @private
*/
override protected function draw():void
{
var loaderSource:Object = CarouselListData(this.listData).source;
if(this.loader.source != loaderSource)
{
this.loader.source = loaderSource;
}
super.draw();
//we size the loader based on the textField size
//since CellRenderer only resizes when the label
//has a value, we need to manually make the textField
//smaller when there is no label.
if(this.label.length == 0)
{
this.textField.width = 0;
this.textField.height = 0;
}
var textPadding:Number = this.getStyleValue("textPadding") as Number;
this.textField.y = this.height - this.textField.height - textPadding;
if(this.selected)
{
}
var imagePadding:Number = this.getStyleValue("imagePadding") as Number;
var loaderWidth:Number = this.width - 2 * imagePadding;
var loaderHeight:Number = this.textField.y - imagePadding - Math.max(imagePadding, textPadding);
this.loader.setSize(loaderWidth, loaderHeight);
this.loader.drawNow();
super.draw();
}
/**
* @private
* Expands on the default implementation to include a TextFormat
* used when the item is selected.
*/
override protected function drawTextFormat():void
{
super.drawTextFormat();
if(this.selected)
{
var selectedTextFormat:TextFormat = this.getStyleValue("selectedTextFormat") as TextFormat;
if(selectedTextFormat)
{
this.textField.setTextFormat(selectedTextFormat);
this.textField.defaultTextFormat = selectedTextFormat;
}
}
}
}
}

View File

@ -0,0 +1,42 @@
/*
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
*/
package com.yahoo.astra.fl.controls.carouselClasses
{
import fl.controls.listClasses.ListData;
import fl.core.UIComponent;
/**
* List data used by cell renderers that appear in a Carousel.
*
* @see com.yahoo.astra.fl.controls.Carousel
* @author Josh Tynjala
*/
public class CarouselListData extends ListData
{
//--------------------------------------
// Constructor
//--------------------------------------
/**
* Constructor.
*/
public function CarouselListData(label:String, source:Object, icon:Object, owner:UIComponent, index:uint, row:uint, col:uint=0)
{
super(label, icon, owner, index, row, col);
this.source = source;
}
//--------------------------------------
// Properties
//--------------------------------------
/**
* The source used for a loaded image. Typically, a cell renderer will
* have a UILoader instance that uses this value.
*/
public var source:Object;
}
}

View File

@ -0,0 +1,88 @@
/*
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
*/
package com.yahoo.astra.fl.controls.carouselClasses
{
import com.yahoo.astra.fl.controls.Carousel;
import flash.events.IEventDispatcher;
/**
* A swappable layout system for a Carousel component.
*
* <p>Expected to be a subclass of Sprite or fl.core.UIComponent.</p>
*
* @see fl.core.UIComponent
*/
public interface ICarouselLayoutRenderer extends IEventDispatcher
{
//--------------------------------------
// Properties
//--------------------------------------
/**
* The x position, in pixels, of the layout renderer.
*/
function get x():Number;
/**
* The y position, in pixels, of the layout renderer.
*/
function get y():Number;
/**
* The width, in pixels, of the layout renderer.
*/
function get width():Number;
/**
* The height, in pixels, of the layout renderer.
*/
function get height():Number;
/**
* The carousel for which this layout renderer draws and positions the items.
*/
function get carousel():Carousel;
/**
* @private
*/
function set carousel(value:Carousel):void;
//--------------------------------------
// Methods
//--------------------------------------
/**
* Moves the layout renderer to a new position.
*
* @param x The new x position.
* @param y The new y position.
*/
function move(x:Number, y:Number):void;
/**
* Resizes the layout renderer.
*
* @param width The new width value.
* @param height The new height value.
*/
function setSize(width:Number, height:Number):void;
/**
* Draws the layout renderer immediately.
*
* @see fl.controls.UIComponent#drawNow
*/
function drawNow():void;
/**
* Designed to allow the clean up any references to cell renderers.
* Event listeners are the most common reference that should be removed.
*/
function cleanUp():void;
}
}

View File

@ -0,0 +1,374 @@
/*
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
*/
package com.yahoo.astra.fl.controls.carouselClasses
{
import com.yahoo.astra.animation.Animation;
import com.yahoo.astra.animation.AnimationEvent;
import fl.controls.listClasses.ICellRenderer;
import fl.core.UIComponent;
import fl.transitions.easing.Regular;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
/**
* A Carousel renderer that displays items in a horizontal row or a vertical
* column. When the Carousel's selectedIndex changes, the selected cell
* renderer slides into view.
*
* @see com.yahoo.astra.fl.controls.Carousel
* @author Josh Tynjala
*/
public class SlidingCarouselRenderer extends BoxCarouselRenderer implements ICarouselLayoutRenderer
{
//--------------------------------------
// Constructor
//--------------------------------------
/**
* Constructor.
*/
public function SlidingCarouselRenderer()
{
super();
this.scrollRect = new Rectangle();
}
//--------------------------------------
// Properties
//--------------------------------------
/**
* @private
* Storage for the animationDuration property.
*/
private var _animationDuration:int = 500;
/**
* The duration of the fading animation.
*/
public function get animationDuration():int
{
return this._animationDuration;
}
/**
* @private
*/
public function set animationDuration(value:int):void
{
this._animationDuration = value;
}
/**
* @private
* Storage for the animationEasingFunction property.
*/
private var _animationEasingFunction:Function = Regular.easeOut;
/**
* The function used to ease the fading animation used by this layout
* renderer type.
*/
public function get animationEasingFunction():Function
{
return this._animationEasingFunction;
}
/**
* @private
*/
public function set animationEasingFunction(value:Function):void
{
this._animationEasingFunction = value;
}
/**
* @private
* A reference to the animation used to slide items in and out.
*/
protected var slide:Animation;
/**
* @private
* The last value of the selectedItem;
*/
protected var previouslySelectedItem:Object;
//--------------------------------------
// Protected Methods
//--------------------------------------
/**
* @private
*/
override protected function draw():void
{
//in all cases, we want to stop the previous animation
if(this.slide)
{
this.slide.pause();
this.slide.removeEventListener(AnimationEvent.UPDATE, slideUpdateHandler);
this.slide.removeEventListener(AnimationEvent.COMPLETE, slideCompleteHandler);
this.slide = null;
}
super.draw();
if(this.carousel.length == 0 || this.carousel.selectedIndex < 0)
{
//nothing to draw
return;
}
var selectedRenderer:ICellRenderer = this.carousel.itemToCellRenderer(this.carousel.selectedItem);
this.moveToRenderer(selectedRenderer);
this.previouslySelectedItem = this.carousel.selectedItem;
}
/**
* @private
* Creates the required renderers.
*/
override protected function createRenderers():Array
{
this.carousel.astra_carousel_internal::invalidateCellRenderers();
var startIndex:int = 0;
var rendererCount:int = this.carousel.length;
if(!this.drawAllRenderers)
{
var selectedRenderer:DisplayObject = this.carousel.astra_carousel_internal::createCellRenderer(this.carousel.selectedItem);
var pageItemCount:int = this.displayedItemCount;
if(this.displayedItemCount == 0)
{
if(this.direction == "horizontal")
{
pageItemCount = Math.ceil(this.width / (selectedRenderer.width + this.horizontalGap));
}
else
{
pageItemCount = Math.ceil(this.height / (selectedRenderer.height + this.verticalGap));
}
}
if((this.direction == "horizontal" && this.horizontalAlign == "center") ||
(this.direction == "vertical" && this.verticalAlign == "middle"))
{
pageItemCount++;
}
var oldIndex:int = this.carousel.dataProvider.getItemIndex(this.previouslySelectedItem);
var newIndex:int = this.carousel.selectedIndex;
if(oldIndex < 0)
{
oldIndex = newIndex;
}
startIndex = Math.min(oldIndex, newIndex);
var endIndex:int = Math.max(oldIndex, newIndex);
rendererCount = Math.abs(oldIndex - newIndex) + pageItemCount;
if(this.direction == "horizontal")
{
switch(this.horizontalAlign)
{
case "center":
{
startIndex -= ((pageItemCount - 1) / 2);
startIndex = Math.max(startIndex, 0);
if(oldIndex == 0 || oldIndex == this.carousel.length - 1)
{
rendererCount--;
}
if((newIndex == 0 || newIndex == this.carousel.length - 1) && newIndex != oldIndex)
{
rendererCount--;
}
break;
}
case "right":
{
startIndex -= (pageItemCount - 1);
startIndex = Math.max(startIndex, 0);
if(newIndex == 0 || oldIndex == 0)
{
rendererCount--;
}
break;
}
default: //left
{
if(oldIndex == this.carousel.length - 1 || newIndex == this.carousel.length - 1)
{
rendererCount--;
}
break;
}
}
}
}
var renderers:Array = [];
for(var i:int = 0; i < rendererCount; i++)
{
var index:int = startIndex + i;
if(index >= this.carousel.length)
{
break;
}
var item:Object = this.carousel.dataProvider.getItemAt(index);
var renderer:ICellRenderer = this.carousel.astra_carousel_internal::createCellRenderer(item);
Sprite(renderer).addEventListener(MouseEvent.CLICK, rendererClickHandler, false, 0, true);
if(renderer is UIComponent)
{
UIComponent(renderer).drawNow();
}
renderers.push(renderer);
}
this.carousel.astra_carousel_internal::validateCellRenderers();
return renderers;
}
/**
* @private
* Animates the scrollRect to display the specified renderer. Generally,
* this is the selected item.
*/
protected function moveToRenderer(renderer:ICellRenderer):void
{
var displayedRenderer:DisplayObject = DisplayObject(renderer);
var rendererX:Number = displayedRenderer.x;
var rendererY:Number = displayedRenderer.y;
if(this.direction == "vertical")
{
switch(this.verticalAlign)
{
case "middle":
{
rendererY -= (this.height - displayedRenderer.height) / 2;
break;
}
case "right":
{
rendererY -= (this.height - displayedRenderer.height);
break;
}
}
}
else //horizontal
{
switch(this.horizontalAlign)
{
case "center":
{
rendererX -= (this.width - displayedRenderer.width) / 2;
break;
}
case "right":
{
rendererX -= (this.width - displayedRenderer.width);
break;
}
}
}
var prevRendererX:Number = rendererX;
var prevRendererY:Number = rendererY;
if(this.previouslySelectedItem)
{
var prevRenderer:DisplayObject = this.carousel.itemToCellRenderer(this.previouslySelectedItem) as DisplayObject;
if(prevRenderer)
{
prevRendererX = prevRenderer.x;
prevRendererY = prevRenderer.y;
if(this.direction == "vertical")
{
switch(this.verticalAlign)
{
case "middle":
{
prevRendererY -= (this.height - prevRenderer.height) / 2;
break;
}
case "right":
{
prevRendererY -= (this.height - prevRenderer.height);
break;
}
}
}
else //horizontal
{
switch(this.horizontalAlign)
{
case "center":
{
prevRendererX -= (this.width - prevRenderer.width) / 2;
break;
}
case "right":
{
prevRendererX -= (this.width - prevRenderer.width);
break;
}
}
}
}
}
//we miss the first update from animation, so let's initialize the scroll rect
var scrollRect:Rectangle = this.scrollRect;
scrollRect.x = prevRendererX;
scrollRect.y = prevRendererY;
this.scrollRect = scrollRect;
this.slide = new Animation(this.animationDuration,
{x: prevRendererX, y: prevRendererY},
{x: rendererX, y: rendererY});
this.slide.easingFunction = this.animationEasingFunction;
this.slide.addEventListener(AnimationEvent.UPDATE, slideUpdateHandler);
this.slide.addEventListener(AnimationEvent.COMPLETE, slideCompleteHandler);
}
//--------------------------------------
// Protected Event Handlers
//--------------------------------------
/**
* @private
* Updates the scroll rect of this layout renderer to show the currently
* selected item.
*/
protected function slideUpdateHandler(event:AnimationEvent):void
{
var scrollRect:Rectangle = this.scrollRect;
scrollRect.x = event.parameters.x;
scrollRect.y = event.parameters.y;
this.scrollRect = scrollRect;
}
/**
* @private
* When the animation completes, clean it up for garbage collection.
*/
protected function slideCompleteHandler(event:AnimationEvent):void
{
this.slideUpdateHandler(event);
this.slide.removeEventListener(AnimationEvent.UPDATE, slideUpdateHandler);
this.slide.removeEventListener(AnimationEvent.COMPLETE, slideCompleteHandler);
this.slide = null;
}
}
}

View File

@ -0,0 +1,356 @@
/*
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
*/
package com.yahoo.astra.fl.controls.carouselClasses
{
import com.yahoo.astra.animation.Animation;
import com.yahoo.astra.animation.AnimationEvent;
import com.yahoo.astra.fl.controls.Carousel;
import fl.controls.listClasses.ICellRenderer;
import fl.core.InvalidationType;
import fl.core.UIComponent;
import fl.events.ComponentEvent;
import fl.transitions.easing.Regular;
import flash.display.DisplayObject;
/**
* A Carousel renderer that displays one item at a time. When the Carousel's
* selectedIndex changes, the previously selected cell renderer fades out
* and the newly selected cell renderer fades in.
*
* @see com.yahoo.astra.fl.controls.Carousel
* @author Josh Tynjala
*/
public class StackCarouselRenderer extends UIComponent implements ICarouselLayoutRenderer
{
//--------------------------------------
// Constructor
//--------------------------------------
/**
* Constructor.
*/
public function StackCarouselRenderer()
{
super();
}
//--------------------------------------
// Properties
//--------------------------------------
/**
* @private
* The selected index from the last time the renderer redrew.
*/
private var _lastSelectedIndex:int = -1;
/**
* @private
* The renderer for the currently selected item.
*/
protected var renderer:ICellRenderer;
/**
* @private
* The renderer for the previously selected item. May be null if no
* item was previously selected.
*/
protected var previousRenderer:ICellRenderer;
/**
* @private
* Storage for the carousel property.
*/
private var _carousel:Carousel;
/**
* @inheritDoc
*/
public function get carousel():Carousel
{
return this._carousel;
}
/**
* @private
*/
public function set carousel(value:Carousel):void
{
this._carousel = value;
this.invalidate(InvalidationType.DATA);
}
/**
* @private
* A reference to the animation used to fade items in and out.
*/
private var _fade:Animation;
/**
* @private
* Storage for the animationDuration property.
*/
private var _animationDuration:int = 500;
/**
* The duration of the fading animation.
*/
public function get animationDuration():int
{
return this._animationDuration;
}
/**
* @private
*/
public function set animationDuration(value:int):void
{
this._animationDuration = value;
}
/**
* @private
* Storage for the animationEasingFunction property.
*/
private var _animationEasingFunction:Function = Regular.easeOut;
/**
* The function used to ease the fading animation used by this layout
* renderer type.
*/
public function get animationEasingFunction():Function
{
return this._animationEasingFunction;
}
/**
* @private
*/
public function set animationEasingFunction(value:Function):void
{
this._animationEasingFunction = value;
}
/**
* @private
* Storage for the forceCreationOfAllRenderers property.
*/
private var _drawAllRenderers:Boolean = false;
/**
* Forces the creation of a renderer for every item in the Carousel,
* regardless of whether each particular item is currently visible.
* Useful for cases where the renderer displays externally-loaded
* content. Network requests for images and other data may cause delays
* in rendering, even when something has been loaded once and the
* cache is already primed.
*
* <p>The visual effect of such rendering delays is often compared to
* "flickering".</p>
*/
public function get drawAllRenderers():Boolean
{
return this._drawAllRenderers;
}
/**
* @private
*/
public function set drawAllRenderers(value:Boolean):void
{
this._drawAllRenderers = value;
this.invalidate(InvalidationType.DATA);
}
/**
* @private
* Storage for the autoSize property.
*/
private var _autoSize:Boolean = false;
/**
* If true, the renderer will resize to fit the content.
*
* @default false
*/
public function get autoSize():Boolean
{
return this._autoSize;
}
/**
* @private
*/
public function set autoSize(value:Boolean):void
{
this._autoSize = value;
this.invalidate(InvalidationType.DATA);
}
//--------------------------------------
// Public Methods
//--------------------------------------
/**
* @private
* @inheritDoc
*/
public function cleanUp():void
{
//nothing to clean up in this implementation
}
//--------------------------------------
// Protected Methods
//--------------------------------------
/**
* @private
*/
override protected function draw():void
{
//in all cases, we want to stop the previous animation
if(this._fade)
{
this._fade.pause();
this._fade.removeEventListener(AnimationEvent.UPDATE, fadeUpdateHandler);
this._fade.removeEventListener(AnimationEvent.COMPLETE, fadeCompleteHandler);
this._fade = null;
}
this.carousel.astra_carousel_internal::invalidateCellRenderers();
if(this.carousel.selectedIndex < 0 || this.carousel.length == 0)
{
this.carousel.astra_carousel_internal::validateCellRenderers();
return;
}
var oldWidth:Number = this.width;
var oldHeight:Number = this.height;
var renderers:Array = [];
if(this.drawAllRenderers)
{
var itemCount:int = this.carousel.length;
for(var i:int = 0; i < itemCount; i++)
{
var item:Object = this.carousel.dataProvider.getItemAt(i);
var renderer:ICellRenderer = this.carousel.astra_carousel_internal::createCellRenderer(item);
DisplayObject(renderer).alpha = 0;
renderers.push(renderer);
}
}
this.previousRenderer = null;
if(this._lastSelectedIndex >= 0 && this._lastSelectedIndex != this.carousel.selectedIndex)
{
if(this.drawAllRenderers)
{
this.previousRenderer = ICellRenderer(renderers[this._lastSelectedIndex]);
}
else
{
var previousItem:Object = this.carousel.dataProvider.getItemAt(this._lastSelectedIndex);
this.previousRenderer = this.carousel.astra_carousel_internal::createCellRenderer(previousItem);
}
}
if(this.drawAllRenderers)
{
this.renderer = ICellRenderer(renderers[this.carousel.selectedIndex]);
}
else
{
var selectedItem:Object = this.carousel.dataProvider.getItemAt(this.carousel.selectedIndex);
this.renderer = this.carousel.astra_carousel_internal::createCellRenderer(selectedItem);
}
if(this._lastSelectedIndex != this.carousel.selectedIndex)
{
DisplayObject(this.renderer).alpha = 0;
if(this.previousRenderer)
{
DisplayObject(this.previousRenderer).alpha = 1;
}
this._fade = new Animation(this.animationDuration, {alpha: 0}, {alpha: 1});
this._fade.easingFunction = this.animationEasingFunction;
this._fade.addEventListener(AnimationEvent.UPDATE, fadeUpdateHandler);
this._fade.addEventListener(AnimationEvent.COMPLETE, fadeCompleteHandler);
this._lastSelectedIndex = this.carousel.selectedIndex;
}
else
{
DisplayObject(this.renderer).alpha = 1;
}
if(this.autoSize)
{
this._width = DisplayObject(this.renderer).width;
this._height = DisplayObject(this.renderer).height;
}
this.renderer.setSize(this.width, this.height);
if(this.renderer is UIComponent)
{
UIComponent(this.renderer).drawNow();
}
if(this.previousRenderer)
{
this.previousRenderer.setSize(this.width, this.height);
if(this.previousRenderer is UIComponent)
{
UIComponent(this.previousRenderer).drawNow();
}
}
super.draw();
if(this.width != oldWidth || this.height != oldHeight)
{
this.dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE));
}
this.carousel.astra_carousel_internal::validateCellRenderers();
}
//--------------------------------------
// Private Event Handlers
//--------------------------------------
/**
* @private
* Updates the alpha values for the currently displayed renderers. The
* renderer for the previously selected item fades out and the renderer
* for the currently selected item fades in.
*/
private function fadeUpdateHandler(event:AnimationEvent):void
{
DisplayObject(this.renderer).alpha = event.parameters.alpha;
if(this.previousRenderer)
{
DisplayObject(this.previousRenderer).alpha = 1 - event.parameters.alpha;
}
}
/**
* @private
* When the animation completes, clean it up for garbage collection.
*/
private function fadeCompleteHandler(event:AnimationEvent):void
{
this.fadeUpdateHandler(event);
this._fade.removeEventListener(AnimationEvent.UPDATE, fadeUpdateHandler);
this._fade.removeEventListener(AnimationEvent.COMPLETE, fadeCompleteHandler);
this._fade = null;
}
}
}

View File

@ -0,0 +1,8 @@
/*
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
*/
package com.yahoo.astra.fl.controls.carouselClasses
{
public namespace astra_carousel_internal = "http://www.yahoo.com/astra/carousel/internal";
}