You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ti...@apache.org on 2012/01/06 21:58:45 UTC

svn commit: r1228400 [5/6] - in /incubator/flex/whiteboard/navigators: ./ .settings/ src/ src/ws/ src/ws/tink/ src/ws/tink/spark/ src/ws/tink/spark/containers/ src/ws/tink/spark/containers/supportClasses/ src/ws/tink/spark/controls/ src/ws/tink/spark/c...

Added: incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/CoverflowLayout.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/CoverflowLayout.as?rev=1228400&view=auto
==============================================================================
--- incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/CoverflowLayout.as (added)
+++ incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/CoverflowLayout.as Fri Jan  6 20:58:43 2012
@@ -0,0 +1,1555 @@
+package ws.tink.spark.layouts
+{
+	
+	import flash.geom.ColorTransform;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.geom.Vector3D;
+	
+	import mx.core.IVisualElement;
+	import mx.core.UIComponent;
+	
+	import spark.layouts.HorizontalAlign;
+	import spark.layouts.VerticalAlign;
+	import spark.primitives.supportClasses.GraphicElement;
+	
+	import ws.tink.spark.layouts.supportClasses.PerspectiveAnimationNavigatorLayoutBase;
+	
+	/**
+	 *  A CoverflowLayout class arranges the layout elements in a
+	 *  linear along with unselected items having a different z and rotation.
+	 * 
+	 *  <p>The horizontal position of the elements is determined by the combined
+	 *  reult of <code>horizontalAlign</code>, <code>horizontalDisplacement</code>,
+	 *  <code>horizontalAlignOffset</code> or <code>horizontalAlignOffsetPercent</code>,
+	 *  <code>elementHorizontalAlign</code> and <code>selectedHorizontalDisplacement</code>.
+	 * 
+	 *  <p>The horizontal position of the elements is determined by the combined
+	 *  reult of <code>verticalAlign</code>, <code>verticalDisplacement</code>,
+	 *  <code>verticalAlignOffset</code> or <code>verticalAlignOffsetPercent</code>,
+	 *  <code>elementVerticalAlign</code> and <code>selectedVerticalDisplacement</code>.
+	 * 
+	 *  <p>The z position of unselected elements is determined by the
+	 *  <code>maximumZ</code> property.</p>.
+	 * 
+	 *  <p>The rotation of the elements is determined by the <code>rotationX</code>,
+	 *  <code>rotationY</code> and <code>rotationZ</code> properties.</p>.
+	 * 
+	 *  <p>The color of unselected elements is determined by the <code>depthColor</code>
+	 *  and <code>depthColorAlpha</code> properties.</p>. If <code>depthColor</code> has
+	 *  a value of -1, no color transform is applied.
+	 *  
+	 *  <p>The number elements or elements rendered is determined by the
+	 *  <code>numUnselectedElements</code> property. If <code>numUnselectedElements</code>
+	 *  has a value of -1 and <code>useVirtualLayout</code> has a value of true, 
+	 *  only the elements that fit within the bound of the target are rendered,
+	 *  If <code>numUnselectedElements</code> has a value of -1 and <code>useVirtualLayout</code>
+	 *  has a value of false, all elements are rendered.
+	 * 
+	 *  @mxml
+	 *
+	 *  <p>The <code>&lt;st:CoverflowLayout&gt;</code> tag inherits all of the
+	 *  tag attributes of its superclass, and adds the following tag attributes:</p>
+	 *
+	 *  <pre>
+	 *  &lt;st:CoverflowLayout
+	 *    <strong>Properties</strong>
+	 * 	  depthColor="-1"
+	 *    depthColorAlpha="1"
+	 *    elementHorizontalAlign="center|left|right"
+	 *    elementVerticalAlign="center|left|right"
+	 *    horizontalAlign="center|left|right"
+	 *    horizontalDisplacement="100"
+	 *    horizontalAlignOffset="0"
+	 *    horizontalAlignOffsetPercent="0"
+	 *    maximumZ="100"
+	 *    numUnselectedElements="-1"
+	 *    rotationX="0"
+	 *    rotationY="45"
+	 *    rotationZ="0"
+	 *    selectedHorizontalDisplacement="100"
+	 *    selectedVerticalDisplacement="0"
+	 *    verticalAlign="bottom|middle|top"
+	 *    verticalDisplacement="0"
+	 *    verticalAlignOffset="0"
+	 *    verticalAlignOffsetPercent="0"
+	 *  /&gt;
+	 *  </pre>
+	 *
+	 *  @includeExample examples/CoverflowLayoutExample.mxml
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public class CoverflowLayout extends PerspectiveAnimationNavigatorLayoutBase
+	{
+		
+
+
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function CoverflowLayout()
+		{
+			super( INDIRECT );
+			_transformCalculator = new TransformValues( this );
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		private var _transformCalculator				: TransformValues;
+		
+		/**
+		 *  @private
+		 */
+		private var _horizontalCenterMultiplier			: Number;
+		
+		/**
+		 *  @private
+		 */
+		private var _verticalCenterMultiplier			: Number;
+		
+		/**
+		 *  @private
+		 */
+		private var _elementHorizontalCenterMultiplier	: Number;
+		
+		/**
+		 *  @private
+		 */
+		private var _elementVerticalCenterMultiplier	: Number;
+		
+		/**
+		 *  @private
+		 *  Stores reference to the elements currently displayed.
+		 */
+		private var _visibleElements:Vector.<IVisualElement>;
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//----------------------------------
+		//  maximumZ
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 *  Storage property for maximumZ.
+		 */
+		private var _maximumZ				: Number = 100;
+		
+		[Inspectable(category="General", defaultValue="100")]
+		/**
+		 *  maximumZ
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get maximumZ() : Number
+		{
+			return _maximumZ;
+		}
+		/**
+		 *  @private
+		 */
+		public function set maximumZ( value : Number ) : void
+		{
+			if( _maximumZ == value ) return;
+			
+			_maximumZ = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  rotationX
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 *  Storage property for rotationX.
+		 */
+		private var _rotationX:Number = 0;
+		
+		/**
+		 *	Whether rotation should be applied to the x axis of elements.
+		 * 
+		 *  @default true
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get rotationX():Number
+		{
+			return _rotationX;
+		}
+		/**
+		 *  @private
+		 */
+		public function set rotationX( value:Number ) : void
+		{
+			if( _rotationX == value ) return;
+			
+			_rotationX = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  rotationY
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 *  Storage property for rotationY.
+		 */
+		private var _rotationY:Number = 45;
+		
+		/**
+		 *	Whether rotation should be applied to the y axis of elements.
+		 * 
+		 *  @default true
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get rotationY():Number
+		{
+			return _rotationY;
+		}
+		/**
+		 *  @private
+		 */
+		public function set rotationY( value:Number ):void
+		{
+			if( value == _rotationY ) return;
+			
+			_rotationY = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  horizontalDisplacement
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 *  Storage property for horizontalDisplacement.
+		 */
+		private var _horizontalDisplacement:Number = 100;
+		
+		[Inspectable(category="General", defaultValue="100")]
+		/**
+		 *  horizontalDisplacement
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get horizontalDisplacement() : Number
+		{
+			return _horizontalDisplacement;
+		}
+		/**
+		 *  @private
+		 */
+		public function set horizontalDisplacement( value : Number ) : void
+		{
+			if( _horizontalDisplacement == value ) return
+				
+			_horizontalDisplacement = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  selectedHorizontalDisplacement
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 *  Storage property for selectedHorizontalDisplacement.
+		 */
+		private var _selectedHorizontalDisplacement:Number = 100;
+		
+		[Inspectable(category="General", defaultValue="100")]
+		/**
+		 *  selectedHorizontalDisplacement
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get selectedHorizontalDisplacement() : Number
+		{
+			return _selectedHorizontalDisplacement;
+		}
+		/**
+		 *  @private
+		 */
+		public function set selectedHorizontalDisplacement( value:Number ) : void
+		{
+			if( _selectedHorizontalDisplacement == value ) return
+				
+			_selectedHorizontalDisplacement = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  verticalDisplacement
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 *  Storage property for verticalDisplacement.
+		 */
+		private var _verticalDisplacement:Number = 0;
+		
+		[Inspectable(category="General", defaultValue="0")]
+		/**
+		 *  verticalDisplacement
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get verticalDisplacement() : Number
+		{
+			return _verticalDisplacement;
+		}
+		/**
+		 *  @private
+		 */
+		public function set verticalDisplacement( value:Number ):void
+		{
+			if( _verticalDisplacement == value ) return;
+			
+			_verticalDisplacement = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  selectedVerticalDisplacement
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 *  Storage property for selectedVerticalDisplacement.
+		 */
+		private var _selectedVerticalDisplacement:Number = 0;
+		
+		[Inspectable(category="General", defaultValue="0")]
+		/**
+		 *  selectedVerticalDisplacement
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get selectedVerticalDisplacement() : Number
+		{
+			return _selectedVerticalDisplacement;
+		}
+		/**
+		 *  @private
+		 */
+		public function set selectedVerticalDisplacement( value:Number ) : void
+		{
+			if( _selectedVerticalDisplacement == value ) return
+				
+				_selectedVerticalDisplacement = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  depthColor
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for depthColor.
+		 */
+		private var _depthColor		: int = -1;
+		
+		[Inspectable(category="General", defaultValue="-1")]
+		/**
+		 *	The color tint to apply to elements as their are moved back on the z axis.
+		 * 
+		 *	<p>If a valid color is added to elements are tinted as they are moved
+		 *	back on the z axis taking into account the <code>depthColorAlpha</code>
+		 *	specified. If a value of -1 is set for the color no tinting is applied.</p>
+		 * 
+		 *  @default -1
+		 * 
+		 * 	@see #depthColorAlpha
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get depthColor():int
+		{
+			return _depthColor;
+		}
+		/**
+		 *  @private
+		 */
+		public function set depthColor( value:int ) : void
+		{
+			if( _depthColor == value ) return;
+			
+			_depthColor = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  depthColorAlpha
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for depthColorAlpha.
+		 */
+		private var _depthColorAlpha		: Number = 1;
+		
+		[Inspectable(category="General", defaultValue="1")]
+		
+		/**
+		 *	The alpha to be used for the color tint that is applied to elements
+		 *	as their are moved back on the z axis.
+		 * 
+		 *  @default 1
+		 * 
+		 * 	@see #depthColor
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get depthColorAlpha():Number
+		{
+			return _depthColorAlpha;
+		}
+		/**
+		 *  @private
+		 */
+		public function set depthColorAlpha( value:Number ) : void
+		{
+			if( _depthColorAlpha == value ) return;
+			
+			_depthColorAlpha = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  numUnselectedElements
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for numUnselectedElements.
+		 */
+		private var _numUnselectedElements	: int = -1;
+		
+		[Inspectable(category="General", defaultValue="-1")]
+		/**
+		 *	The number of items to show either side of the selected item
+		 *	are positioned around this element.
+		 * 
+		 *	<p>Valid values are <code>HorizontalAlign.LEFT</code>, <code>HorizontalAlign.CENTER</code>
+		 *	and <code>HorizontalAlign.RIGHT</code>.</p>
+		 * 
+		 *  @default 2
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		
+		public function get numUnselectedElements():int
+		{
+			return _numUnselectedElements;
+		}
+		/**
+		 *  @private
+		 */
+		public function set numUnselectedElements( value:int ) : void
+		{
+			if( _numUnselectedElements == value ) return;
+			
+			_numUnselectedElements = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  horizontalAlign
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for horizontalAlign.
+		 */
+		private var _horizontalAlign:String = HorizontalAlign.CENTER;
+		
+		/**
+		 *  @private
+		 *  Flag to indicate the horizontalAlign property has changed.
+		 */
+		private var _horizontalAlignChange:Boolean = true;
+		
+		[Inspectable(category="General", enumeration="left,right,center", defaultValue="center")]
+		/**
+		 *	The horizontal position of the selected element in the viewport. All other elements
+		 *	are positioned around this element.
+		 * 
+		 *	<p>Valid values are <code>HorizontalAlign.LEFT</code>, <code>HorizontalAlign.CENTER</code>
+		 *	and <code>HorizontalAlign.RIGHT</code>.</p>
+		 * 
+		 *  @default "center"
+		 * 
+		 * 	@see #horizontalAlignOffset
+		 * 	@see #horizontalAlignOffsetPercent
+		 * 	@see spark.layouts.HorizontalAlign
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get horizontalAlign():String
+		{
+			return _horizontalAlign;
+		}
+		/**
+		 *  @private
+		 */
+		public function set horizontalAlign(value:String):void
+		{
+			if( value == _horizontalAlign ) return;
+			
+			_horizontalAlign = value;
+			_horizontalAlignChange = true;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  verticalAlign
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for verticalAlign.
+		 */
+		private var _verticalAlign:String = VerticalAlign.MIDDLE;
+		
+		/**
+		 *  @private
+		 *  Flag to indicate the verticalAlign property has changed.
+		 */
+		private var _verticalAlignChange:Boolean = true;
+		
+		[Inspectable(category="General", enumeration="top,bottom,middle", defaultValue="middle")]
+		/**
+		 *	The vertical position of the selected element in the viewport. All other elements
+		 *	are positioned around this element.
+		 * 
+		 *	<p>Valid values are <code>VerticalAlign.TOP</code>, <code>VerticalAlign.MIDDLE</code>
+		 *	and <code>VerticalAlign.BOTTOM</code>.</p>
+		 * 
+		 *  @default "middle"
+		 * 
+		 * 	@see #verticalAlignOffset
+		 * 	@see #verticalAlignOffsetPercent
+		 * 	@see spark.layouts.VerticalAlign
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get verticalAlign():String
+		{
+			return _verticalAlign;
+		}
+		/**
+		 *  @private
+		 */
+		public function set verticalAlign(value:String):void
+		{
+			if( value == _verticalAlign ) return;
+			
+			_verticalAlign = value;
+			_verticalAlignChange = true;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  horizontalAlignOffset
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for horizontalAlignOffset.
+		 */
+		private var _horizontalAlignOffset:Number = 0;
+		
+		[Inspectable(category="General", defaultValue="0")]
+		/**
+		 *	The offset in pixels to be used in conjunction with <code>horizontalAlign</code>
+		 *	to set the horizontal position of the selected element in the viewport. All other elements
+		 *	are positioned around this element.
+		 * 
+		 *	<p>If <code>horizontalAlignOffsetPercent</code> is set after this property,
+		 *	this property is set automatically depending on the value of <code>horizontalAlignOffsetPercent</code>.</p>
+		 * 
+		 *  @default 0
+		 * 
+		 * 	@see #horizontalAlign
+		 * 	@see #horizontalAlignOffsetPercent
+		 * 	@see spark.layouts.HorizontalAlign
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get horizontalAlignOffset():Number
+		{
+			return _horizontalAlignOffset;
+		}
+		/**
+		 *  @private
+		 */
+		public function set horizontalAlignOffset(value:Number):void
+		{
+			if( _horizontalAlignOffset == value ) return;
+			
+			_horizontalAlignOffset = value;
+			_horizontalAlignOffsetPercent = NaN;
+			invalidateTargetDisplayList();
+		}    
+		
+		
+		//----------------------------------
+		//  verticalAlignOffset
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for verticalAlignOffset.
+		 */
+		private var _verticalAlignOffset:Number = 0;
+		
+		[Inspectable(category="General", defaultValue="0")]
+		/**
+		 *	The offset in pixels to be used in conjunction with <code>verticalAlign</code>
+		 *	to set the vertical position of the selected element in the viewport. All other elements
+		 *	are positioned around this element.
+		 * 
+		 *	<p>If <code>verticalAlignOffsetPercent</code> is set after this property,
+		 *	this property is set automatically depending on the value of <code>verticalAlignOffsetPercent</code>.</p>
+		 * 
+		 *  @default 0
+		 * 
+		 * 	@see #verticalAlign
+		 * 	@see #verticalAlignOffsetPercent
+		 * 	@see spark.layouts.VerticalAlign
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get verticalAlignOffset():Number
+		{
+			return _verticalAlignOffset;
+		}
+		/**
+		 *  @private
+		 */
+		public function set verticalAlignOffset(value:Number):void
+		{
+			if( _verticalAlignOffset == value ) return;
+			
+			_verticalAlignOffset = value;
+			_verticalAlignOffsetPercent = NaN;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  horizontalAlignOffsetPercent
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for horizontalAlignOffsetPercent.
+		 */
+		private var _horizontalAlignOffsetPercent:Number = 0;
+		
+		[Inspectable(category="General", defaultValue="0")]
+		/**
+		 *	The offset as a percentage of the unscaled width of the viewport
+		 *  to be used in conjunction with <code>horizontalAlign</code> to set the horizontal
+		 *	position of the selected element in the viewport. All other elements are
+		 * 	positioned around this element.
+		 * 
+		 *	<p>Setting this property overrides any value set on <code>horizontalAlignOffset</code>.</p>
+		 * 
+		 *  @default 0
+		 * 
+		 * 	@see #horizontalAlign
+		 * 	@see #horizontalAlignOffset
+		 * 	@see spark.layouts.HorizontalAlign
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get horizontalAlignOffsetPercent():Number
+		{
+			return _horizontalAlignOffsetPercent;
+		}
+		/**
+		 *  @private
+		 */
+		public function set horizontalAlignOffsetPercent(value:Number):void
+		{
+			if( _horizontalAlignOffsetPercent == value ) return;
+			
+			_horizontalAlignOffsetPercent = value;
+			if( !isNaN( _horizontalAlignOffsetPercent ) ) _horizontalAlignOffset = unscaledHeight * ( _horizontalAlignOffsetPercent / 100 );
+			invalidateTargetDisplayList();
+		}    
+		
+		
+		//----------------------------------
+		//  verticalAlignOffsetPercent
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for verticalAlignOffsetPercent.
+		 */
+		private var _verticalAlignOffsetPercent:Number = 0;
+		
+		[Inspectable(category="General", defaultValue="0")]
+		/**
+		 *	The offset as a percentage of the unscaled height of the viewport
+		 *  to be used in conjunction with <code>verticalAlign</code> to set the vertical
+		 *	position of the selected element in the viewport. All other elements are
+		 * 	positioned around this element.
+		 * 
+		 *	<p>Setting this property overrides any value set on <code>verticalAlignOffset</code>.</p>
+		 * 
+		 *  @default 0
+		 * 
+		 * 	@see #verticalAlign
+		 * 	@see #verticalAlignOffset
+		 * 	@see spark.layouts.VerticalAlign
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get verticalAlignOffsetPercent():Number
+		{
+			return _verticalAlignOffsetPercent;
+		}
+		/**
+		 *  @private
+		 */
+		public function set verticalAlignOffsetPercent(value:Number):void
+		{
+			if( _verticalAlignOffsetPercent == value ) return;
+			
+			_verticalAlignOffsetPercent = value;
+			if( !isNaN( _verticalAlignOffsetPercent ) ) _verticalAlignOffset = unscaledHeight * ( _verticalAlignOffsetPercent / 100 );
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  elementHorizontalAlign
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for elementHorizontalAlign.
+		 */
+		private var _elementHorizontalAlign:String = HorizontalAlign.CENTER;
+		
+		/**
+		 *  @private
+		 *  Flag to indicate the elementHorizontalAlign property has changed.
+		 */
+		private var _elementHorizontalAlignChange		: Boolean = true;
+		
+		[Inspectable(category="General", enumeration="left,right,center", defaultValue="center")]
+		/**
+		 *	The horizontal transform point of elements.
+		 * 
+		 *	<p>Valid values are <code>HorizontalAlign.LEFT</code>, <code>HorizontalAlign.CENTER</code>
+		 *	and <code>HorizontalAlign.RIGHT</code>.</p>
+		 * 
+		 *  @default "center"
+		 * 
+		 * 	@see spark.layouts.HorizontalAlign
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get elementHorizontalAlign():String
+		{
+			return _elementHorizontalAlign;
+		}
+		/**
+		 *  @private
+		 */
+		public function set elementHorizontalAlign(value:String):void
+		{
+			if( value == _elementHorizontalAlign ) return;
+			
+			_elementHorizontalAlign = value;
+			_elementHorizontalAlignChange = true;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  elementVerticalAlign
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for elementVerticalAlign.
+		 */
+		private var _elementVerticalAlign:String = VerticalAlign.MIDDLE;
+		
+		/**
+		 *  @private
+		 *  Flag to indicate the elementVerticalAlign property has changed.
+		 */
+		private var _elementVerticalAlignChange			: Boolean = true;
+		
+		[Inspectable(category="General", enumeration="top,bottom,middle", defaultValue="middle")]
+		/**
+		 *	The vertical transform point of elements.
+		 * 
+		 *	<p>Valid values are <code>VerticalAlign.TOP</code>, <code>VerticalAlign.MIDDLE</code>
+		 *	and <code>VerticalAlign.BOTTOM</code>.</p>
+		 * 
+		 *  @default "middle"
+		 * 
+		 * 	@see spark.layouts.VerticalAlign
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get elementVerticalAlign():String
+		{
+			return _elementVerticalAlign;
+		}
+		/**
+		 *  @private
+		 */
+		public function set elementVerticalAlign(value:String):void
+		{
+			if( value == _elementVerticalAlign ) return;
+			
+			_elementVerticalAlign = value;
+			_elementVerticalAlignChange = true;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *	@private
+		 * 
+		 *	Positions, transforms and sets the size of an element
+		 *  that will be visible in the layout.
+		 */
+		protected function updateVisibleElementAt( element:IVisualElement, index:int ):void
+		{
+			setElementLayoutBoundsSize( element, false );
+			
+			_transformCalculator.updateForIndex( index, element, element.width, element.height, _elementHorizontalCenterMultiplier, _elementVerticalCenterMultiplier );
+			
+			applyColorTransformToElement( element, _transformCalculator.colorTransform );
+		}
+		
+		
+		/**
+		 *	@private
+		 * 
+		 *	Sets the depth of elements inlcuded in the layout at depths
+		 *	to display correctly for the z position set with transformAround.
+		 * 
+		 *	Also sets the depth of elements that are not included in the layout.
+		 *	The depth of these is dependent on whether their element index is before
+		 *	or after the index of the selected element.
+		 * 
+		 *	- If their element index is before the selected elements index
+		 *   they appear beneath all items included in the layout.
+		 * 
+		 *	- If their element index is after the selected elements index
+		 *   they appear above all items included in the layout
+		 */
+		private function updateDepths( depths:Vector.<int> ):void
+		{
+			if( !depths || !depths.length ) return;
+			
+			var animationIndex:int = Math.max( 0, Math.min( Math.round( animationValue ), numElementsInLayout - 1 ) );
+			
+			var element:IVisualElement;
+			var index:int;
+			var i:int
+			var numBeforeMinDepth:int = 0;
+			var minDepth:int = depths[ 0 ] - 1;
+			var maxDepth:int = depths[ depths.length - 1 ] + 1;
+			
+			const elements:Vector.<IVisualElement> = new Vector.<IVisualElement>();
+			for( i = firstIndexInView; i <= lastIndexInView; i++ )
+			{
+				index = indicesInLayout[ i ];
+				element = target.getElementAt( index );
+				element.depth = ( i > animationIndex ) ? -i : i;
+				if( !element ) continue;
+				elements.push( element );
+			}
+			
+			target.invalidateLayering();
+		}
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		override public function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number):void
+		{
+			if( _horizontalAlignChange )
+			{
+				_horizontalAlignChange = false;
+				
+				switch( _horizontalAlign )
+				{
+					case HorizontalAlign.LEFT :
+					{
+						_horizontalCenterMultiplier = 0;
+						break;
+					}
+					case HorizontalAlign.RIGHT :
+					{
+						_horizontalCenterMultiplier = 1;
+						break;
+					}
+					default :
+					{
+						_horizontalCenterMultiplier = 0.5;
+					}
+				}
+			}
+			
+			if( _verticalAlignChange )
+			{
+				_verticalAlignChange = false;
+				
+				switch( _verticalAlign )
+				{
+					case VerticalAlign.TOP :
+					{
+						_verticalCenterMultiplier = 0;
+						break;
+					}
+					case VerticalAlign.BOTTOM :
+					{
+						_verticalCenterMultiplier = 1;
+						break;
+					}
+					default :
+					{
+						_verticalCenterMultiplier = 0.5;
+					}
+				}
+			}
+			
+			if( _elementHorizontalAlignChange )
+			{
+				_elementHorizontalAlignChange = false;
+				
+				switch( _elementHorizontalAlign )
+				{
+					case HorizontalAlign.LEFT :
+					{
+						_elementHorizontalCenterMultiplier = 0;
+						break;
+					}
+					case HorizontalAlign.RIGHT :
+					{
+						_elementHorizontalCenterMultiplier = 1;
+						break;
+					}
+					default :
+					{
+						_elementHorizontalCenterMultiplier = 0.5;
+					}
+				}
+			}
+			
+			if( _elementVerticalAlignChange )
+			{
+				_elementVerticalAlignChange = false;
+				
+				switch( _elementVerticalAlign )
+				{
+					case VerticalAlign.TOP :
+					{
+						_elementVerticalCenterMultiplier = 0;
+						break;
+					}
+					case VerticalAlign.BOTTOM :
+					{
+						_elementVerticalCenterMultiplier = 1;
+						break;
+					}
+					default :
+					{
+						_elementVerticalCenterMultiplier = 0.5;
+					}
+				}
+			}
+			
+			super.updateDisplayList( unscaledWidth, unscaledHeight );
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function updateDisplayListBetween():void
+		{
+			super.updateDisplayListBetween();
+			
+			if( sizeChangedInLayoutPass )
+			{
+				if( !isNaN( _horizontalAlignOffsetPercent ) ) _horizontalAlignOffset = unscaledHeight * ( _horizontalAlignOffsetPercent / 100 );
+				if( !isNaN( _verticalAlignOffsetPercent ) ) _verticalAlignOffset = unscaledHeight * ( _verticalAlignOffsetPercent / 100 );
+			}
+				
+			_transformCalculator.updateForLayoutPass( _horizontalCenterMultiplier, _verticalCenterMultiplier, _rotationX, _rotationY );
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function updateDisplayListVirtual():void
+		{
+			super.updateDisplayListVirtual();
+			
+			// Store a references to the visible elements in case numUnselectedElements is used.
+			const newVisibleElements:Vector.<IVisualElement> = new Vector.<IVisualElement>();
+			
+			var element:IVisualElement;
+			var depths:Vector.<int> = new Vector.<int>();
+			var index:int;
+
+			for( var i:int = firstIndexInView; i <= lastIndexInView; i++ )
+			{
+				element = target.getVirtualElementAt( indicesInLayout[ i ] );
+				if( _visibleElements )
+				{
+					index = _visibleElements.indexOf( element );
+					if( index != -1 ) _visibleElements.splice( index, 1 );
+				}
+				newVisibleElements.push( element );
+				depths.push( indicesInLayout[ i ] );
+				element.visible = true;
+				updateVisibleElementAt( element, i );
+			}
+			
+			// Hide all previously visible elements that should show in the layout.
+			for each( element in _visibleElements )
+			{
+				element.visible = false;
+			}
+			
+			_visibleElements = newVisibleElements.concat();
+			updateDepths( depths );
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function updateDisplayListReal():void
+		{
+			super.updateDisplayListReal();
+
+			var element:IVisualElement;
+			var depths:Vector.<int> = new Vector.<int>();
+			var index:int;
+			
+			_visibleElements = new Vector.<IVisualElement>();
+
+			for( var i:int = 0; i < numElementsInLayout; i++ )
+			{
+				element = target.getElementAt( indicesInLayout[ i ] );
+				
+				if( i >= firstIndexInView && i <= lastIndexInView )
+				{
+					depths.push( indicesInLayout[ i ] );
+					updateVisibleElementAt( element, i );
+					element.visible = true;
+					_visibleElements.push( element );
+				}
+				else
+				{
+					element.visible = false;
+				}
+			}
+			
+			updateDepths( depths );
+		}
+		
+		/**
+		 *  @inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		override protected function restoreElement( element:IVisualElement ):void
+		{
+			super.restoreElement( element );
+			
+			var vector:Vector3D = new Vector3D( 0, 0, 0 );
+			element.visible = true;
+			element.depth = 0;
+			element.transformAround( vector, null, null, vector, null, vector, vector, false );
+			applyColorTransformToElement( element, new ColorTransform() );
+		}
+		
+		
+		/**
+		 *  @private
+		 */
+		private function angle( x1:Number, y1:Number, x2:Number, y2:Number ):Number
+		{
+			return ( Math.atan2( y2 - y1, x2 - x1 ) * ( 180 / Math.PI ) ) % 360;
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function tanD( a:Number ):Number
+		{
+			return Math.tan( a * ( Math.PI / 180 ) );
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function updateIndicesInView():void
+		{
+			super.updateIndicesInView();
+			
+			var start:int;
+			var end:int;
+			
+			if( selectedElement )
+			{
+				const animationIndex:int = Math.round( animationValue );
+				
+				if( numUnselectedElements < 1 )
+				{
+					if( !useVirtualLayout )
+					{
+						start = 0;
+						end = indicesInLayout.length;
+					}
+					else
+					{
+						// The projection rectangle in 3D.
+						// TODO this should take into account the rotation
+						// of each item to be accurrate.
+						const plane:Rectangle = getProjectionRectAtZ( maximumZ );
+						
+						var center:Number;
+						var startPoint:Number;
+						var elementSize:Number;
+						
+						var numItemsRight:int = 0;
+						var numItemsLeft:int = 0;
+						var numItemsBottom:int = 0;
+						var numItemsTop:int = 0;
+						
+						// horizontal
+						if( horizontalDisplacement )
+						{
+							center = ( unscaledWidth * _horizontalCenterMultiplier ) + _horizontalAlignOffset;
+							elementSize = getElementLayoutBoundsWidth( selectedElement );
+							
+							// right
+							// add the offset for the selected item
+							startPoint = center + selectedHorizontalDisplacement;
+							// minus off the width of the nearest non-seleced element
+							startPoint -= elementSize * _elementHorizontalCenterMultiplier;
+							numItemsRight = Math.ceil( ( plane.right - startPoint ) / horizontalDisplacement );
+							
+							// left
+							// add the offset for the selected item
+							startPoint = center - selectedHorizontalDisplacement;
+							// minus off the width of the nearest non-seleced element
+							startPoint += elementSize * Math.abs( _elementHorizontalCenterMultiplier - 1 );
+							numItemsLeft = Math.ceil( ( startPoint - plane.left ) / horizontalDisplacement );
+						}
+						
+						// vertical
+						if( verticalDisplacement )
+						{
+							center = ( unscaledHeight * _verticalCenterMultiplier ) + _verticalAlignOffset;
+							elementSize = getElementLayoutBoundsHeight( selectedElement );
+							
+							// bottom
+							// add the offset for the selected item
+							startPoint = center + selectedVerticalDisplacement;
+							// minus off the width of the nearest non-seleced element
+							startPoint -= elementSize * _elementVerticalCenterMultiplier;
+							numItemsBottom = Math.ceil( ( plane.bottom - startPoint ) / verticalDisplacement );
+							
+							// top
+							// add the offset for the selected item
+							startPoint = center - selectedVerticalDisplacement;
+							// minus off the width of the nearest non-seleced element
+							startPoint += elementSize * Math.abs( _elementVerticalCenterMultiplier - 1 );
+							numItemsTop = Math.ceil( ( startPoint - plane.top ) / verticalDisplacement );
+						}
+						
+						start = Math.max( animationIndex - ( numItemsTop != 0 && numItemsTop < numItemsLeft ? numItemsTop : numItemsLeft ), 0 );
+						end = Math.min( animationIndex + ( numItemsBottom != 0 && numItemsBottom < numItemsRight ? numItemsBottom : numItemsRight ) + 1, target.numElements );
+					}
+				}
+				else
+				{
+					start = Math.max( animationIndex - numUnselectedElements, 0 );
+					end = Math.min( animationIndex + numUnselectedElements + 1, indicesInLayout.length )
+				}
+			}
+			else
+			{
+				start = -1;
+				end = -1;
+			}
+			
+			indicesInView( start, end - start );
+		}
+		
+		
+	}
+}
+
+
+import flash.geom.ColorTransform;
+import flash.geom.Point;
+import flash.geom.Vector3D;
+
+import mx.core.IVisualElement;
+
+import ws.tink.spark.layouts.CoverflowLayout;
+
+
+internal class TransformValues
+{
+	
+	
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Constructor
+	//
+	//--------------------------------------------------------------------------
+	
+	/**
+	 *  Constructor.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public function TransformValues( layout:CoverflowLayout )
+	{
+		_layout = layout;
+		_colorTransform = new ColorTransform();
+	}
+	
+	
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Variables
+	//
+	//--------------------------------------------------------------------------
+	
+	private var _layout			: CoverflowLayout;
+	
+	private var _index			: int;
+	private var _indexOffset	: Number;
+	
+	// Center
+	private var _cx				: Number;
+	private var _cy				: Number;
+	
+	// AlignOffset
+	private var _ho				: Number;
+	private var _vo				: Number;
+	
+	// Number of items
+	private var _ni				: Number;
+	
+	private var _c				: int;
+	private var _ca				: Number;
+	
+	private var _rotY				: int;
+	private var _rotX				: int;
+	
+	private var _oy:Number;
+	private var _ox:Number;
+	
+	
+	/**
+	 *  @private
+	 *  Storage property for x.
+	 */
+	private var _x:Number;
+	
+	/**
+	 *  @private
+	 *  Storage property for y.
+	 */
+	private var _y:Number;
+	
+	/**
+	 *  @private
+	 *  Storage property for z.
+	 */
+	private var _z:Number;
+	
+	/**
+	 *  @private
+	 *  Storage property for xRotation.
+	 */
+	private var _xRotation:Number;
+	
+	/**
+	 *  @private
+	 *  Storage property for yRotation.
+	 */
+	private var _yRotation:Number;
+	
+	
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Properties
+	//
+	//--------------------------------------------------------------------------
+	
+	//----------------------------------
+	//  colorTransform
+	//----------------------------------  
+	
+	/**
+	 *  @private
+	 *  Storage property for colorTransform.
+	 */
+	private var _colorTransform:ColorTransform;
+	
+	/**
+	 *	colorTransform
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public function get colorTransform():ColorTransform
+	{
+		return _colorTransform;
+	}
+	
+	
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Methods
+	//
+	//--------------------------------------------------------------------------
+	
+	/**
+	 *	updateForLayoutPass
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public function updateForLayoutPass( centerMultiplierX:Number, centerMultiplierY:Number, rotX:int, rotY:int ):void
+	{
+		_index = Math.floor( _layout.animationValue );
+		_indexOffset = _layout.animationValue - _index;
+		
+		
+		_cx = _layout.unscaledWidth * centerMultiplierX;
+		_cy = _layout.unscaledHeight * centerMultiplierY;
+		
+		_ho = _layout.horizontalAlignOffset;
+		_vo = _layout.verticalAlignOffset;
+		
+		_c = _layout.depthColor;
+		_ca = _layout.depthColorAlpha / 100;
+		
+		if( _c < 0 )
+		{
+			_colorTransform.redMultiplier = _colorTransform.greenMultiplier = _colorTransform.blueMultiplier = 1;
+			_colorTransform.redOffset = _colorTransform.greenOffset = _colorTransform.blueOffset = _colorTransform.alphaOffset = 0;
+		}
+		
+		_rotY = rotY;
+		_rotX = -rotX;
+	}
+	
+	/**
+	 *	circular
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	private function calculatePos( index:Number ):void
+	{
+		var o:Number = Math.max( -1, Math.min( 1, index ) );
+		
+		var displacement:Number;
+		
+		_yRotation = _rotY * o;
+		_xRotation = _rotX * o;
+		
+		if(  Math.abs( index ) > 1 )
+		{
+			var dir:Number = index < 0 ? index + 1 : index - 1;
+			_x = _cx + _ho + ( _layout.selectedHorizontalDisplacement * o ) + ( _layout.horizontalDisplacement * dir );
+			_y = _cy + _vo + ( _layout.selectedVerticalDisplacement * o ) + ( _layout.verticalDisplacement * dir );
+		}
+		else
+		{
+			_x = _cx + _ho + ( _layout.selectedHorizontalDisplacement * index );
+			_y = _cy + _vo + ( _layout.selectedVerticalDisplacement * index );
+		}
+		
+		_z = _layout.maximumZ * Math.abs( o );
+	}
+	
+	/**
+	 *	updateForIndex
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public function updateForIndex( i:int, element:IVisualElement, width:Number, height:Number, hMultiplier:Number, vMultiplier:Number ):void
+	{
+		_ox = ( width / 2 ) * ( hMultiplier - 0.5 ) * 2;
+		_oy = ( height / 2 ) * ( vMultiplier - 0.5 ) * 2;
+		
+		calculatePos( ( i - _index ) - _indexOffset );
+		
+		if( _c > -1 )
+		{
+			const v:Number = ( _z / _layout.maximumZ ) * _ca;
+			
+			_colorTransform.color = _c;
+			_colorTransform.redOffset *= v;
+			_colorTransform.greenOffset *= v;
+			_colorTransform.blueOffset *= v;
+			_colorTransform.redMultiplier = _colorTransform.greenMultiplier = _colorTransform.blueMultiplier = 1 - v;
+		}
+		
+		element.transformAround( new Vector3D( width / 2, height / 2, 0 ),
+			null,
+			null,
+			new Vector3D( _x - _ox, _y - _oy, _z ),
+			null,
+			new Vector3D( _xRotation, _yRotation, 0 ),
+			new Vector3D( _x - _ox, _y - _oy, _z ),
+			false );
+	}
+}
\ No newline at end of file

Added: incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/StackLayout.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/StackLayout.as?rev=1228400&view=auto
==============================================================================
--- incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/StackLayout.as (added)
+++ incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/StackLayout.as Fri Jan  6 20:58:43 2012
@@ -0,0 +1,707 @@
+/*
+Copyright (c) 2010 Tink Ltd - http://www.tink.ws
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
+the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
+THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package ws.tink.spark.layouts
+{
+	import flash.display.BitmapData;
+	import flash.events.Event;
+	import flash.geom.Matrix3D;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	
+	import mx.core.IInvalidating;
+	import mx.core.ILayoutElement;
+	import mx.core.IUIComponent;
+	import mx.core.IVisualElement;
+	import mx.core.mx_internal;
+	import mx.effects.EffectInstance;
+	import mx.effects.IEffect;
+	import mx.effects.IEffectInstance;
+	import mx.events.EffectEvent;
+	
+	import spark.components.supportClasses.GroupBase;
+	import spark.effects.Fade;
+	import spark.effects.Move;
+	import spark.layouts.HorizontalAlign;
+	import spark.layouts.VerticalAlign;
+	import spark.layouts.supportClasses.LayoutBase;
+	import spark.utils.BitmapUtil;
+	
+	import ws.tink.spark.layouts.supportClasses.NavigatorLayoutBase;
+
+	use namespace mx_internal;
+	
+	/**
+	 *  An StackLayout class shows a single element at a time..
+	 * 
+	 *  <p>The horizontal position of the shown element is determined by the layout's
+	 *  <code>horizontalAlign</code> property.</p>
+	 * 
+	 *  <p>The vertical position of the shown element is determined by the layout's
+	 *  <code>verticalAlign</code> property.</p>
+	 * 
+	 *  <p>The width of each element is calculated according to the following rules,
+	 *  listed in their respective order of precedence (element's minimum width and
+	 *  maximum width are always respected):</p>
+	 *  <ul>
+	 *    <li>If <code>horizontalAlign</code> is <code>"justify"</code>, 
+	 *    then set the element's width to the container width.</li>
+	 *
+	 *    <li>If <code>horizontalAlign</code> is <code>"contentJustify"</code>,
+	 *    then set the element's width to the maximum between the container's width 
+	 *    and all elements' preferred width.</li>
+	 *
+	 *    <li>If the element's <code>percentWidth</code> is set, then calculate the element's
+	 *    width as a percentage of the container's width.</li>
+	 *
+	 *    <li>Set the element's width to its preferred width.</li>
+	 *  </ul>
+	 *
+	 *  <p>The height of each element is calculated according to the following rules,
+	 *  listed in their respective order of precedence (element's minimum height and
+	 *  maximum height are always respected):</p>
+	 *  <ul>
+	 *    <li>If the <code>verticalAlign</code> property is <code>"justify"</code>,
+	 *   then set the element's height to the container height.</li>
+	 *
+	 *    <li>If the <code>verticalAlign</code> property is <code>"contentJustify"</code>, 
+	 *    then set the element's height to the maximum between the container's height 
+	 *    and all elements' preferred height.</li>
+	 *
+	 *    <li>If the element's <code>percentHeight</code> property is set, 
+	 *    then calculate the element's height as a percentage of the container's height.</li>
+	 *
+	 *    <li>Set the element's height to its preferred height.</li>
+	 *  </ul>
+	 * 
+	 *  @mxml
+	 *
+	 *  <p>The <code>&lt;st:StackLayout&gt;</code> tag inherits all of the
+	 *  tag attributes of its superclass, and adds the following tag attributes:</p>
+	 *
+	 *  <pre>
+	 *  &lt;st:StackLayout
+	 *    <strong>Properties</strong>
+	 *    horizontalAlign="center|contentJustify|justify|left|right"
+	 *    verticalAlign="contentJustify|bottom|justify|middle|top"
+	 *  /&gt;
+	 *  </pre>
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public class StackLayout extends NavigatorLayoutBase
+	{
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function StackLayout()
+		{
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		private var _bitmapFrom		: BitmapData;
+		
+		/**
+		 *  @private
+		 */
+		private var _bitmapTo		: BitmapData
+		
+		/**
+		 *  @private
+		 */
+		private var _stackIndex		: int = -2;
+
+		/**
+		 *  @private
+		 */		
+		public var effect			: IEffect;
+		
+		/**
+		 *  @private
+		 */
+		private var _effectInstance		: EffectInstance;
+		
+		/**
+		 *  @private
+		 */
+		private var _selectedElement		: IVisualElement;
+		
+		/**
+		 *  @private
+		 */
+		private var _elementMaxDimensions		: ElementMaxDimensions;
+		
+		/**
+		 *  @private
+		 */
+		private var _numElementsInLayout		: int;
+		
+		/**
+		 *  @private
+		 */
+		private var _numElementsNotInLayout		: int;
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//----------------------------------
+		//  verticalAlign
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 *  Storage property for verticalAlign.
+		 */
+		private var _verticalAlign:String = VerticalAlign.JUSTIFY;
+		
+		[Inspectable(category="General", enumeration="top,bottom,middle,justify,contentJustify", defaultValue="justify")]
+		/** 
+		 *  The vertical alignment of layout elements.
+		 * 
+		 *  <p>If the value is <code>"bottom"</code>, <code>"middle"</code>, 
+		 *  or <code>"top"</code> then the layout elements are aligned relative 
+		 *  to the container's <code>contentHeight</code> property.</p>
+		 * 
+		 *  <p>If the value is <code>"contentJustify"</code> then the actual
+		 *  height of the layout element is set to 
+		 *  the container's <code>contentHeight</code> property. 
+		 *  The content height of the container is the height of the largest layout element. 
+		 *  If all layout elements are smaller than the height of the container, 
+		 *  then set the height of all the layout elements to the height of the container.</p>
+		 * 
+		 *  <p>If the value is <code>"justify"</code> then the actual height
+		 *  of the layout elements is set to the container's height.</p>
+		 *
+		 *  <p>This property does not affect the layout's measured size.</p>
+		 *  
+		 *  @default "justify"
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get verticalAlign():String
+		{
+			return _verticalAlign;
+		}
+		/**
+		 *  @private
+		 */
+		public function set verticalAlign(value:String):void
+		{
+			if( value == _verticalAlign ) return;
+			
+			_verticalAlign = value;
+			
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  horizontalAlign
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for horizontalAlign.
+		 */
+		private var _horizontalAlign:String = HorizontalAlign.JUSTIFY;
+		
+		[Inspectable(category="General", enumeration="left,right,center,justify,contentJustify", defaultValue="justify")]
+		/** 
+		 *  The horizontal alignment of layout elements.
+		 * 
+		 *  <p>If the value is <code>"left"</code>, <code>"right"</code>, or <code>"center"</code> then the 
+		 *  layout element is aligned relative to the container's <code>contentWidth</code> property.</p>
+		 * 
+		 *  <p>If the value is <code>"contentJustify"</code>, then the layout element's actual
+		 *  width is set to the <code>contentWidth</code> of the container.
+		 *  The <code>contentWidth</code> of the container is the width of the largest layout element. 
+		 *  If all layout elements are smaller than the width of the container, 
+		 *  then set the width of all layout elements to the width of the container.</p>
+		 * 
+		 *  <p>If the value is <code>"justify"</code> then the layout element's actual width
+		 *  is set to the container's width.</p>
+		 *
+		 *  <p>This property does not affect the layout's measured size.</p>
+		 *  
+		 *  @default "justify"
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get horizontalAlign():String
+		{
+			return _horizontalAlign;
+		}
+		/**
+		 *  @private
+		 */
+		public function set horizontalAlign(value:String):void
+		{
+			if( value == _horizontalAlign ) return;
+			
+			_horizontalAlign = value;
+			
+			invalidateTargetDisplayList();
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//----------------------------------
+		//  target
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 */
+		override public function set target(value:GroupBase):void
+		{
+			if( target == value ) return;
+			
+			super.target = value;
+			
+			_numElementsInLayout = 0;
+			_elementMaxDimensions = new ElementMaxDimensions();
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		override public function measure():void
+		{
+			super.measure();
+			//TODO need to implement measure and add ASDocs
+		}
+		
+		/**
+		 *  @private
+		 */
+		override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+		{
+			if( _effectInstance ) _effectInstance.end();
+			
+			super.updateDisplayList( unscaledWidth, unscaledHeight );
+			
+			var i:int;
+			
+			if( !renderingData )
+			{
+				if( _numElementsInLayout != numElementsInLayout )
+				{
+					_numElementsInLayout = numElementsInLayout;
+					for( i = 0; i < _numElementsInLayout; i++ )
+					{
+						elements[ indicesInLayout[ i ] ].visible = ( i == selectedIndex );
+					}
+				}
+				
+				if( _numElementsNotInLayout != numElementsNotInLayout )
+				{
+					_numElementsNotInLayout = numElementsNotInLayout;
+					for( i = 0; i < _numElementsNotInLayout; i++ )
+					{
+						elements[ indicesInLayout[ i ] ].visible = true;
+					}
+				}
+			}
+			
+			if( _stackIndex != selectedIndex )
+			{
+				if( effect && _stackIndex >= 0 )
+				{
+					target.validateNow();
+					
+					_bitmapTo = BitmapUtil.getSnapshot(IUIComponent(target));
+					
+					Object( effect ).bitmapTo = _bitmapTo;
+					Object( effect ).bitmapFrom = _bitmapFrom;
+					_effectInstance = EffectInstance( effect.play( [ target ] )[ 0 ] );
+					_effectInstance.addEventListener( EffectEvent.EFFECT_END, onEffectEnd, false, 0, true );
+					
+					Object( effect ).bitmapTo = null;
+					Object( effect ).bitmapFrom = null;
+				}
+				
+				_stackIndex = selectedIndex;
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function updateDisplayListVirtual():void
+		{
+			super.updateDisplayListVirtual();
+			
+			if( target.numElements == 0 ) return;
+			
+			// Hide the last selectedElement.
+			if( _selectedElement && _selectedElement != selectedElement ) _selectedElement.visible = false;
+			// Update the selectedElement.
+			_selectedElement = selectedElement;
+			if( !_selectedElement ) return;
+			
+			_elementMaxDimensions.update( _selectedElement );
+			
+			updateSelectedElementSizeAndPosition( _selectedElement );
+			_selectedElement.visible = true;
+			
+			updateDepths( null );
+		}
+		
+		
+		/**
+		 *  @private
+		 */
+		override protected function updateDisplayListReal():void
+		{
+			super.updateDisplayListReal();
+			
+			if( target.numElements == 0 ) return;
+			
+			var i:int;
+			var element:IVisualElement;
+			for( i = 0; i < numElementsInLayout; i++ )
+			{
+				element = target.getElementAt( indicesInLayout[ i ] );
+				if( element != selectedElement ) 
+				{
+					element.visible = false;
+				}
+				
+				_elementMaxDimensions.update( element );
+			}
+			
+			_selectedElement = selectedElement;
+			
+			if( _selectedElement )
+			{
+				updateSelectedElementSizeAndPosition( _selectedElement );
+				_selectedElement.visible = true;
+			}
+			
+			updateDepths( null );
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function updateSelectedElementSizeAndPosition( element:IVisualElement ):void
+		{
+			var w:Number = calculateElementWidth( element, unscaledWidth, _elementMaxDimensions.width );
+			var h:Number = calculateElementHeight( element, unscaledHeight, _elementMaxDimensions.height );
+			
+			element.setLayoutBoundsSize( w, h );
+			element.setLayoutBoundsPosition( calculateElementX( w ), calculateElementY( h ) );
+		}
+		
+		/**
+		 *	@private
+		 * 
+		 *	Sets the depth of elements inlcuded in the layout at depths
+		 *	to display correctly for the z position set with transformAround.
+		 * 
+		 *	Also sets the depth of elements that are not included in the layout.
+		 *	The depth of these is dependent on whether their element index is before
+		 *	or after the index of the selected element.
+		 */
+		private function updateDepths( depths:Vector.<int> ):void
+		{
+//			var element:IVisualElement;
+//			var i:int;
+//			var numElementsNotInLayout:int = indicesNotInLayout.length;
+//			for( i = 0; i < numElementsNotInLayout; i++ )
+//			{
+//				element = target.getElementAt( indicesNotInLayout[ i ] );
+//				element.depth = indicesNotInLayout[ i ];
+//			}
+//			
+//			//FIXME tink, -1 to allow for bug
+//			_selectedElement.depth = ( indicesInLayout[ selectedIndex ] == 0 ) ? -1 : indicesInLayout[ selectedIndex ];
+		}
+		
+		
+		/**
+		 *  @inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		override protected function restoreElement( element:IVisualElement ):void
+		{
+			super.restoreElement( element );
+			
+			element.visible = true;
+		}
+		
+		/**
+		 *  @private
+		 *  Used only for virtual layout.
+		 */
+		private function calculateElementWidth( element:ILayoutElement, targetWidth:Number, containerWidth:Number ):Number
+		{
+			switch( horizontalAlign )
+			{
+				case HorizontalAlign.JUSTIFY :
+				{
+					return targetWidth;
+				}
+				case HorizontalAlign.CONTENT_JUSTIFY : 
+				{
+					return Math.max( element.getPreferredBoundsWidth(), targetWidth );
+				}
+			}
+			
+			// If percentWidth is specified then the element's width is the percentage
+			// of targetWidth clipped to min/maxWidth and to (upper limit) targetWidth.
+			var percentWidth:Number = element.percentWidth;
+			if( !isNaN( percentWidth ) )
+			{
+				var width:Number = targetWidth * ( percentWidth * 0.01 );
+				return Math.min( targetWidth, Math.min( element.getMaxBoundsWidth(), Math.max( element.getMinBoundsWidth(), width ) ) );
+			}
+			
+			return element.getPreferredBoundsWidth();  // not constrained
+		}
+		
+		/**
+		 *  @private
+		 *  Used only for virtual layout.
+		 */
+		private function calculateElementHeight( element:ILayoutElement, targetHeight:Number, containerHeight:Number):Number
+		{
+			switch( verticalAlign )
+			{
+				case VerticalAlign.JUSTIFY :
+				{
+					return targetHeight;
+				}
+				case VerticalAlign.CONTENT_JUSTIFY : 
+				{
+					return Math.max( element.getPreferredBoundsHeight(), targetHeight );
+				}
+			}
+			
+			// If percentWidth is specified then the element's width is the percentage
+			// of targetWidth clipped to min/maxWidth and to (upper limit) targetWidth.
+			var percentHeight:Number = element.percentHeight;
+			if( !isNaN( percentHeight ) )
+			{
+				var height:Number = targetHeight * ( percentHeight * 0.01 );
+				return Math.min( targetHeight, Math.min( element.getMaxBoundsHeight(), Math.max( element.getMinBoundsHeight(), height ) ) );
+			}
+			
+			return element.getPreferredBoundsHeight();  // not constrained
+		}
+		
+		
+		/**
+		 *  @private
+		 */
+		private function calculateElementX( w:Number ):Number
+		{
+			switch( horizontalAlign )
+			{
+				case HorizontalAlign.RIGHT :
+				{
+					return unscaledWidth - w;
+				}
+				case HorizontalAlign.CENTER :
+				{
+					return ( unscaledWidth - w ) / 2;
+				}
+				default :
+				{
+					return 0;
+				}
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function calculateElementY( h:Number ):Number
+		{
+			switch( verticalAlign )
+			{
+				case VerticalAlign.BOTTOM :
+				{
+					return unscaledHeight - h;
+				}
+				case VerticalAlign.MIDDLE :
+				{
+					return ( unscaledHeight - h ) / 2;
+				}
+				default :
+				{
+					return 0;
+				}
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		protected function onEffectEnd( event:EffectEvent ):void
+		{
+			_effectInstance.removeEventListener( EffectEvent.EFFECT_END, onEffectEnd, false );
+			_effectInstance = null;
+			
+			_bitmapTo.dispose();
+			_bitmapFrom.dispose();
+		}
+		
+//		override protected function scrollPositionChanged() : void
+//		{
+//			super.scrollPositionChanged();
+//			
+//			if( !target ) return;
+//			
+//			
+//		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function invalidateSelectedIndex(index:int, offset:Number):void
+		{
+			if( selectedIndex == index ) return;
+			
+			if( effect && selectedIndex >= 0 )
+			{
+				try
+				{
+					_bitmapFrom = BitmapUtil.getSnapshot(IUIComponent(target));
+				}
+				catch( e:Error )
+				{
+					_bitmapFrom = new BitmapData( 30, 30, false, 0x000000 );
+					
+				}
+			}
+			
+			super.invalidateSelectedIndex( index, offset );
+		}
+
+		/**
+		 *  @private
+		 */
+		override protected function updateDisplayListBetween():void
+		{
+			super.updateDisplayListBetween();
+			
+			if( !target.numElements )
+			{
+				indicesInView( -1, 0 );
+			}
+			else
+			{
+				indicesInView( selectedIndex, 1 );
+			}
+		}
+		
+        
+    }
+}
+
+
+import mx.core.ILayoutElement;
+
+class ElementMaxDimensions
+{
+	
+	private var _width	: Number;
+	private var _height	: Number;
+	
+	public function ElementMaxDimensions()
+	{
+		
+	}
+	
+	public function update( element:ILayoutElement ):void
+	{
+		var w:Number = Math.min( element.getPreferredBoundsWidth(), element.getLayoutBoundsWidth() );
+		var h:Number = Math.min( element.getPreferredBoundsHeight(), element.getLayoutBoundsHeight() );
+		if( w > _width ) w = _width;
+		if( h > _height ) w = _height;
+	}
+	
+	public function get width():Number
+	{
+		return _width;
+	}
+	
+	public function get height():Number
+	{
+		return _height;
+	}
+	
+
+}
\ No newline at end of file

Added: incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/AnimationNavigatorLayoutBase.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/AnimationNavigatorLayoutBase.as?rev=1228400&view=auto
==============================================================================
--- incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/AnimationNavigatorLayoutBase.as (added)
+++ incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/AnimationNavigatorLayoutBase.as Fri Jan  6 20:58:43 2012
@@ -0,0 +1,463 @@
+package ws.tink.spark.layouts.supportClasses
+{
+	import spark.effects.animation.Animation;
+	import spark.effects.animation.MotionPath;
+	import spark.effects.animation.SimpleMotionPath;
+	import spark.effects.easing.IEaser;
+	import spark.effects.easing.Linear;
+	import spark.effects.easing.Sine;
+	
+	import ws.tink.spark.controls.supportClasses.AnimationTarget;
+
+	/**
+	 *  A AnimationNavigatorLayoutBase class is a base class for navigator layouts
+	 *  that can animation between indices.
+	 * 
+	 *  <p>Subclasses need to set the <code>animationType</code> in the constructor,
+	 *  and should use the <code>animationValue</code>to layout elements.</p> 
+	 * 
+	 *  @mxml
+	 *
+	 *  <p>The <code>&lt;st:AnimationNavigatorLayoutBase&gt;</code> tag inherits all of the
+	 *  tag attributes of its superclass, and adds the following tag attributes:</p>
+	 *
+	 *  <pre>
+	 *  &lt;st:AnimationNavigatorLayoutBase
+	 *    <strong>Properties</strong>
+	 *    duration="700"
+	 *    easer="{spark.effects.easing.Linear( 0, 1 )}"
+	 *  /&gt;
+	 *  </pre>
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public class AnimationNavigatorLayoutBase extends NavigatorLayoutBase
+	{
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Class Constants
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  An animationType value passed to the constructor.
+		 *  When the animation type is "direct", the selectedIndex is immediately set
+		 *  to the proposedIndex and the selectedIndexOffset is animated from 1 to 0.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		protected static const DIRECT:String = "direct";
+		
+		/**
+		 *  An animationType value passed to the constructor.
+		 *  When the animation type is "indirect", the selectedIndex and selectedIndexOffset
+		 *  are both animated. The selectedIndexOffset gets a value between -0.5 and 0.5.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		protected static const INDIRECT:String = "indirect";
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor. 
+		 * 
+		 *  @param animationType The type of animation. 
+		 *  
+		 *  @see #
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */ 
+		public function AnimationNavigatorLayoutBase( animationType:String )
+		{
+			super();
+			
+			_animationType = animationType;
+			easer = new Linear( 0, 1 );
+			duration = 700;
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+//		private var _proposedSelectedIndex2			: int = -1;
+//		
+//		/**
+//		 *  @private
+//		 */
+//		private var _proposedSelectedIndex2Offset	: Number = 0;
+		
+		/**
+		 *  @private
+		 */
+		private var _animationType:String = DIRECT;
+		
+		
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//----------------------------------
+		//  duration
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 *  Storage property for easer.
+		 */
+		private var _duration:Number;
+		
+		/** 
+		 *  The duration of the animation in milliseconds. 
+		 *
+		 *  @default 700
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get duration():Number
+		{
+			return _duration;
+		}
+		/**
+		 *  @private
+		 */
+		public function set duration(value:Number):void
+		{
+			if( _duration == value ) return;
+			
+			_duration = value;
+			animation.duration = _duration;
+		}
+		
+		
+		//----------------------------------
+		//  easer
+		//----------------------------------    
+		
+		/**
+		 *  @private
+		 *  Storage property for easer.
+		 */
+		private var _easer:IEaser;
+		
+		/**
+		 *  The easing behavior for this effect. 
+		 *  This IEaser object is used to convert the elapsed fraction of 
+		 *  the animation into an eased fraction, which is then used to
+		 *  calculate the value at that eased elapsed fraction.
+		 * 
+		 *  @default spark.effects.easing.Linear( 0, 1 )
+		 *
+		 *  @see spark.effects.easing.Linear
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get easer():IEaser
+		{
+			return _easer;
+		}
+		/**
+		 *  @private
+		 */
+		public function set easer(value:IEaser):void
+		{
+			if( _easer == value ) return;
+			
+			_easer = value;
+			animation.easer = _easer;
+		}
+		
+		
+		//----------------------------------
+		//  animationValue
+		//----------------------------------
+		
+		/**
+		 *  @private
+		 *  Storage property for animationValue.
+		 */
+		private var _animationValue:Number = 0;
+		
+		/**
+		 *  If the <code>animationType</code> is "direct" the <code>animationValue</code>
+		 *  will ease from 1 to 0. If set to <code>animationType</code> is "indirect" the
+		 *  <code>animationValue</code> will ease from the current value of <code>selectedIndex</code>
+		 *  to the new <code>selectedIndex</code>.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get animationValue():Number
+		{
+			return _animationValue % numElementsInLayout;
+//			return animation.isPlaying ? _animationValue : 0;
+		}
+		
+		
+		//----------------------------------
+		//  animation
+		//----------------------------------   
+		
+		/**
+		 *  @private
+		 *  Storage property for animation.
+		 */
+		private var _animation:Animation;
+		
+		/**
+		 *  @private
+		 */
+		private function get animation():Animation
+		{
+			if( _animation ) return _animation;
+			_animation = new Animation();
+			var animTarget:AnimationTarget = new AnimationTarget();
+			animTarget.updateFunction = animationTargetUpdateFunction;
+			animTarget.endFunction = animationTargetEndFunction;
+//			switch( _animationType )
+//			{
+//				case DIRECT :
+//				{
+//					animTarget.updateFunction = animationTargetUpdateFunction;
+//					animTarget.endFunction = animationTargetEndFunction;
+//					break;
+//				}
+//				case INDIRECT :
+//				{
+//					animTarget.updateFunction = animationTargetUpdateFunctionIndirect;
+//					animTarget.endFunction = animationTargetEndFunctionIndirect;
+//				}
+//			}
+			
+			_animation.animationTarget = animTarget;
+			return _animation;
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Returns whether the layout is currently animating.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function isAnimating():Boolean
+		{
+			return animation.isPlaying;
+		}
+		
+		/**
+		 *  To be overridden in subclasses. <code>indicesInView()</code> should be invoked
+		 *  in this method updating the first and last index in view.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		protected function updateIndicesInView():void
+		{
+			
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function startAnimation( from:Number, to:Number ):void
+		{
+			animation.stop();
+			animation.motionPaths = new <MotionPath>[ new SimpleMotionPath( "animationIndex", from, to ) ];
+			animation.play();
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function animationTargetUpdateFunction( animation:Animation ):void
+		{
+//			super.invalidateSelectedIndex( selectedIndex, animation.currentValue[ "animationIndex" ] );
+			_animationValue = animation.currentValue[ "animationIndex" ];
+			
+//			updateIndicesInView();
+			invalidateTargetDisplayList();
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function animationTargetEndFunction( animation:Animation ):void
+		{
+//			super.invalidateSelectedIndex( selectedIndex, animation.currentValue[ "animationIndex" ] );
+			_animationValue = animation.currentValue[ "animationIndex" ];
+//			updateIndicesInView();
+			invalidateTargetDisplayList();
+		}
+		
+		
+		
+//		/**
+//		 *  @private
+//		 */
+//		private function animationTargetUpdateFunctionIndirect( animation:Animation ):void
+//		{
+//			var newValue:Number = animation.currentValue[ "animationIndex" ];
+//			var index:int = Math.round( newValue );
+//			super.invalidateSelectedIndex( index, newValue - index );
+////			updateIndicesInView();
+//		}
+//		
+//		/**
+//		 *  @private
+//		 */
+//		private function animationTargetEndFunctionIndirect( animation:Animation ):void
+//		{
+//			var newValue:Number = animation.currentValue[ "animationIndex" ];
+//			var index:int = Math.round( newValue );
+//			super.invalidateSelectedIndex( index, newValue - index );
+////			updateIndicesInView();
+//		}
+		
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Methods
+		//
+		//--------------------------------------------------------------------------
+		
+//		override protected function updateSelectedIndex(index:int, offset:Number):void
+//		{
+//			var animate:Boolean = selectedIndex != index;
+//			
+//			super.updateSelectedIndex( index, offset );
+//			
+//			if( animate )
+//			{
+//				switch( _animationType )
+//				{
+//					case DIRECT :
+//					{
+//						//						super.invalidateSelectedIndex( index, 1 );
+//						startAnimation( 1, 0 );
+//						break;
+//					}
+//					case INDIRECT :
+//					{
+//						//						startAnimation( selectedIndex + selectedIndexOffset, _proposedSelectedIndex2 + _proposedSelectedIndex2Offset );
+//						startAnimation( index - selectedIndex, 0 );
+//						break;
+//					}
+//				}
+//			}
+//			else
+//			{
+//				updateIndicesInView();
+//			}
+//		}
+		
+		/**
+		 *  @inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */  
+		override protected function invalidateSelectedIndex(index:int, offset:Number):void
+		{
+			var prevIndex:int = selectedIndex;
+			
+			super.invalidateSelectedIndex( index, 0 );
+			
+//			if( index == selectedIndex ) return;
+			
+//			if( index == _proposedSelectedIndex2 && _proposedSelectedIndex2Offset == offset ) return;
+//			
+//			_proposedSelectedIndex2 = index;
+//			_proposedSelectedIndex2Offset = offset;
+			
+			if( prevIndex == -1 || !duration || isNaN( duration ) || index == -1 || prevIndex == index )
+			{
+//				super.invalidateSelectedIndex( index, 0 );
+			}
+			else
+			{
+//				super.invalidateSelectedIndex( index, 0 );
+				
+				switch( _animationType )
+				{
+					case DIRECT :
+					{
+//						super.invalidateSelectedIndex( index, 1 );
+						startAnimation( 1, 0 );
+						break;
+					}
+					case INDIRECT :
+					{
+						startAnimation( animation.isPlaying ? animationValue : prevIndex, index );
+						break;
+					}
+				}
+				
+			}
+		}
+		
+		override protected function updateDisplayListBetween():void
+		{
+			super.updateDisplayListBetween();
+			
+			updateIndicesInView();
+		}
+	}
+}
\ No newline at end of file

Added: incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/INavigatorLayout.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/INavigatorLayout.as?rev=1228400&view=auto
==============================================================================
--- incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/INavigatorLayout.as (added)
+++ incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/INavigatorLayout.as Fri Jan  6 20:58:43 2012
@@ -0,0 +1,108 @@
+/*
+Copyright (c) 2010 Tink Ltd - http://www.tink.ws
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
+the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
+THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package ws.tink.spark.layouts.supportClasses
+{
+	import flash.events.IEventDispatcher;
+	
+	import mx.core.ISelectableList;
+	import mx.core.IVisualElement;
+
+	/**
+	 *  The INavigatorLayout interface indicates that the implementor
+	 * 	is an LayoutBase that supports a <code>selectedIndex</code> property.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public interface INavigatorLayout extends IEventDispatcher
+	{
+		
+		function get selectedElement():IVisualElement;
+		
+		//----------------------------------
+		//  selectedIndex
+		//----------------------------------
+		
+		/**
+		 *  The index of the selected INavigatorLayout item.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		function get selectedIndex():int;
+		/**
+		 *  @private
+		 */
+		function set selectedIndex( value:int ):void;
+		
+		
+		//----------------------------------
+		//  useVirtualLayout
+		//----------------------------------
+		
+		/**
+		 *  Comment.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		function get useVirtualLayout():Boolean
+		/**
+		 *  @private
+		 */
+		function set useVirtualLayout( value:Boolean ):void
+			
+			
+		//----------------------------------
+		//  firstIndexInView
+		//----------------------------------
+		
+		/**
+		 *  Comment.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		function get firstIndexInView():int
+			
+			
+		//----------------------------------
+		//  lastIndexInView
+		//----------------------------------
+		
+		/**
+		 *  Comment.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		function get lastIndexInView():int
+
+	}
+}
\ No newline at end of file

Added: incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/LayoutAxis.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/LayoutAxis.as?rev=1228400&view=auto
==============================================================================
--- incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/LayoutAxis.as (added)
+++ incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/supportClasses/LayoutAxis.as Fri Jan  6 20:58:43 2012
@@ -0,0 +1,102 @@
+/*
+
+Copyright (c) 2010 Tink Ltd - http://www.tink.ws
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
+the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
+THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+package ws.tink.spark.layouts.supportClasses
+{
+	
+
+	/**
+	 *  The DeferredCreationPolicy class defines the constant values
+	 *  for the <code>creationPolicy</code> property of the DeferedGroup class.
+	 *
+	 *  @see ws.tink.spark.containers.DeferredGroup#creationPolicy
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public class LayoutAxis
+	{
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Class constants
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Immediately create all descendants.
+		 *
+		 *  <p>Avoid using this <code>creationPolicy</code> because
+		 *  it increases the startup time of your application.
+		 *  There is usually no good reason to create components at startup
+		 *  which the user cannot see.
+		 *  If you are using this policy so that you can "push" data into
+		 *  hidden components at startup, you should instead design your
+		 *  application so that the data is stored in data variables
+		 *  and components which are created later "pull" in this data,
+		 *  via databinding or an <code>initialize</code> handler.</p>
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public static const VERTICAL:String = "vertical";
+		
+		/**
+		 *  Construct all decendants immediately but only inialize those
+		 *  that are visible.
+		 *  
+		 *  <p>This is useful if you using the container as a dataProvider
+		 *  to a MenuBar, as the MenuBar requires all the children to be created
+		 *  to get the correct dataProvider to drive its content.</p>
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public static const HORIZONTAL:String = "horizontal";
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function LayoutAxis()
+		{
+			
+		}
+	}
+}
\ No newline at end of file