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 [4/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/AccordionLayout.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/AccordionLayout.as?rev=1228400&view=auto
==============================================================================
--- incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/AccordionLayout.as (added)
+++ incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/AccordionLayout.as Fri Jan 6 20:58:43 2012
@@ -0,0 +1,1433 @@
+/*
+Copyright (c) 2011 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.DisplayObject;
+ import flash.geom.Matrix;
+ import flash.geom.Rectangle;
+
+ import mx.core.ILayoutElement;
+ import mx.core.ISelectableList;
+ import mx.core.IVisualElement;
+ import mx.core.mx_internal;
+
+ import spark.components.supportClasses.ButtonBarBase;
+ import spark.components.supportClasses.GroupBase;
+ import spark.effects.animation.Animation;
+
+ import ws.tink.spark.layouts.supportClasses.AnimationNavigatorLayoutBase;
+ import ws.tink.spark.layouts.supportClasses.LayoutAxis;
+
+ use namespace mx_internal;
+
+ /**
+ * An AccordionLayout class arranges the layout elements in a vertical
+ * or horizontal sequence, with one of them at a time fully visible.
+ *
+ * <p>The position of the elements is determined by arranging them
+ * in a sequence, top to bottom or left to right depending on the
+ * value or <code>duration</code>.</p>
+ *
+ * <p>If the <code>target</code> of the layout implements ISelectable list,
+ * a ButtonBarBase can be set using the <code>buttonBar</code> property and the layout
+ * will connect the <code>target</code> and ButtonBarBase together so that the
+ * ButtonBarBase can be used to navigate through the elements.</p>
+ *
+ * @mxml
+ *
+ * <p>The <code><st:Accordion></code> tag inherits all of the
+ * tag attributes of its superclass, and adds the following tag attributes:</p>
+ *
+ * <pre>
+ * <st:AccordionLayout
+ * <strong>Properties</strong>
+ * buttonRotation="none|left|right"
+ * direction="vertical|horizontal"
+ * duration="700"
+ * easer=""<i>IEaser</i>""
+ * labelField="label"
+ * labelFunction="null"
+ * layoutAllButtonBarBounds="true"
+ * minElementSize="0"
+ * useScrollRect"true"
+ * />
+ * </pre>
+ *
+ * @includeExample examples/AccordionExample.mxml
+ *
+ * @see ws.tink.spark.layouts.AccordionLayout
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public class AccordionLayout extends AnimationNavigatorLayoutBase
+ {
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function AccordionLayout()
+ {
+ super( AnimationNavigatorLayoutBase.DIRECT );
+ _measuredCache = new MeasuredCache();
+ _buttonLayout = new ButtonLayout( this );
+ }
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ private var _proposedSelectedIndexOffset : Number = 0;
+
+ /**
+ * @private
+ */
+ private var _buttonLayout:ButtonLayout;
+
+ /**
+ * @private
+ */
+ private var _elementSizes:Vector.<ElementSize> = new Vector.<ElementSize>();
+
+ /**
+ * @private
+ */
+ private var _animator:Animation;
+
+ /**
+ * @private
+ */
+ private var _measuredCache:MeasuredCache;
+
+ /**
+ * @private
+ * Flag to indicate the size and positioning of the buttonBar have changed.
+ */
+ private var _buttonBarChanged:Boolean;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // buttonRotation
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for buttonRotation.
+ */
+ private var _buttonRotation:String = "none";
+
+ [Inspectable(category="General", enumeration="none,left,right", defaultValue="none")]
+
+ /**
+ * rotateButtonBar.
+ *
+ * @default "vertical"
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get buttonRotation():String
+ {
+ return _buttonRotation;
+ }
+ /**
+ * @private
+ */
+ public function set buttonRotation( value:String ):void
+ {
+ if( value == _buttonRotation ) return;
+
+ _buttonRotation = value;
+
+ _buttonBarChanged = true;
+ _elementSizesInvalid = true;
+ _buttonLayout.invalidateTargetDisplayList();
+ invalidateTargetDisplayList();
+ invalidateTargetSize();
+ }
+
+
+ //----------------------------------
+ // direction
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for direction.
+ */
+ private var _direction:String = LayoutAxis.VERTICAL;
+
+ [Inspectable(category="General", enumeration="vertical,horizontal", defaultValue="vertical")]
+
+ /**
+ * direction.
+ *
+ * @default "vertical"
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get direction():String
+ {
+ return _direction;
+ }
+ /**
+ * @private
+ */
+ public function set direction( value:String ):void
+ {
+ if( value == _direction ) return;
+
+ _direction = value;
+
+ _buttonBarChanged = true;
+ _elementSizesInvalid = true;
+ _buttonLayout.invalidateTargetDisplayList();
+ _buttonLayout.invalidateTargetSize();
+ invalidateTargetDisplayList();
+ invalidateTargetSize();
+ }
+
+
+ //----------------------------------
+ // overlayButtonBar
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for overlayButtonBar.
+ */
+ private var _layoutAllButtonBarBounds:Boolean = false;
+
+ [Inspectable(category="General", enumeration="true,false", defaultValue="true")]
+
+ /**
+ * overlayButtonBar.
+ *
+ * @default "vertical"
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get layoutAllButtonBarBounds():Boolean
+ {
+ return _layoutAllButtonBarBounds;
+ }
+ /**
+ * @private
+ */
+ public function set layoutAllButtonBarBounds( value:Boolean ):void
+ {
+ if( value == _layoutAllButtonBarBounds ) return;
+
+ _layoutAllButtonBarBounds = value;
+
+ _buttonBarChanged = true;
+ _buttonLayout.invalidateTargetDisplayList();
+ _buttonLayout.invalidateTargetSize();
+ invalidateTargetDisplayList();
+ invalidateTargetSize();
+ }
+
+ //----------------------------------
+ // minElementSize
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for minElementSize.
+ */
+ private var _minElementSize:Number = 0;
+
+ /**
+ * The minumm size of an element when it's element index isn't the
+ * selectedIndex of the layout.
+ *
+ * @default 0
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get minElementSize():Number
+ {
+ return _minElementSize;
+ }
+ /**
+ * @private
+ */
+ public function set minElementSize( value:Number ):void
+ {
+ if( value == _minElementSize ) return;
+
+ _minElementSize = value;
+
+ _elementSizesInvalid = true;
+ invalidateTargetDisplayList();
+ if( target ) target.invalidateSize();
+ }
+
+
+// //----------------------------------
+// // verticalAlign
+// //----------------------------------
+//
+// /**
+// * @private
+// * Storage property for verticalAlign.
+// */
+// private var _verticalAlign:String = VerticalAlign.JUSTIFY;
+//
+// [Inspectable(category="General", enumeration="justify", 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="justify", defaultValue="justify")]
+//
+// /**
+// * The horizontal alignment of layout elements.
+// * 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>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();
+// }
+
+
+ //----------------------------------
+ // buttonBar
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for buttonBar.
+ */
+ private var _buttonBar:ButtonBarBase;
+
+ /**
+ * Â useScrollRect
+ *
+ * Â @langversion 3.0
+ * Â @playerversion Flash 10
+ * Â @playerversion AIR 1.5
+ * Â @productversion Flex 4
+ */
+ public function get buttonBar():ButtonBarBase
+ {
+ return _buttonBar;
+ }
+ /**
+ * @private
+ */
+ public function set buttonBar( value:ButtonBarBase ):void
+ {
+ if( _buttonBar == value ) return;
+ _buttonBar = value;
+
+ if( _buttonBar )
+ {
+ _buttonBar.layout = _buttonLayout;
+ if( _buttonBar && target is ISelectableList ) _buttonBar.dataProvider = ISelectableList( target );
+ if( target ) target.invalidateSize();
+ }
+ }
+
+
+ //----------------------------------
+ // useScrollRect
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for useScrollRect.
+ */
+ private var _useScrollRect:Boolean = true;
+
+ /**
+ * Â useScrollRect
+ *
+ * @default true
+ *
+ * Â @langversion 3.0
+ * Â @playerversion Flash 10
+ * Â @playerversion AIR 1.5
+ * Â @productversion Flex 4
+ */
+ public function get useScrollRect():Boolean
+ {
+ return _useScrollRect;
+ }
+ /**
+ * @private
+ */
+ public function set useScrollRect( value:Boolean ):void
+ {
+ if( _useScrollRect == value ) return;
+
+ _useScrollRect = value;
+ }
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // target
+ //----------------------------------
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override public function set target(value:GroupBase):void
+ {
+ if( target == value ) return;
+
+ super.target = value;
+
+ if( _buttonBar && target is ISelectableList ) _buttonBar.dataProvider = ISelectableList( target );
+ }
+
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+
+
+ /**
+ * @private
+ * Sort function used to store the list of element sizes in display list order.
+ */
+ private function sortElementSizes( a:ElementSize, b:ElementSize ):int
+ {
+ if( a.displayListIndex < b.displayListIndex ) return -1;
+ if( a.displayListIndex > b.displayListIndex ) return 1;
+ return 0;
+ }
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden Methods
+ //
+ //--------------------------------------------------------------------------
+
+ private var _elementSizesInvalid:Boolean;
+
+ public function invalidateElementSizes():void
+ {
+ _elementSizesInvalid = true;
+ invalidateTargetDisplayList();
+ }
+
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+
+ override protected function updateDisplayListBetween():void
+ {
+ if( sizeChangedInLayoutPass || _buttonBarChanged )
+ {
+ _buttonBarChanged = false;
+
+ // TODO I think this should solve the issue of animating when resizing.
+ // If we are resizing due to an index change we want to animate,
+ // if its not due to an index change we do not want to animate.
+ if( !animationValue ) clearVirtualLayoutCache();
+
+ _elementSizesInvalid = true;
+ _buttonLayout.invalidateTargetDisplayList();
+ if( _buttonBar && target )
+ {
+ _buttonBar.includeInLayout = !layoutAllButtonBarBounds;
+
+ if( _layoutAllButtonBarBounds && !isNaN( unscaledWidth ) && !isNaN( unscaledHeight ) )
+ {
+ _buttonBar.setLayoutBoundsSize( unscaledWidth, unscaledHeight );
+ _buttonBar.setLayoutBoundsPosition( target.x, target.y );
+ }
+ }
+ }
+ }
+
+
+
+ override public function measure():void
+ {
+ super.measure();
+
+ if( !target ) return;
+
+ if( !indicesInLayout || !indicesInLayout.length )
+ {
+ target.measuredWidth = target.measuredMinWidth;
+ target.measuredHeight = target.measuredMinHeight;
+ return;
+ }
+
+ var i:int
+ var element:ILayoutElement;
+
+ if( _buttonBarChanged ) _measuredCache.reset();
+
+ if( !useVirtualLayout )
+ {
+ // If we are not using a virtual layout, reset the measured cache
+ // and measure all elements again.
+ _measuredCache.reset();
+ for each( i in indicesInLayout )
+ {
+ _measuredCache.cache( target.getElementAt( indicesInLayout[ i ] ) );
+ }
+ }
+ else if( selectedIndex != -1 )
+ {
+ // If we are using a virtual layout, cache the size of the selected item.
+ _measuredCache.cache( target.getElementAt( indicesInLayout[ selectedIndex ] ) );
+ }
+
+ const prevButtonSize:Number = _buttonLayout._totalSize;
+ _buttonLayout._totalSize = 0;
+ _buttonLayout._buttonSizes = new Vector.<int>();
+
+ if( _buttonBar )
+ {
+
+ var matrix:Matrix = new Matrix();
+ var rotation:Number = buttonRotation == "none" ? 0 : buttonRotation == "left" ? -90 : 90;
+ if( rotation ) matrix.rotate( rotation * ( Math.PI / 180 ) );
+
+ var size:Number;
+ const numElements:int = target.numElements;
+ var s:Number = 0;
+ for( i = 0; i < numElements; i++ )
+ {
+ element = _buttonLayout.target.getElementAt( i );
+
+ if( !element ) continue;
+ if( matrix ) element.setLayoutMatrix( matrix, true );
+
+ if( direction == LayoutAxis.VERTICAL )
+ {
+ size = element.getPreferredBoundsHeight();
+ if( i < numElements - 1 ) size--;
+ _buttonLayout._totalSize += size;
+ }
+ else
+ {
+ size = element.getPreferredBoundsWidth();
+ if( i < numElements - 1 ) size--;
+ _buttonLayout._totalSize += size;
+ }
+
+ _buttonLayout._buttonSizes[ i ] = size;
+ }
+ }
+
+ var w:Number = 0;
+ var h:Number = 0;
+ switch( direction )
+ {
+ case LayoutAxis.VERTICAL :
+ {
+ if( minElementSize ) h += minElementSize * ( numElementsInLayout - 1 );
+ if( _buttonBar ) h += _buttonLayout._totalSize;
+ break;
+ }
+ case LayoutAxis.HORIZONTAL :
+ {
+ if( minElementSize ) w += minElementSize * ( numElementsInLayout - 1 );
+ if( _buttonBar ) w += _buttonLayout._totalSize;
+ break;
+ }
+ }
+
+
+ target.measuredWidth = _measuredCache.measuredWidth + w;
+ target.measuredHeight = _measuredCache.measuredHeight + h;
+ target.measuredMinWidth = target.measuredWidth;
+ target.measuredMinHeight = target.measuredHeight;
+
+ // Use Math.ceil() to make sure that if the content partially occupies
+ // the last pixel, we'll count it as if the whole pixel is occupied.
+ target.measuredWidth = Math.ceil( target.measuredWidth );
+ target.measuredHeight = Math.ceil( target.measuredHeight );
+ target.measuredMinWidth = Math.ceil( target.measuredMinWidth );
+ target.measuredMinHeight = Math.ceil( target.measuredMinHeight );
+
+ if( _buttonBar )
+ {
+ _buttonBar.invalidateSize();
+ _buttonBar.validateNow();
+
+ if( target.measuredWidth < _buttonBar.measuredWidth ) target.measuredWidth = Math.ceil( _buttonBar.measuredWidth );
+ if( target.measuredMinWidth < _buttonBar.measuredMinWidth ) target.measuredMinWidth = Math.ceil( _buttonBar.measuredMinWidth );
+
+ if( target.measuredHeight < _buttonBar.measuredHeight ) target.measuredHeight = Math.ceil( _buttonBar.measuredHeight );
+ if( target.measuredMinHeight < _buttonBar.measuredMinHeight ) target.measuredMinHeight = Math.ceil( _buttonBar.measuredMinHeight );
+ }
+
+ if( prevButtonSize != _buttonLayout._totalSize )
+ {
+ invalidateElementSizes();
+ invalidateTargetDisplayList();
+ }
+ }
+
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.updateDisplayList( unscaledWidth, unscaledHeight );
+
+ _elementSizesInvalid = false;
+ updateDisplayListElements();
+ }
+
+
+ /**
+ * Â @inheritDoc
+ *
+ * Â @langversion 3.0
+ * Â @playerversion Flash 10
+ * Â @playerversion AIR 1.5
+ * Â @productversion Flex 4
+ */
+ override public function clearVirtualLayoutCache():void
+ {
+ super.clearVirtualLayoutCache();
+
+ // At this point we don't want animation so we clear out the element sizes.
+ _elementSizes = new Vector.<ElementSize>();
+
+ _measuredCache.reset();
+ }
+
+
+
+ /**
+ * @private
+ */
+ private function updateDisplayListElements():void
+ {
+ var prevSize:Number;
+ var elementSize:ElementSize;
+ var element:IVisualElement;
+ var elementPos:Number = 0;
+ const offsetMultiplier:Number = 1 - animationValue;
+ const numElements:int = _elementSizes.length;
+ for( var i:int = 0; i < numElements; i++ )
+ {
+ if( _buttonLayout._buttonSizes.length > i )
+ {
+ element = _buttonLayout.target.getElementAt( i );
+ if( direction == LayoutAxis.VERTICAL )
+ {
+ element.setLayoutBoundsPosition( 0, elementPos );
+ }
+ else
+ {
+ element.setLayoutBoundsPosition( elementPos, 0 );
+ }
+ elementPos += _buttonLayout._buttonSizes[ i ];
+ }
+
+ elementSize = _elementSizes[ i ];
+ prevSize = elementSize.size;
+ elementSize.size = elementSize.start + ( elementSize.diff * offsetMultiplier );
+
+ if( elementSize.elementChanged )
+ {
+ if( direction == LayoutAxis.VERTICAL )
+ {
+ if( _useScrollRect && elementSize.element is DisplayObject )
+ {
+ DisplayObject( elementSize.element ).scrollRect = new Rectangle( 0, 0, unscaledWidth, elementSize.size );
+
+ elementSize.element.setLayoutBoundsSize( unscaledWidth, unscaledHeight - _buttonLayout._totalSize );
+ }
+ else
+ {
+ elementSize.element.setLayoutBoundsSize( unscaledWidth, elementSize.size );
+ }
+
+ elementSize.element.setLayoutBoundsPosition( 0, elementPos );
+ }
+ else
+ {
+ if( _useScrollRect && elementSize.element is DisplayObject )
+ {
+ DisplayObject( elementSize.element ).scrollRect = new Rectangle( 0, 0, elementSize.size, unscaledHeight );
+ elementSize.element.setLayoutBoundsSize( unscaledWidth - _buttonLayout._totalSize, unscaledHeight );
+ }
+ else
+ {
+ elementSize.element.setLayoutBoundsSize( elementSize.size, unscaledHeight );
+ }
+
+ elementSize.element.setLayoutBoundsPosition( elementPos, 0 );
+ }
+
+ elementPos += elementSize.size;
+ }
+ }
+ }
+
+
+ private function update( e:ElementSize, selectedSize:Number, creatingAll:Boolean ):void
+ {
+ if( creatingAll )
+ {
+ e.size = e.layoutIndex == selectedIndex ? selectedSize : minElementSize;
+ e.start = e.size;
+ }
+ else
+ {
+ e.start = e.size;
+ e.diff = e.layoutIndex == selectedIndex ? selectedSize - e.start : minElementSize - e.start;
+ }
+ }
+
+
+
+
+ /**
+ * Â @inheritDoc
+ *
+ * Â @langversion 3.0
+ * Â @playerversion Flash 10
+ * Â @playerversion AIR 1.5
+ * Â @productversion Flex 4
+ */
+ override protected function updateDisplayListVirtual():void
+ {
+ super.updateDisplayListVirtual();
+
+ if( !indicesInLayout.length ) return;
+
+ var i:int;
+ var elementSize:ElementSize;
+ const numElementSizes:int = _elementSizes.length;
+ const creatingAll:Boolean = numElementSizes == 0;
+
+ if( _elementSizesInvalid )
+ {
+ // We use this vector to store a reference to the element index
+ // of any item that is currently in the display list.
+ // If we are creating a new elementSize, we must make sure that this element
+ // is actually added (i.e. not worry about being virtual as it's already created).
+ const indicesCreated:Vector.<int> = new Vector.<int>();
+ const size:Number = direction == LayoutAxis.VERTICAL ? unscaledHeight : unscaledWidth;
+ const selectedSize:Number = size - _buttonLayout._totalSize - ( minElementSize * ( numElementsInLayout - 1 ) );
+
+ // Store a reference to the indices that we need ElementSize items for.
+ var indicesRequired:Vector.<int>;
+ var indicesRequiredIndex:int;
+ var element:IVisualElement;
+
+ if( buttonBar || minElementSize )
+ {
+ indicesRequired = indicesInLayout.concat()
+ }
+ else
+ {
+ if( target.numChildren > 1 )
+ {
+ for( i = 0; i < target.numChildren; i++ )
+ {
+ element = IVisualElement( target.getChildAt( i ) );
+ if( element.includeInLayout )
+ {
+ // Store a reference to the the element index of all children.
+ indicesCreated.push( target.getElementIndex( element ) );
+
+ }
+ }
+ }
+
+ // Also add this as an index that is required.
+ indicesRequired = indicesCreated.concat();
+
+ // Make sure we always push the selectedIndex
+ var selected:int = indicesInLayout[ selectedIndex ];
+ if( indicesRequired.indexOf( selected ) == -1 ) indicesRequired.push( selected );
+ }
+
+
+ for( i = numElementSizes - 1; i >= 0; i-- )
+ {
+ elementSize = _elementSizes[ i ];
+
+ // Remove ElementSize items that are not in the layout.
+ indicesRequiredIndex = indicesRequired.indexOf( elementSize.displayListIndex );
+ if( indicesRequiredIndex == -1 && !elementSize.size )
+ {
+ _elementSizes.splice( i, 1 );
+ }
+ // Update ElementSize items.
+ else
+ {
+ if( indicesRequiredIndex != -1 ) indicesRequired.splice( indicesRequiredIndex, 1 )
+
+ // Only get the virtual element if it is the selectedIndex,
+ // its start size is bigger than 0, or its diff in size is bigger than 0.
+ if( elementSize.displayListIndex == selectedIndex || elementSize.start || elementSize.diff ) elementSize.element = target.getVirtualElementAt( elementSize.displayListIndex );
+
+ update( elementSize, selectedSize, creatingAll );
+ }
+ }
+
+
+ // If we need to create some ElementSize items.
+ const numElementsRequired:int = indicesRequired.length;
+ for( i = 0; i < numElementsRequired; i++ )
+ {
+ elementSize = new ElementSize();
+ elementSize.diff = 0;
+ elementSize.size = minElementSize;
+ elementSize.displayListIndex = indicesRequired[ i ];
+ elementSize.layoutIndex = indicesInLayout.indexOf( elementSize.displayListIndex );
+
+ // Only get the virtual element if it is the selectedIndex,
+ // its start size is bigger than 0.
+ if( elementSize.displayListIndex == selectedIndex || elementSize.start ||
+ indicesCreated.indexOf( elementSize.displayListIndex ) != -1 )
+ {
+ elementSize.element = target.getVirtualElementAt( elementSize.displayListIndex );
+ }
+
+ _elementSizes.push( elementSize );
+
+ update( elementSize, selectedSize, creatingAll );
+ }
+
+ // If we've added items we now need to do a sort.
+ if( numElementsRequired ) _elementSizes.sort( sortElementSizes );
+ }
+ else
+ {
+ for( i = 0; i < numElementSizes; i++ )
+ {
+ elementSize = _elementSizes[ i ];
+
+ // Only get the virtual element if its size is bigger than 0,
+ // or it is the selectedIndex.
+ if( selectedIndex == elementSize.layoutIndex || elementSize.size ) elementSize.element = target.getVirtualElementAt( elementSize.displayListIndex );
+ }
+ }
+ }
+
+
+
+ /**
+ * Â @inheritDoc
+ *
+ * Â @langversion 3.0
+ * Â @playerversion Flash 10
+ * Â @playerversion AIR 1.5
+ * Â @productversion Flex 4
+ */
+ override protected function updateDisplayListReal():void
+ {
+ super.updateDisplayListReal();
+
+ if( !indicesInLayout.length ) return;
+
+ var i:int;
+ var elementSize:ElementSize;
+ const numElementSizes:int = _elementSizes.length;
+ const creatingAll:Boolean = numElementSizes == 0;
+
+ if( _elementSizesInvalid )
+ {
+ var indicesRequiredIndex:int;
+
+ const size:Number = direction == LayoutAxis.VERTICAL ? unscaledHeight : unscaledWidth;
+ const selectedSize:Number = size - _buttonLayout._totalSize - ( minElementSize * ( numElementsInLayout - 1 ) );
+
+ // Store a reference to the indices that we need ElementSize items for.
+ //const indicesRequired:Vector.<int> = buttonBar || minElementSize ? indicesInLayout.concat() : Vector.<int>( [ indicesInLayout[ selectedIndex ] ] );
+ const indicesRequired:Vector.<int> = indicesInLayout.concat();
+
+ for( i = numElementSizes - 1; i >= 0; i-- )
+ {
+ elementSize = _elementSizes[ i ];
+
+ // Remove ElementSize items that are not in the layout.
+ indicesRequiredIndex = indicesRequired.indexOf( elementSize.displayListIndex );
+ if( indicesRequiredIndex == -1 && !elementSize.size )
+ {
+ _elementSizes.splice( i, 1 );
+ }
+ // Update ElementSize items.
+ else
+ {
+ if( indicesRequiredIndex != -1 ) indicesRequired.splice( indicesRequiredIndex, 1 )
+ elementSize.element = target.getElementAt( elementSize.displayListIndex );
+
+ update( elementSize, selectedSize, creatingAll );
+ }
+ }
+
+
+ // If we need to create some ElementSize items.
+ const numElementsRequired:int = indicesRequired.length;
+ for( i = 0; i < numElementsRequired; i++ )
+ {
+ elementSize = new ElementSize();
+ elementSize.diff = 0;
+ elementSize.size = minElementSize;
+ elementSize.displayListIndex = indicesRequired[ i ];
+ elementSize.layoutIndex = indicesInLayout.indexOf( elementSize.displayListIndex );
+
+ elementSize.element = target.getElementAt( elementSize.displayListIndex );
+
+ _elementSizes.push( elementSize );
+
+ update( elementSize, selectedSize, creatingAll );
+ }
+
+ // If we've added items we now need to do a sort.
+ if( numElementsRequired ) _elementSizes.sort( sortElementSizes );
+ }
+ else
+ {
+ for( i = 0; i < numElementSizes; i++ )
+ {
+ elementSize = _elementSizes[ i ];
+ elementSize.element = target.getElementAt( elementSize.displayListIndex );
+ }
+ }
+
+ }
+
+ /**
+ * @private
+ */
+ override protected function invalidateSelectedIndex( index:int, offset:Number ):void
+ {
+ super.invalidateSelectedIndex( index, offset );
+ invalidateElementSizes();
+ }
+
+ /**
+ * @private
+ */
+ override protected function updateIndicesInView():void
+ {
+ super.updateIndicesInView();
+ indicesInView( 0, numElementsInLayout );
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override protected function restoreElement( element:IVisualElement ):void
+ {
+ super.restoreElement( element );
+
+ if( element is DisplayObject ) DisplayObject( element ).scrollRect = null;
+ }
+
+ }
+}
+import flash.geom.Matrix;
+
+import mx.core.ILayoutElement;
+import mx.core.IVisualElement;
+
+import spark.components.supportClasses.GroupBase;
+import spark.layouts.supportClasses.LayoutBase;
+
+import ws.tink.spark.layouts.AccordionLayout;
+import ws.tink.spark.layouts.supportClasses.LayoutAxis;
+
+
+internal class ElementSize
+{
+ public var start:Number;
+ public var diff:Number;
+
+ public var displayListIndex:uint;
+ public var layoutIndex:uint;
+
+
+
+ public function ElementSize()
+ {
+ }
+
+ public function toString():String
+ {
+ return "start: " + start.toString() + " size: " + size.toString() + " displayListIndex: " + displayListIndex.toString() + " element: " + ( element == null ).toString() + "!!!!";
+ }
+
+ private var _element:IVisualElement;
+ public function get element():IVisualElement
+ {
+ return _element;
+ }
+ public function set element( value:IVisualElement ):void
+ {
+ if( _element == value ) return;
+
+ _element = value;
+ if( _element ) _elementChanged = true;
+ }
+
+ private var _size:Number;
+ public function get size():Number
+ {
+ return _size;
+ }
+ public function set size( value:Number ):void
+ {
+ if( _size == value ) return;
+
+ if( ( _size + value > 0 ) && _element ) _elementChanged = true;
+ _size = value;
+// if( _size ) _elementChanged = true;
+ }
+
+ private var _elementChanged:Boolean;
+ public function get elementChanged():Boolean
+ {
+ return _elementChanged;
+ }
+}
+
+internal class MeasuredCache
+{
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function MeasuredCache()
+ {
+ reset();
+ }
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // measuredWidth
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for measuredWidth.
+ */
+ private var _measuredWidth:Number;
+
+ /**
+ * measuredWidth
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get measuredWidth():Number
+ {
+ return _measuredWidth;
+ }
+
+
+ //----------------------------------
+ // measuredHeight
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for measuredHeight.
+ */
+ private var _measuredHeight:Number;
+
+ /**
+ * measuredHeight
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get measuredHeight():Number
+ {
+ return _measuredHeight;
+ }
+
+
+ //----------------------------------
+ // measuredMinWidth
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for measuredMinWidth.
+ */
+ private var _measuredMinWidth:Number;
+
+ /**
+ * measuredMinWidth
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get measuredMinWidth():Number
+ {
+ return _measuredMinWidth;
+ }
+
+
+ //----------------------------------
+ // measuredMinHeight
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for measuredMinHeight.
+ */
+ private var _measuredMinHeight:Number;
+
+ /**
+ * measuredMinHeight
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get measuredMinHeight():Number
+ {
+ return _measuredMinHeight;
+ }
+
+ public function cache( elt:ILayoutElement ):void
+ {
+ var preferred:Number;
+ var min:Number;
+
+ // Calculate preferred width first, as it's being used to calculate min width
+ preferred = Math.ceil(elt.getPreferredBoundsWidth());
+ // Calculate min width
+ min = !isNaN(elt.percentWidth) ? Math.ceil(elt.getMinBoundsWidth()) : preferred;
+ _measuredWidth = Math.max( _measuredWidth, preferred );
+ _measuredMinWidth = Math.max( _measuredMinWidth, min );
+
+ // Calculate preferred width first, as it's being used to calculate min width
+ preferred = Math.ceil(elt.getPreferredBoundsHeight());
+ // Calculate min width
+ min = !isNaN(elt.percentHeight) ? Math.ceil(elt.getMinBoundsHeight()) : preferred;
+ _measuredHeight = Math.max( _measuredHeight, preferred );
+ _measuredMinHeight = Math.max( _measuredMinHeight, min );
+
+ }
+
+ public function reset():void
+ {
+ _measuredWidth = 0;
+ _measuredMinWidth = 0;
+ _measuredHeight = 0;
+ _measuredMinHeight = 0;
+ }
+}
+
+
+internal class ButtonLayout extends LayoutBase
+{
+
+ private var _parentLayout:AccordionLayout;
+ public var _buttonSizes:Vector.<int> = new Vector.<int>();
+ public var _totalSize:int = 0;
+ public var _rotation:Number;
+
+ public function ButtonLayout( parentLayout:AccordionLayout ):void
+ {
+ _parentLayout = parentLayout;
+ }
+
+ override public function measure():void
+ {
+ if( !_parentLayout.target ) return;
+ var matrix:Matrix;
+ var rotation:Number = _parentLayout.buttonRotation == "none" ? 0 : _parentLayout.buttonRotation == "left" ? -90 : 90;
+ if( rotation != _rotation )
+ {
+ _rotation = rotation;
+ matrix = new Matrix();
+ matrix.rotate( _rotation * ( Math.PI / 180 ) );
+ }
+
+ var element:IVisualElement;
+ var size:Number;
+ const numElements:int = target.numElements;
+ var s:Number = 0;
+ for( var i:int = 0; i < numElements; i++ )
+ {
+ element = target.getElementAt( i );
+
+ if( matrix ) element.setLayoutMatrix( matrix, true );
+
+ if( _parentLayout.direction == LayoutAxis.VERTICAL )
+ {
+
+ s = Math.max( s, element.getPreferredBoundsWidth() );
+ }
+ else
+ {
+ s = Math.max( s, element.getPreferredBoundsHeight() );
+ }
+
+ }
+
+ if( _parentLayout.direction == LayoutAxis.VERTICAL )
+ {
+ target.measuredWidth = target.measuredMinWidth = s;
+ target.measuredHeight = _parentLayout.target.measuredHeight;
+ target.measuredMinHeight = _parentLayout.target.measuredMinHeight;
+ }
+ else
+ {
+ target.measuredWidth = _parentLayout.target.measuredWidth
+ target.measuredMinWidth = _parentLayout.target.measuredWidth;
+ target.measuredHeight = target.measuredMinHeight = s;
+ }
+ }
+
+ public function invalidateTargetDisplayList() : void
+ {
+ if( !target ) return;
+ target.invalidateDisplayList();
+ }
+
+ public function invalidateTargetSize() : void
+ {
+ if( !target ) return;
+ target.invalidateSize();
+ }
+
+ override public function set target( value:GroupBase ):void
+ {
+ _totalSize = 0;
+ _buttonSizes.splice( 0, _buttonSizes.length );
+ super.target = value;
+ }
+ override public function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
+ {
+ super.updateDisplayList( unscaledWidth, unscaledHeight );
+
+ if( !target || !_parentLayout.target ) return;
+
+ var matrix:Matrix;
+ var rotation:Number = _parentLayout.buttonRotation == "none" ? 0 : _parentLayout.buttonRotation == "left" ? -90 : 90;
+ if( rotation != _rotation )
+ {
+ _rotation = rotation;
+ matrix = new Matrix();
+ matrix.rotate( _rotation * ( Math.PI / 180 ) );
+ }
+
+ var element:IVisualElement;
+ const numElements:int = target.numElements;
+ for( var i:int = 0; i < numElements; i++ )
+ {
+ element = target.getElementAt( i );
+
+ if( matrix ) element.setLayoutMatrix( matrix, true );
+
+ if( _parentLayout.direction == LayoutAxis.VERTICAL )
+ {
+ element.setLayoutBoundsSize( unscaledWidth, element.getPreferredBoundsHeight() );
+ }
+ else
+ {
+ element.setLayoutBoundsSize( element.getPreferredBoundsWidth(), unscaledHeight );
+ }
+ }
+
+ _parentLayout.invalidateElementSizes();
+ }
+
+}
Added: incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/CarouselLayout.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/CarouselLayout.as?rev=1228400&view=auto
==============================================================================
--- incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/CarouselLayout.as (added)
+++ incubator/flex/whiteboard/navigators/src/ws/tink/spark/layouts/CarouselLayout.as Fri Jan 6 20:58:43 2012
@@ -0,0 +1,1757 @@
+/*
+Copyright (c) 2011 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.geom.ColorTransform;
+ import flash.geom.Point;
+ 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 CarouselLayout class arranges the layout elements in a
+ * sequence along an arc, with one of them at a time selected.
+ *
+ * <p>The position of the elements is determined by the radii
+ * <code>radiusX</code>, <code>radiusY</code> and <code>radiusZ</code>.
+ * These can be properties can be set the negative values to produce
+ * a ring of elements surrounding the view point.</p>
+ *
+ * <p>The rotation of the elements is determined by the
+ * <code>rotationX</code> and <code>rotationY</code> properties.</p>
+ * <ul>
+ * <li>If a value of <code>"none"</code> is used for a rotation property,
+ * no rotation is applied to the element around the corresponding axis.</li>
+ *
+ * <li>If a value of <code>"standard"</code> is used for a rotation property,
+ * the element will be rotated so that it faces outwards around the arc.</li>
+ *
+ * <li>If a value of <code>"reversed"</code> is used for a rotation property,
+ * the element will be rotated so that it faces inwards around the arc.</li>
+ * </ul>
+ *
+ * @mxml
+ *
+ * <p>The <code><st:CarouselLayout></code> tag inherits all of the
+ * tag attributes of its superclass, and adds the following tag attributes:</p>
+ *
+ * <pre>
+ * <st:AccordionLayout
+ * <strong>Properties</strong>
+ * angle="360"
+ * depthColor="-1"
+ * depthColorAlpha="1"
+ * horizontalAlign="center|left|right"
+ * horizontalAlignOffset="0"
+ * horizontalAlignOffsetPercent="0"
+ * numUnselectedElements="-1"
+ * radiusX="100"
+ * radiusY="0"
+ * radiusZ="NaN"
+ * rotateX="none|reversed|standard"
+ * rotateY="none|reversed|standard"
+ * verticalAlign="bottom|middle|top"
+ * verticalAlignOffset="0"
+ * verticalAlignOffsetPercent="0"
+ * />
+ * </pre>
+ *
+ * @includeExample examples/CarouselLayoutExample.mxml
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public class CarouselLayout extends PerspectiveAnimationNavigatorLayoutBase
+ {
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function CarouselLayout()
+ {
+ 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
+ */
+ private var _displayedElements : Vector.<IVisualElement>
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // angle
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for angle.
+ */
+ private var _angle:Number = 360;
+
+ /**
+ * The segment of a circle to rotate the elements around.
+ *
+ * @default 360
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get angle():Number
+ {
+ return _angle;
+ }
+ /**
+ * @private
+ */
+ public function set angle( value:Number ) : void
+ {
+ if( _angle == value ) return;
+
+ _angle = value;
+ invalidateTargetDisplayList();
+ }
+
+
+ //----------------------------------
+ // rotateX
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for rotateX.
+ */
+ private var _rotateX:int = 0;
+
+ [Inspectable(category="General", enumeration="none,reversed,standard", defaultValue="none")]
+ /**
+ * 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 rotateX():String
+ {
+ return _rotateX ? _rotateX < 0 ? "reversed" : "standard" : "none";
+ }
+ /**
+ * @private
+ */
+ public function set rotateX( value:String ) : void
+ {
+ var r:int;
+
+ switch( value )
+ {
+ case "reversed" :
+ {
+ r = -1;
+ break;
+ }
+ case "standard" :
+ {
+ r = 1;
+ break;
+ }
+ default :
+ {
+ r = 0;
+ }
+
+ }
+
+ if( _rotateX == r ) return;
+
+ _rotateX = r;
+ invalidateTargetDisplayList();
+ }
+
+
+ //----------------------------------
+ // rotateY
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for rotateY.
+ */
+ private var _rotateY:int = 1;
+
+ [Inspectable(category="General", enumeration="none,reversed,standard", defaultValue="standard")]
+ /**
+ * 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 rotateY():String
+ {
+ return _rotateY ? _rotateY < 0 ? "reversed" : "standard" : "none";
+ }
+ /**
+ * @private
+ */
+ public function set rotateY( value:String ) : void
+ {
+ var r:int;
+
+ switch( value )
+ {
+ case "reversed" :
+ {
+ r = -1;
+ break;
+ }
+ case "standard" :
+ {
+ r = 1;
+ break;
+ }
+ default :
+ {
+ r = 0;
+ }
+
+ }
+
+ if( r == _rotateY ) return;
+
+ _rotateY = r;
+ 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;
+// _indicesInViewChanged = true;
+ 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 );
+// _indicesInViewChanged = true;
+ 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 );
+// _indicesInViewChanged = true;
+ 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();
+ }
+
+
+ //----------------------------------
+ // radiusX
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for radiusX.
+ */
+ private var _radiusX : Number = 100;
+
+ [Inspectable(category="General", type="Number", defaultValue="100")]
+ /**
+ * The radius to be used on the x axis for the SemiCarouselLayout.
+ *
+ * @default 100
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get radiusX():Number
+ {
+ return _radiusX;
+ }
+ /**
+ * @private
+ */
+ public function set radiusX( value:Number ):void
+ {
+ if( value == _radiusX ) return;
+
+ _radiusX = value;
+ invalidateTargetDisplayList();
+ }
+
+
+ //----------------------------------
+ // radiusY
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for radiusY.
+ */
+ private var _radiusY : Number = 0;
+
+ [Inspectable(category="General", type="Number", defaultValue="0")]
+ /**
+ * The radius to be used on the y axis for the SemiCarouselLayout.
+ *
+ * @default 0
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get radiusY():Number
+ {
+ return _radiusY;
+ }
+ /**
+ * @private
+ */
+ public function set radiusY( value:Number ):void
+ {
+ if( value == _radiusY ) return;
+
+ _radiusY = value;
+ invalidateTargetDisplayList();
+ }
+
+
+ //----------------------------------
+ // radiusZ
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for radiusZ.
+ */
+ private var _radiusZ : Number;
+
+ [Inspectable(category="General", type="Number", defaultValue="NaN")]
+ /**
+ * The radius to be used on the z axis for the SemiCarouselLayout.
+ *
+ * <p>If a value of NaN is passed the largest of <code>radiusX</code>
+ * or <code>radiusY</code> is used.</p>
+ *
+ * @default NaN
+ *
+ * @see #radiusX
+ * @see #radiusY
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function get radiusZ():Number
+ {
+ return _radiusZ;
+ }
+ /**
+ * @private
+ */
+ public function set radiusZ( value:Number ):void
+ {
+ if( value == _radiusZ ) return;
+
+ _radiusZ = value;
+ 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
+ {
+ _displayedElements.push( element );
+
+ setElementLayoutBoundsSize( element, false );
+
+ _transformCalculator.updateForIndex( index, element, element.width, element.height, _elementHorizontalCenterMultiplier, _elementVerticalCenterMultiplier );
+
+// elementTransformAround( element );
+ applyColorTransformToElement( element, _transformCalculator.colorTransform );
+ element.visible = true;
+ }
+
+ /**
+ * @private
+ */
+ private function sortElementsByZ( a:IVisualElement, b:IVisualElement ):int
+ {
+ if( getZ( a ) > getZ( b ) )
+ {
+ return -1;
+ }
+ else if( getZ( a ) < getZ( b ) )
+ {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * @private
+ *
+ * Util function to return the value of the z property
+ * on an element.
+ */
+ private function getZ( e:IVisualElement ):Number
+ {
+ if( e is GraphicElement )
+ {
+ return GraphicElement( e ).z;
+ }
+ else
+ {
+ return UIComponent( e ).z;
+ }
+ }
+
+ /**
+ * @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 );
+ if( !element ) continue;
+ elements.push( element );
+ }
+
+ elements.sort( sortElementsByZ );
+ var num:int = elements.length;
+ for( i = 0; i < num; i++ )
+ {
+ elements[ i ].depth = depths[ i ];
+ }
+
+// target.validateNow();
+// for( i = firstIndexInView; i <= lastIndexInView; i++ )
+// {
+// index = indicesInLayout[ i ];
+// element = target.getElementAt( index );
+// if( !element ) continue;
+// if( index < indicesInLayout[ animationIndex ] )
+// {
+// element.depth = _transformCalculator.radiusZ > -1 ? depths.shift() : depths.pop();
+// }
+//// else if ( index > indicesInLayout[ animationIndex ] )
+//// {
+//// element.depth = _direction == SemiCarouselLayoutDirection.CONVEX ? depths.pop() : depths.shift();
+//// }
+// else
+// {
+// element.depth = _transformCalculator.radiusZ > -1 ? depths.pop() : depths.shift();
+// }
+// }
+//
+//
+// var numElementsNotInLayout:int = indicesNotInLayout.length;
+// for( i = 0; i < numElementsNotInLayout; i++ )
+// {
+// if( indicesNotInLayout[ i ] > indicesInLayout[ animationIndex ] )
+// {
+// break;
+// }
+// else
+// {
+// numBeforeMinDepth++;
+// }
+// }
+//
+// minDepth -= numBeforeMinDepth - 1;
+// for( i = 0; i < numElementsNotInLayout; i++ )
+// {
+// element = target.getElementAt( indicesNotInLayout[ i ] );
+// if( !element ) continue;
+// if( indicesNotInLayout[ i ] > indicesInLayout[ animationIndex ] )
+// {
+// element.depth = maxDepth;
+// maxDepth++;
+// }
+// else
+// {
+// element.depth = minDepth;
+// minDepth++;
+// }
+// }
+//
+// target.validateNow();
+ }
+
+ /**
+ * @private
+ *
+ * A convenience method used to transform an element by applying
+ * the current values if the TransforCalulator instance.
+ */
+// private function elementTransformAround( element:IVisualElement ):void
+// {
+// var halfWidth:Number = element.width / 2;
+// var halfHeight:Number = element.height / 2;
+// var offsetX:Number = halfWidth * ( _elementHorizontalCenterMultiplier - 0.5 ) * 2;
+// var offsetY:Number = halfHeight * ( _elementVerticalCenterMultiplier - 0.5 ) * 2;
+//
+// element.transformAround( new Vector3D( element.width / 2, element.height / 2, 0 ),
+// null,
+// null,
+// new Vector3D( _transformCalculator.x - offsetX, _transformCalculator.y - offsetY, _transformCalculator.z ),
+// null,
+// new Vector3D( _transformCalculator.xRotation, _transformCalculator.yRotation, 0 ),
+// new Vector3D( _transformCalculator.x - offsetX, _transformCalculator.y - offsetY, _transformCalculator.z ),
+// false );
+//
+// }
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override public function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number):void
+ {
+// if( this.unscaledWidth != unscaledWidth || this.unscaledHeight != unscaledHeight ) _sizeChanged = true;
+
+ if( _horizontalAlignChange )
+ {
+ _horizontalAlignChange = false;
+// _indicesInViewChanged = true;
+
+ switch( _horizontalAlign )
+ {
+ case HorizontalAlign.LEFT :
+ {
+ _horizontalCenterMultiplier = 0;
+ break;
+ }
+ case HorizontalAlign.RIGHT :
+ {
+ _horizontalCenterMultiplier = 1;
+ break;
+ }
+ default :
+ {
+ _horizontalCenterMultiplier = 0.5;
+ }
+ }
+ }
+
+ if( _verticalAlignChange )
+ {
+ _verticalAlignChange = false;
+// _indicesInViewChanged = true;
+
+ switch( _verticalAlign )
+ {
+ case VerticalAlign.TOP :
+ {
+ _verticalCenterMultiplier = 0;
+ break;
+ }
+ case VerticalAlign.BOTTOM :
+ {
+ _verticalCenterMultiplier = 1;
+ break;
+ }
+ default :
+ {
+ _verticalCenterMultiplier = 0.5;
+ }
+ }
+ }
+
+ if( _elementHorizontalAlignChange )
+ {
+ _elementHorizontalAlignChange = false;
+// _indicesInViewChanged = true;
+
+ switch( _elementHorizontalAlign )
+ {
+ case HorizontalAlign.LEFT :
+ {
+ _elementHorizontalCenterMultiplier = 0;
+ break;
+ }
+ case HorizontalAlign.RIGHT :
+ {
+ _elementHorizontalCenterMultiplier = 1;
+ break;
+ }
+ default :
+ {
+ _elementHorizontalCenterMultiplier = 0.5;
+ }
+ }
+ }
+
+ if( _elementVerticalAlignChange )
+ {
+ _elementVerticalAlignChange = false;
+// _indicesInViewChanged = true;
+
+ switch( _elementVerticalAlign )
+ {
+ case VerticalAlign.TOP :
+ {
+ _elementVerticalCenterMultiplier = 0;
+ break;
+ }
+ case VerticalAlign.BOTTOM :
+ {
+ _elementVerticalCenterMultiplier = 1;
+ break;
+ }
+ default :
+ {
+ _elementVerticalCenterMultiplier = 0.5;
+ }
+ }
+ }
+
+ super.updateDisplayList( unscaledWidth, unscaledHeight );
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override protected function updateDisplayListBetween():void
+ {
+ super.updateDisplayListBetween();
+
+ if( sizeChangedInLayoutPass )
+ {
+// _indicesInViewChanged = true;
+ if( !isNaN( _horizontalAlignOffsetPercent ) ) _horizontalAlignOffset = unscaledHeight * ( _horizontalAlignOffsetPercent / 100 );
+ if( !isNaN( _verticalAlignOffsetPercent ) ) _verticalAlignOffset = unscaledHeight * ( _verticalAlignOffsetPercent / 100 );
+ }
+
+ _transformCalculator.updateForLayoutPass( _horizontalCenterMultiplier, _verticalCenterMultiplier, _rotateX, _rotateY );
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override protected function updateDisplayListVirtual():void
+ {
+ super.updateDisplayListVirtual();
+
+ var element:IVisualElement;
+ var depths:Vector.<int> = new Vector.<int>();
+
+ for each( element in _displayedElements )
+ {
+ element.visible = false;
+ }
+
+ _displayedElements = new Vector.<IVisualElement>();
+
+ for( var i:int = firstIndexInView; i <= lastIndexInView; i++ )
+ {
+ element = target.getVirtualElementAt( indicesInLayout[ i ] );
+ depths.push( indicesInLayout[ i ] );
+ updateVisibleElementAt( element, i );
+ }
+
+ updateDepths( depths );
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override protected function updateDisplayListReal():void
+ {
+ super.updateDisplayListReal();
+
+ var element:IVisualElement;
+ var depths:Vector.<int> = new Vector.<int>();
+
+ _displayedElements = 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);
+ }
+ 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() );
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override protected function updateIndicesInView():void
+ {
+ super.updateIndicesInView();
+
+ if( _numUnselectedElements > 0 )
+ {
+ const ceilIndex:int = Math.ceil( animationValue );
+ const floorIndex:int = Math.floor( animationValue );
+ const firstIndexInView:int = Math.max( ceilIndex - _numUnselectedElements, 0 );
+
+ var numIndicesInView:int = ( _numUnselectedElements * 2 ) + 1;
+ // If the number of elements on the left are less than _numUnselectedElements
+ if( floorIndex < _numUnselectedElements )
+ {
+ numIndicesInView -= _numUnselectedElements - floorIndex;
+ }
+ // If we are mid transition, we don't need the last item
+ else if( floorIndex != animationValue )
+ {
+ numIndicesInView -= 1;
+ }
+
+ // If we are at the end of the list of elements
+ if( floorIndex + _numUnselectedElements >= numElementsInLayout )
+ {
+ numIndicesInView -= _numUnselectedElements - ( ( numElementsInLayout - 1 ) - floorIndex );
+ }
+
+ indicesInView( firstIndexInView, numIndicesInView );
+ }
+ else
+ {
+ indicesInView( 0, numElementsInLayout );
+ }
+ }
+
+
+ }
+}
+
+
+
+import flash.geom.ColorTransform;
+import flash.geom.Point;
+import flash.geom.Vector3D;
+
+import mx.core.IVisualElement;
+
+import ws.tink.spark.layouts.CarouselLayout;
+
+
+internal class TransformValues
+{
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ public function TransformValues( layout:CarouselLayout )
+ {
+ _layout = layout;
+ _colorTransform = new ColorTransform();
+ }
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ private var _layout : CarouselLayout;
+
+ 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;
+
+ private var _rx : Number;
+ private var _ry : Number;
+ private var _rz : Number;
+
+ // Number of items
+ private var _ni : Number;
+ private var _an : 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;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // x
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for x.
+ */
+ private var _x:Number;
+
+// /**
+// * x
+// *
+// * @langversion 3.0
+// * @playerversion Flash 10
+// * @playerversion AIR 1.5
+// * @productversion Flex 4
+// */
+// public function get x():Number
+// {
+// return _x;
+// }
+
+
+ //----------------------------------
+ // y
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for y.
+ */
+ private var _y:Number;
+
+// /**
+// * y
+// *
+// * @langversion 3.0
+// * @playerversion Flash 10
+// * @playerversion AIR 1.5
+// * @productversion Flex 4
+// */
+// public function get y():Number
+// {
+// return _y;
+// }
+
+
+ //----------------------------------
+ // z
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for z.
+ */
+ private var _z:Number;
+
+// /**
+// * z
+// *
+// * @langversion 3.0
+// * @playerversion Flash 10
+// * @playerversion AIR 1.5
+// * @productversion Flex 4
+// */
+// public function get z():Number
+// {
+// return _z;
+// }
+
+
+ //----------------------------------
+ // xRotation
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for xRotation.
+ */
+ private var _xRotation:Number;
+
+// /**
+// * xRotation
+// *
+// * @langversion 3.0
+// * @playerversion Flash 10
+// * @playerversion AIR 1.5
+// * @productversion Flex 4
+// */
+// public function get xRotation():Number
+// {
+// return _xRotation;
+// }
+
+
+ //----------------------------------
+ // yRotation
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage property for yRotation.
+ */
+ private var _yRotation:Number;
+
+ /**
+ * yRotation
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+// public function get yRotation():Number
+// {
+// return _yRotation;
+// }
+//
+//
+ public function get radiusZ():Number
+ {
+ return _rz;
+ }
+
+
+ //----------------------------------
+ // 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;
+ }
+
+ _rx = _layout.radiusX;
+ _ry = _layout.radiusY;
+ _rz = _layout.radiusZ;
+
+ if( isNaN( _rz ) ) _rz = Math.abs( ( Math.abs( _rx ) > Math.abs( _ry ) ) ? _rx : _ry );
+
+ _rotY = rotY;
+ _rotX = rotX;
+
+ const numElements:int = _layout.numUnselectedElements < 0 ? 0 : _layout.numUnselectedElements;
+
+ _an = numElements ? _layout.angle / ( numElements * 2 ) : _layout.angle / _layout.numElementsInLayout;
+ }
+
+ /**
+ * circular
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ private function layout( index:Number ):void
+ {
+ const degree:Number = _an * index;
+ const radian:Number = degree * Math.PI / 180;
+
+ _x = _cx + _ho + ( Math.sin( radian ) * _rx );
+ _y = _cy + _vo + ( Math.sin( radian ) * _ry );
+ _z = _rz - ( Math.cos( radian ) * _rz );
+
+ _yRotation = _rx && _rotY != 0 ? -( angle( _x, _z, _cx + _ho, _rz ) - 90 ) * _rotY : 0;
+ _xRotation = _ry && _rotX != 0 ? ( angle( _y , _z, _cy + _vo, _rz ) - 90 ) * _rotX : 0;
+
+ if( _rz < 0 )
+ {
+ if( _yRotation ) _yRotation += 180;
+ if( _xRotation ) _xRotation += 180;
+ }
+ }
+
+ public function angle( x1:Number, y1:Number, x2:Number, y2:Number ):Number
+ {
+ return Math.atan2( y2 - y1, x2 - x1 ) * ( 180 / Math.PI );
+ }
+
+
+ /**
+ * 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;
+
+ layout( ( i - _index ) - _indexOffset );
+
+ if( _c > -1 )
+ {
+ const radian:Number = ( _layout.angle / 2 ) * Math.PI / 180;
+ const maxDepth:Number = _rz - ( Math.cos( radian ) * _rz )
+ const v:Number = ( _z / maxDepth ) * _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