flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cza...@apache.org
Subject [02/10] moved new components Accordion, DataAccordion, InlineScroller .. new layouts AccordionLayout, CarouselLayout, CoverflowLayout, StackLayout .. and many more from tinks whiteboard to experimental project
Date Wed, 20 Mar 2013 13:01:37 GMT
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/0d3bf3b6/frameworks/projects/experimental/src/spark/layouts/supportClasses/NavigatorLayoutBase.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/layouts/supportClasses/NavigatorLayoutBase.as b/frameworks/projects/experimental/src/spark/layouts/supportClasses/NavigatorLayoutBase.as
new file mode 100644
index 0000000..ce3e7bc
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/layouts/supportClasses/NavigatorLayoutBase.as
@@ -0,0 +1,1329 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package spark.layouts.supportClasses
+{
+	import flash.display.DisplayObject;
+	import flash.geom.ColorTransform;
+	import flash.geom.Rectangle;
+	import flash.net.getClassByAlias;
+	
+	import mx.core.IVisualElement;
+	import mx.core.mx_internal;
+	import mx.events.ChildExistenceChangedEvent;
+	import mx.events.FlexEvent;
+	
+	import spark.components.DataGroup;
+	import spark.components.Scroller;
+	import spark.components.supportClasses.GroupBase;
+	import spark.core.NavigationUnit;
+	import spark.events.IndexChangeEvent;
+	import spark.layouts.supportClasses.LayoutBase;
+	import spark.primitives.supportClasses.GraphicElement;
+	
+	use namespace mx_internal;
+	
+	
+	//--------------------------------------
+	//  Events
+	//--------------------------------------
+	
+	/**
+	 *  @eventType spark.events.IndexChangeEvent.CHANGE
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	[Event(name="change", type="spark.events.IndexChangeEvent")]
+	
+	/**
+	 *  @eventType mx.events.FlexEvent.VALUE_COMMIT
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	[Event(name="valueCommit", type="mx.events.FlexEvent")]
+	
+	
+	/**
+	 *  A NavigatorLayoutBase class is a base class for navigator layouts.
+	 * 
+	 *  <p>More info coming.</p>.
+	 * 
+	 *  @mxml
+	 *
+	 *  <p>The <code>&lt;st:NavigatorLayoutBase&gt;</code> tag inherits all of the
+	 *  tag attributes of its superclass, and adds the following tag attributes:</p>
+	 *
+	 *  <pre>
+	 *  &lt;st:NavigatorLayoutBase
+	 *    <strong>Properties</strong>
+	 * 	  firstIndexInView="<i>calculated</i>"
+	 *    indicesInLayout="<i>calculated</i>"
+	 *    lastIndexInView="<i>calculated</i>"
+	 * 	  numElementsInLayout="<i>calculated</i>"
+	 *    numElementsNotInLayout="<i>calculated</i>"
+	 * 	  numIndicesInView="<i>calculated</i>"
+	 *    renderingData="<i>calculated</i>"
+	 * 	  scrollBarDirection="horizontal|vertical"
+	 *    selectedIndex="-1"
+	 *    unscaledWidth="<i>calculated</i>"
+	 *    unscaledHeight="<i>calculated</i>"
+	 *    useScrollBarForNavigation="true"
+	 * 
+	 *    <strong>Events</strong>
+	 *    change="<i>No default</i>"
+	 *    valueCommit="<i>No default</i>"
+	 *  /&gt;
+	 *  </pre>
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public class NavigatorLayoutBase extends LayoutBase implements INavigatorLayout
+	{
+		
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function NavigatorLayoutBase()
+		{
+			super();
+			
+			//			useVirtualLayout = true;
+			
+			useScrollBarForNavigation = true;
+			
+			_scrollBarDirection = LayoutAxis.VERTICAL;
+		}	
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 *	Flag to indicate the selectedIndex changed after the target was changed.
+		 */
+		private var _selectedIndexChangedAfterTargetChanged	: Boolean;
+		
+		/**
+		 *  @private
+		 *	Flag to indicate the IVisualElements in the target have changed.
+		 */
+		private var _elementsChanged: Boolean;
+		
+		/**
+		 *  @private
+		 *	Flag to indicate the target has changed.
+		 */
+		private var _targetChanged:Boolean;
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//----------------------------------
+		//  lastIndexInView
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 *	Storage property for lastIndexInView.
+		 */
+		private var _lastIndexInView		: int = -1;
+		
+		/**
+		 *  lastIndexInView
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get lastIndexInView():int
+		{
+			return _lastIndexInView;
+		}
+		
+		
+		//----------------------------------
+		//  firstIndexInView
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 *	Storage property for firstIndexInView.
+		 */
+		private var _firstIndexInView		: int = -1;
+		
+		/**
+		 *  firstIndexInView
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get firstIndexInView():int
+		{
+			return _firstIndexInView;
+		}
+		
+		
+		//----------------------------------
+		//  numVisibleElements
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 *	Storage property for numIndicesInView.
+		 */
+		private var _numIndicesInView		: int = -1;
+		
+		/**
+		 *  inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get numIndicesInView():int
+		{
+			return _numIndicesInView;
+		}
+		
+		
+		//----------------------------------
+		//  renderingData
+		//---------------------------------- 
+		
+		/**
+		 *  inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get renderingData():Boolean
+		{
+			if( target is DataGroup )
+			{
+				var dataGroup:DataGroup = DataGroup( target );
+				if( dataGroup.itemRenderer || dataGroup.itemRendererFunction != null ) return true;
+			}
+			
+			return false;
+		}
+		
+		//		[Inspectable(category="General", enumeration="false,true", defaultValue="true")]
+		//		public function get stepScrollBar():Boolean
+		//		{
+		//			return _stepScrollBar;
+		//		}
+		//		public function set stepScrollBar(value:Boolean):void
+		//		{
+		//			if( value == _stepScrollBar ) return;
+		//			
+		//			_stepScrollBar = value;
+		//			
+		//			invalidateTargetDisplayList();
+		//		}
+		
+		
+		//----------------------------------
+		//  selectedIndexOffset
+		//---------------------------------- 
+		//		
+		//		/**
+		//		 *  @private
+		//		 *	Storage property for selectedIndexOffset.
+		//		 */
+		//		private var _selectedIndexOffset	: Number = 0;
+		//		
+		//		/**
+		//		 *  inheritDoc
+		//		 *  
+		//		 *  @langversion 3.0
+		//		 *  @playerversion Flash 10
+		//		 *  @playerversion AIR 1.5
+		//		 *  @productversion Flex 4
+		//		 */
+		//		public function get selectedIndexOffset():Number
+		//		{
+		//			return _selectedIndexOffset;
+		//		}
+		//		/**
+		//		 *  @private
+		//		 */
+		//		public function set selectedIndexOffset( value:Number ):void
+		//		{
+		//			if( _useScrollBarForNavigation )
+		//			{
+		//				updateScrollBar( _selectedIndex, value );
+		//			}
+		//			else
+		//			{
+		//				updateSelectedIndex( _selectedIndex, value );
+		//			}
+		//		}
+		
+		
+		//----------------------------------
+		//  selectedElement
+		//---------------------------------- 
+		
+		private var _selectedElement:IVisualElement;
+		
+		/**
+		 *  @inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get selectedElement():IVisualElement
+		{
+			return _selectedElement;
+		}
+		
+		
+		
+		//----------------------------------
+		//  selectedIndex
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 *	Storage property for selectedIndex.
+		 */
+		private var _selectedIndex			: int = -1;
+		
+		/**
+		 *  @private
+		 */
+		private var _programmaticSelectedIndex:int;
+		
+		[Bindable( event="change" )]
+		[Bindable( event="valueCommit" )]
+		/**
+		 *  @inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get selectedIndex():int
+		{
+			return _proposedSelectedIndex == -1 ? _selectedIndex : _proposedSelectedIndex;
+		}
+		/**
+		 *  @private
+		 */
+		public function set selectedIndex( value:int ):void
+		{
+			if( selectedIndex == value ) return;
+			
+			_programmaticSelectedIndex = value;
+			if( _targetChanged ) _selectedIndexChangedAfterTargetChanged = true;
+			
+			if( _useScrollBarForNavigation && getScroller() )
+			{
+				updateScrollBar( value, 0 );
+			}
+			else
+			{
+				//				updateSelectedIndex( value, 0 );
+				invalidateSelectedIndex( value, 0 );
+			}
+		}
+		
+		
+		//----------------------------------
+		//  useScrollBarForNavigation
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 *  Storage property for useScrollBarForNavigation.
+		 */
+		private var _useScrollBarForNavigation:Boolean;
+		
+		[Inspectable(category="General", enumeration="false,true", defaultValue="true")]
+		/**
+		 *  useScrollBarForNavigation
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get useScrollBarForNavigation():Boolean
+		{
+			return _useScrollBarForNavigation;
+		}
+		/**
+		 *  @private
+		 */
+		public function set useScrollBarForNavigation(value:Boolean):void
+		{
+			if( value == _useScrollBarForNavigation ) return;
+			
+			_useScrollBarForNavigation = value;
+			
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  scrollBarDirection
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for scrollBarDirection.
+		 */
+		private var _scrollBarDirection		: String;
+		
+		[Inspectable(category="General", enumeration="horizontal,vertical", defaultValue="vertical")]
+		
+		/**
+		 *  The direction of the ScrollBar to use for navigation.
+		 * 
+		 * 	<p>If <code>scrollBarDirection</code> is set to <code>LayoutAxis.VERTICAL</code>
+		 *  a VScrollBar will be displayed in the views Scroller.
+		 * 	If set to <code>LayoutAxis.HORIZONTAL</code> a HScrollBar will be displayed
+		 * 	in the views Scroller.</p>
+		 *  
+		 * 	<p>If the viewport doesn't have a Scroller or <code>useScrollBarForNavigation</code>
+		 *  is set to <code>false</code> a ScrollBar is displayed.</p>
+		 * 
+		 *  <p>The default value is <code>LayoutAxis.VERTICAL</code></p>
+		 *
+		 * 	@see mx.controls.scrollClasses.LayoutAxis
+		 *  @see spark.layouts.NavigatorLayoutBase#useScrollBarForNavigation
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get scrollBarDirection():String
+		{
+			return _scrollBarDirection;
+		}
+		/**
+		 *  @private
+		 */
+		public function set scrollBarDirection( value:String ) : void
+		{
+			if( _scrollBarDirection == value ) return;
+			
+			switch( value )
+			{
+				case LayoutAxis.HORIZONTAL :
+				case LayoutAxis.VERTICAL :
+				{
+					_scrollBarDirection = value;
+					if( target ) scrollPositionChanged();
+					invalidateTargetDisplayList();
+					break;
+				}
+				default :
+				{
+					
+				}
+			}
+		}
+		
+		
+		//----------------------------------
+		//  numElementsInLayout
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for numElementsInLayout.
+		 */
+		private var _numElementsInLayout:int = -1;
+		
+		/**
+		 *  Returns an <code>int</code> specifying number of elements included in the layout.
+		 * 
+		 *  @see mx.core.UIComponent#includeInLayout
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get numElementsInLayout():int
+		{
+			return _numElementsInLayout;
+		}
+		
+		
+		//----------------------------------
+		//  numElementsNotInLayout
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for numElementsNotInLayout.
+		 */
+		private var _numElementsNotInLayout:int = -1;
+		
+		/**
+		 *  Returns an <code>int</code> specifying number of elements not included in the layout.
+		 * 
+		 *  @see mx.core.UIComponent#includeInLayout
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get numElementsNotInLayout():int
+		{
+			return _numElementsNotInLayout;
+		}
+		
+		
+		//----------------------------------
+		//  indicesInLayout
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for indicesInLayout.
+		 */
+		private var _indicesInLayout:Vector.<int>;
+		
+		/**
+		 *  A convenience method for determining the elements included in the layout.
+		 * 
+		 *  @return A list of the element indices not included in the layout.
+		 * 
+		 *  @see mx.core.UIComponent#includeInLayout
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get indicesInLayout():Vector.<int>
+		{
+			return _indicesInLayout;
+		}
+		
+		
+		//----------------------------------
+		//  indicesNotInLayout
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for indicesNotInLayout.
+		 */
+		private var _indicesNotInLayout:Vector.<int>;
+		
+		/**
+		 *  A convenience method for determining the elements excluded from the layout.
+		 * 
+		 *  @return A list of the element indices not included in the layout.
+		 * 
+		 *  @see mx.core.UIComponent#includeInLayout
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get indicesNotInLayout():Vector.<int>
+		{
+			return _indicesNotInLayout;
+		}
+		
+		
+		//----------------------------------
+		//  unscaledWidth
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for unscaledWidth.
+		 */
+		private var _unscaledWidth	: Number;
+		
+		/**
+		 *  A convenience method for determining the unscaled width of the viewport.
+		 *
+		 *  @return A Number which is unscaled width of the component
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get unscaledWidth():Number
+		{
+			return _unscaledWidth;
+		}
+		
+		
+		//----------------------------------
+		//  unscaledHeight
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *  Storage property for unscaledHeight.
+		 */
+		private var _unscaledHeight	: Number;
+		
+		/**
+		 *  A convenience method for determining the unscaled height of the viewport.
+		 *
+		 *  @return A Number which is unscaled height of the component
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get unscaledHeight():Number
+		{
+			return _unscaledHeight;
+		}
+		
+		
+		
+		
+		
+		//TODO tink comment and implement properly
+		protected var _elements	: Vector.<IVisualElement>;
+		public function get elements():Vector.<IVisualElement>
+		{
+			return _elements;
+		}
+		
+		
+		private var _sizeChangedInLayoutPass:Boolean;
+		public function get sizeChangedInLayoutPass():Boolean
+		{
+			return _sizeChangedInLayoutPass;
+		}
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @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;
+			
+			if( target ) restoreElements();
+			super.target = value;
+			
+			_targetChanged = true;
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		
+		override public function measure():void
+		{
+			updateElements();
+			updateElementsInLayout();
+		}
+		
+		/**
+		 *  @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 );
+			
+			_sizeChangedInLayoutPass = _unscaledWidth != unscaledWidth || _unscaledHeight != unscaledHeight;
+			_unscaledWidth = unscaledWidth;
+			_unscaledHeight = unscaledHeight;
+			
+			//			if( _elementsChanged || _targetChanged )
+			//			{
+			//				_elementsChanged = false;
+			//				updateElements();
+			//			}
+			
+			var scrollPositionInvalid:Boolean;
+			
+			//TODO support includeInLayout
+			// Only really want to do this if...
+			// a) the number of elements have changed
+			// b) includeLayout has changed on an element
+			 updateElementsInLayout();
+			
+			// TODO This was move to measure, but if the target has an explicit size
+			// measure isn't invoked, so checking it here too.
+			// If fired in measure this should no longer get invoked due to
+			// the check in place.
+			if( !indicesInLayout || target.numElements != indicesInLayout.length + indicesNotInLayout.length )
+			{
+				updateElements();
+				updateElementsInLayout();
+			}
+			
+			//			if( numElementsInLayout != _numElementsInLayout ) scrollPositionInvalid = true;
+			
+			// If the selected index has changed exit the method as its handle in selectedIndex
+			if( _numElementsInLayout == 0 )
+			{
+				//				_selectedIndex = -1;
+				_selectedIndexInvalid = true;
+				_proposedSelectedIndex = -1;
+				//				_proposedSelectedIndexOffset = 0;
+			}
+			else if( selectedIndex == -1 )
+			{
+				_selectedIndexInvalid = true;
+				_proposedSelectedIndex = 0;
+				//				_proposedSelectedIndexOffset = 0;
+				//				scrollPositionChanged();
+				scrollPositionInvalid = true;
+			}
+			else if( selectedIndex >= _numElementsInLayout )
+			{
+				_selectedIndexInvalid = true;
+				_proposedSelectedIndex = 0;
+				scrollPositionInvalid = true;
+			}
+			
+			if( _targetChanged )
+			{
+				_targetChanged = false;
+				
+				// Only update if the target was changed after the selectedIndex
+				if( !_selectedIndexChangedAfterTargetChanged )
+				{
+					//					scrollPositionChanged();
+					scrollPositionInvalid = true;
+				}
+				else
+				{
+					_selectedIndexChangedAfterTargetChanged = false;
+				}
+			}
+			
+			if( scrollPositionInvalid ) scrollPositionChanged();
+			
+			if( _useScrollBarForNavigation )
+			{
+				updateScrollerForNavigation();
+			}
+			else
+			{
+				updateScrollerForContent();
+			}
+			
+			const selectedIndexChanged:Boolean = _selectedIndexInvalid;
+			
+			if( _selectedIndexInvalid )
+			{
+				_selectedIndexInvalid = false;
+				_selectedIndex = numElementsInLayout ? _proposedSelectedIndex % numElementsInLayout : _proposedSelectedIndex;
+				_proposedSelectedIndex = -1;
+				
+				//				updateSelectedIndex( _proposedSelectedIndex, _proposedSelectedIndexOffset );
+				//				updateSelectedIndex( _proposedSelectedIndex, 0 );
+			}
+			
+			if( selectedIndex > -1 )
+			{
+				if( useVirtualLayout )
+				{
+					_selectedElement = target ? target.getVirtualElementAt( indicesInLayout[ selectedIndex ] ) : null;
+				}
+				else
+				{
+					_selectedElement = target ? target.getElementAt( indicesInLayout[ selectedIndex ] ) : null;
+				}
+			}
+			
+			updateDisplayListBetween();
+			
+			if( useVirtualLayout )
+			{
+				updateDisplayListVirtual();
+			}
+			else
+			{
+				updateDisplayListReal();
+			}
+			
+			_sizeChangedInLayoutPass = false;
+			
+			if( selectedIndexChanged )
+			{
+				if( _programmaticSelectedIndex == selectedIndex )
+				{
+					dispatchEvent( new FlexEvent( FlexEvent.VALUE_COMMIT ) );
+				}
+				else
+				{
+					dispatchEvent( new IndexChangeEvent( IndexChangeEvent.CHANGE ) );
+				}
+				_programmaticSelectedIndex = -2;
+			}
+		}
+		
+		protected function updateDisplayListBetween():void
+		{
+		}
+		
+		protected function updateElements():void
+		{
+			var elts:Array;
+			if( target is DataGroup )
+			{
+				var dataGroup:DataGroup = DataGroup( target );
+				
+				// If the user isn't using itemRenderers instead directly adding children to the dataProvider
+				if( !dataGroup.itemRenderer && dataGroup.itemRendererFunction == null && dataGroup.dataProvider )
+				{
+					elts = dataGroup.dataProvider.toArray();
+				}
+				else
+				{
+					elts = new Array();
+					for( var i:int = 0; i < dataGroup.numChildren; i++ )
+					{
+						elts.push( dataGroup.getChildAt( i ) );
+					}
+				}
+			}
+			else
+			{
+				try
+				{
+					elts = target[ "getMXMLContent" ]();
+				}
+				catch( e:Error )
+				{
+					elts = target[ "toArray" ]();
+				}
+				catch( e:Error )
+				{
+					throw new Error( "NavigatorLayoutBase cannot be used as a layout for this kind of container" );
+					elts = new Array();
+				}
+			}
+			
+			_elements = ( elts ) ? Vector.<IVisualElement>( elts ) : new Vector.<IVisualElement>();
+		}
+		
+		protected function updateElementsInLayout():void
+		{
+			_indicesInLayout = new Vector.<int>();
+			_indicesNotInLayout = new Vector.<int>();
+			
+			var i:int;
+			var numElements:int;
+			
+			if( renderingData )
+			{
+				numElements = target.numElements;
+				for( i = 0; i < numElements; i++ )
+				{
+					_indicesInLayout.push( i );
+				}
+				
+				_numElementsInLayout = _indicesInLayout.length;
+				_numElementsNotInLayout = _indicesNotInLayout.length;
+				return;
+			}
+			
+			numElements = _elements.length;
+			for( i = 0; i < numElements; i++ )
+			{
+				if( _elements[ i ].includeInLayout )
+				{
+					_indicesInLayout.push( i );
+				}
+				else
+				{
+					_indicesNotInLayout.push( i );
+				}
+			}
+			_numElementsInLayout = _indicesInLayout.length;
+			_numElementsNotInLayout = _indicesNotInLayout.length;
+		}
+		
+		protected function updateScrollerForNavigation():void
+		{
+			if( !target ) return;
+			
+			var scroller:Scroller = getScroller();
+			switch( scrollBarDirection )
+			{
+				case LayoutAxis.HORIZONTAL :
+				{
+					target.setContentSize( unscaledWidth * _numElementsInLayout, unscaledHeight );
+					if( scroller && scroller.horizontalScrollBar ) 
+					{
+						scroller.horizontalScrollBar.stepSize = unscaledWidth;
+						target.horizontalScrollPosition = selectedIndex * unscaledWidth;
+					}
+					break;
+				}
+				case LayoutAxis.VERTICAL :
+				{
+					target.setContentSize( unscaledWidth, unscaledHeight * _numElementsInLayout );
+					if( scroller && scroller.verticalScrollBar )
+					{
+						scroller.verticalScrollBar.stepSize = unscaledHeight;
+						target.verticalScrollPosition = selectedIndex * unscaledHeight;
+					}
+					break;
+				}
+			}
+		}
+		
+		protected function updateScrollerForContent():void
+		{
+			target.setContentSize( unscaledWidth, unscaledHeight );
+		}
+		
+		/**
+		 *  @private
+		 *  Update the layout of the virtualized elements in view.
+		 */
+		protected function updateDisplayListVirtual():void
+		{
+			//			var numElementsNoInLayout:int = _indicesNotInLayout.length;
+			//			for( var i:int = 0; i < numElementsNoInLayout; i++ )
+			//			{
+			//				target.getVirtualElementAt( _indicesNotInLayout[ i ] );
+			//			}
+		}
+		
+		/**
+		 *  @private
+		 *  Update the layout of all elements that in target.
+		 */
+		protected function updateDisplayListReal():void
+		{
+			//			var numElementsNoInLayout:int = _indicesNotInLayout.length;
+			//			for( var i:int = 0; i < numElementsNoInLayout; i++ )
+			//			{
+			//				target.getElementAt( _indicesNotInLayout[ i ] );
+			//			}
+		}
+		
+		protected function setElementLayoutBoundsSize( element:IVisualElement, postLayoutTransform:Boolean = true ):void
+		{
+			if( !element ) return;
+			element.setLayoutBoundsSize(
+				getElementLayoutBoundsWidth( element, postLayoutTransform ),
+				getElementLayoutBoundsHeight( element, postLayoutTransform ),
+				postLayoutTransform );
+		}
+		
+		protected function getElementLayoutBoundsWidth( element:IVisualElement, postLayoutTransform:Boolean = true ):Number
+		{
+			return isNaN( element.percentWidth ) ? element.getPreferredBoundsWidth( postLayoutTransform ) : unscaledWidth * ( element.percentWidth / 100 )
+		}
+		
+		protected function getElementLayoutBoundsHeight( element:IVisualElement, postLayoutTransform:Boolean = true ):Number
+		{
+			return isNaN( element.percentHeight ) ? element.getPreferredBoundsHeight( postLayoutTransform ) : unscaledHeight * ( element.percentHeight / 100 );
+		}
+		
+		override protected function scrollPositionChanged() : void
+		{
+			if( !target || !_useScrollBarForNavigation ) return;
+			
+			var scrollPosition:Number;
+			var indexMaxScroll:Number;
+			switch( scrollBarDirection )
+			{
+				case LayoutAxis.HORIZONTAL :
+				{
+					scrollPosition = horizontalScrollPosition;
+					indexMaxScroll = ( _unscaledWidth * _numElementsInLayout ) / _numElementsInLayout;
+					break;
+				}
+				case LayoutAxis.VERTICAL :
+				{
+					scrollPosition = verticalScrollPosition;
+					indexMaxScroll = ( _unscaledHeight * _numElementsInLayout ) / _numElementsInLayout;
+					break;
+				}
+			}
+			
+			if( target.numElements )
+			{
+				//				updateSelectedIndex( Math.round( scrollPosition / indexMaxScroll ),
+				//								( scrollPosition % indexMaxScroll > indexMaxScroll / 2 ) ? -( 1 - ( scrollPosition % indexMaxScroll ) / indexMaxScroll ) : ( scrollPosition % indexMaxScroll ) / indexMaxScroll );			
+				invalidateSelectedIndex( Math.round( scrollPosition / indexMaxScroll ),
+					( scrollPosition % indexMaxScroll > indexMaxScroll / 2 ) ? -( 1 - ( scrollPosition % indexMaxScroll ) / indexMaxScroll ) : ( scrollPosition % indexMaxScroll ) / indexMaxScroll );			
+			}
+			else
+			{
+				//				updateSelectedIndex( -1, NaN );
+				invalidateSelectedIndex( -1, NaN );
+			}
+		}
+		
+		protected function updateScrollBar( index:int, offset:Number ):void
+		{
+			if( !target ) return;
+			
+			var scroller:Scroller = getScroller();
+			switch( scrollBarDirection )
+			{
+				case LayoutAxis.HORIZONTAL :
+				{
+					if( !isNaN( unscaledWidth ) ) target.horizontalScrollPosition = ( index + offset ) * unscaledWidth;
+				}
+				case LayoutAxis.VERTICAL :
+				{
+					if( !isNaN( unscaledHeight ) ) target.verticalScrollPosition = (  index + offset ) * unscaledHeight;
+				}
+			}
+		}
+		
+		/**
+		 *  Updates the selectedIndex and selectedIndexOffset properties if they have changed.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */  
+		//		protected function updateSelectedIndex( index:int, offset:Number ):void
+		//		{
+		////			trace( "updateSelectedIndex", index, offset );
+		//			if( _selectedIndex == index ) return;// && ( _selectedIndexOffset == offset || ( isNaN( _selectedIndexOffset ) && isNaN( offset ) ) ) ) return;
+		//			
+		//			_proposedSelectedIndex = -1;
+		////			_proposedSelectedIndexOffset = 0;
+		//			
+		//			_selectedIndexChanged = _selectedIndex != index;
+		//			_selectedIndex = index;
+		////			_selectedIndexOffset = offset;
+		////			invalidateTargetDisplayList();
+		//		}
+		
+		private var _proposedSelectedIndex:int = -1;
+		//		private var _proposedSelectedIndexOffset:Number = 0;;
+		private var _selectedIndexInvalid:Boolean;
+		protected function invalidateSelectedIndex( index:int, offset:Number ):void
+		{
+			if( _proposedSelectedIndex == index ) return;// && ( _proposedSelectedIndexOffset == offset || ( isNaN( _proposedSelectedIndexOffset ) && isNaN( offset ) ) ) ) return;
+			
+			_selectedIndexInvalid = true;
+			_proposedSelectedIndex = index;// % numElementsInLayout;
+			//			_proposedSelectedIndexOffset = offset;
+			invalidateTargetDisplayList();
+		}
+		
+		protected function indicesInView( firstIndexinView:int, numIndicesInView:int ):void
+		{
+			if( firstIndexinView == _firstIndexInView && _numIndicesInView == numIndicesInView ) return;
+			
+			_firstIndexInView = firstIndexinView;
+			_numIndicesInView = numIndicesInView;
+			
+			_lastIndexInView = _firstIndexInView + ( _numIndicesInView - 1 );
+			
+			invalidateTargetDisplayList();
+		}
+		
+		protected function invalidateTargetDisplayList() : void
+		{
+			if( !target ) return;
+			
+			target.invalidateDisplayList();
+		}
+		
+		public function invalidateTargetSize() : void
+		{
+			if( !target ) return;
+			
+			target.invalidateSize();
+		}
+		
+		/**
+		 *  Returns a reference to the views Scroller if there is one.
+		 *	If there is no Scroller for the view <code>null</code> is returned.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		protected function getScroller():Scroller
+		{
+			if( !target ) return null;
+			
+			// TODO changes for NavigatorApplication, look into
+			try
+			{
+				return target.parent.parent as Scroller;
+			}
+			catch( e:Error )
+			{
+				
+			}
+			
+			return null;
+		}
+		
+		//		/**
+		//		 *  @inheritDoc
+		//		 *  
+		//		 *  @langversion 3.0
+		//		 *  @playerversion Flash 10
+		//		 *  @playerversion AIR 1.5
+		//		 *  @productversion Flex 4
+		//		 */
+		//		override public function elementAdded( index:int ):void
+		//		{
+		//			super.elementAdded( index );
+		//			
+		//			_elementsChanged = true;
+		//			
+		//			invalidateTargetDisplayList();
+		//			//TODO maybe add a listener here for "includeInLayoutChanged"
+		//			// not implement due to risk of not being able to remove the listener
+		//			// (https://bugs.adobe.com/jira/browse/SDK-25896)
+		//			
+		//			
+		//			// TODO Tink
+		//			// We should fire this if the index added is less or equal to the
+		//			// selectedIndex.
+		//			// WE NEED TO FORCE THIS TO UPDATE THOUGH AS IT WON'T BY DEFAULT
+		//			// AS THE INDEX HASN'T CHANGED
+		////			if( selectedIndex == -1 ) scrollPositionChanged();
+		//		}
+		
+		//		/**
+		//		 *  @inheritDoc
+		//		 *  
+		//		 *  @langversion 3.0
+		//		 *  @playerversion Flash 10
+		//		 *  @playerversion AIR 1.5
+		//		 *  @productversion Flex 4
+		//		 */
+		//		override public function elementRemoved(index:int):void
+		//		{
+		//			super.elementRemoved( index );
+		//			
+		//			_elementsChanged = true;
+		//			
+		//			//TODO restor element (https://bugs.adobe.com/jira/browse/SDK-25896)
+		//			
+		//			// TODO Tink
+		//			// We should fire this if the index added is less or equal to the
+		//			// selectedIndex.
+		//			// WE NEED TO FORCE THIS TO UPDATE THOUGH AS IT WON'T BY DEFAULT
+		//			// AS THE INDEX HASN'T CHANGED
+		////			if( selectedIndex == -1 ) scrollPositionChanged();
+		//		}
+		
+		/**
+		 *  @private
+		 */
+		protected function restoreElements():void
+		{
+			// When using virtualization, elements get created after updateElements()
+			// has been invoked as part of getVirtualItemAt(), therefore we must re-calculate them.
+			if( target is DataGroup && target.numChildren != _elements.length ) updateElements();
+			
+			for each( var element:IVisualElement in _elements )
+			{
+				// Only restoe the element if its includeInLayout property
+				// is true.
+				if( element.includeInLayout ) restoreElement( element );
+			}
+		}
+		
+		override public function updateScrollRect( w:Number, h:Number ):void
+		{
+			if( !target ) return;
+			
+			target.scrollRect = clipAndEnableScrolling ? new Rectangle( 0, 0, w, h ) : null;
+		}
+		
+		/**
+		 *  Restores the element to reset any changes to is visible properties. 
+		 *  This method should be overridden in a subclass to return any elements
+		 *  used in the layout to its default state when it is removed from the
+		 *  targets displayList or when the target is removed from the layout.
+		 * 
+		 *  @param element The element to be restored.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		protected function restoreElement( element:IVisualElement ):void
+		{
+			
+		}
+		
+		override public function getHorizontalScrollPositionDelta( navigationUnit:uint ):Number
+		{
+			if( _useScrollBarForNavigation )
+			{
+				switch( navigationUnit )
+				{
+					case NavigationUnit.PAGE_RIGHT :
+					case NavigationUnit.RIGHT :
+					{
+						return unscaledWidth;
+					}
+					case NavigationUnit.END :
+					{
+						return ( unscaledWidth * ( _numElementsInLayout - 1 ) ) - horizontalScrollPosition;
+					}
+					case NavigationUnit.HOME :
+					{
+						return -horizontalScrollPosition;
+					}
+					case NavigationUnit.PAGE_LEFT :
+					case NavigationUnit.LEFT :
+					{
+						return -unscaledWidth;
+					}
+					default :
+					{
+						return 0;
+					}
+				}
+			}
+			else
+			{
+				return super.getHorizontalScrollPositionDelta( navigationUnit );
+			}
+		}
+		
+		override public function getVerticalScrollPositionDelta( navigationUnit:uint ):Number
+		{
+			if( _useScrollBarForNavigation )
+			{
+				switch( navigationUnit )
+				{
+					case NavigationUnit.PAGE_DOWN :
+					case NavigationUnit.DOWN :
+					{
+						return unscaledHeight;
+					}
+					case NavigationUnit.END :
+					{
+						return ( unscaledHeight * ( _numElementsInLayout - 1 ) ) - verticalScrollPosition;
+					}
+					case NavigationUnit.HOME :
+					{
+						return -verticalScrollPosition;
+					}
+					case NavigationUnit.PAGE_UP :
+					case NavigationUnit.UP :
+					{
+						return -unscaledHeight;
+					}
+					default :
+					{
+						return 0;
+					}
+				}
+			}
+			else
+			{
+				return super.getVerticalScrollPositionDelta( navigationUnit );
+			}
+		}
+		
+		final protected function applyColorTransformToElement( element:IVisualElement, colorTransform:ColorTransform ):void
+		{
+			if( element is GraphicElement )
+			{
+				GraphicElement( element ).transform.colorTransform = colorTransform;
+			}
+			else
+			{
+				DisplayObject( element ).transform.colorTransform = colorTransform;
+			}
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/0d3bf3b6/frameworks/projects/experimental/src/spark/layouts/supportClasses/PerspectiveAnimationNavigatorLayoutBase.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/layouts/supportClasses/PerspectiveAnimationNavigatorLayoutBase.as b/frameworks/projects/experimental/src/spark/layouts/supportClasses/PerspectiveAnimationNavigatorLayoutBase.as
new file mode 100644
index 0000000..7a5a338
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/layouts/supportClasses/PerspectiveAnimationNavigatorLayoutBase.as
@@ -0,0 +1,383 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package spark.layouts.supportClasses
+{
+	import flash.geom.PerspectiveProjection;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	
+	import spark.components.supportClasses.GroupBase;
+	import spark.layouts.HorizontalAlign;
+	import spark.layouts.VerticalAlign;
+	import spark.primitives.Rect;
+
+	public class PerspectiveAnimationNavigatorLayoutBase extends AnimationNavigatorLayoutBase
+	{
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor. 
+		 * 
+		 *  @param animationType The type of animation.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */ 
+		public function PerspectiveAnimationNavigatorLayoutBase( animationType:String )
+		{
+			super( animationType );
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		private var _projectionChanged	: Boolean;
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//----------------------------------
+		//  projectionCenterX
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *	Storage property for projectionCenterX.
+		 */
+		private var _projectionCenterX:Number = NaN;
+		
+		/**
+		 *  @private
+		 *	Flag to indicate that the projectCenterX property as been set to number
+		 *  value other than NaN.
+		 */
+		private var _projectionCenterXSet:Boolean;
+		
+		[Inspectable(category="General", defaultValue="NaN")]
+		/**
+		 *  projectionCenterX
+		 * 
+		 *  @default 0
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get projectionCenterX():Number
+		{
+			return _projectionCenterX;
+		}
+		/**
+		 *  @private
+		 */
+		public function set projectionCenterX(value:Number):void
+		{
+			if( _projectionCenterX == value ) return;
+			
+			_projectionCenterX = value;
+			_projectionChanged = true;
+			_projectionCenterXSet = true;
+			invalidateTargetDisplayList();
+		}    
+		
+		
+		//----------------------------------
+		//  projectionCenterY
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *	Storage property for projectionCenterY.
+		 */
+		private var _projectionCenterY:Number = NaN;
+		
+		/**
+		 *  @private
+		 *	Flag to indicate that the projectCenterY property as been set to number
+		 *  value other than NaN.
+		 */
+		private var _projectionCenterYSet:Boolean;
+		
+		[Inspectable(category="General", defaultValue="NaN")]
+		/**
+		 *  projectionCenterY
+		 * 
+		 *  @default NaN
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get projectionCenterY():Number
+		{
+			return _projectionCenterY;
+		}
+		/**
+		 *  @private
+		 */
+		public function set projectionCenterY(value:Number):void
+		{
+			if( _projectionCenterY == value ) return;
+			
+			_projectionCenterY = value;
+			_projectionChanged = true;
+			_projectionCenterYSet = true;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  fieldOfView
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *	Storage property for fieldOfView.
+		 */
+		private var _fieldOfView:Number = NaN;
+		
+		[Inspectable(category="General")]
+		/**
+		 *  fieldOfView
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get fieldOfView():Number
+		{
+			return ( perspectiveProjection ) ? perspectiveProjection.fieldOfView : _fieldOfView;
+		}
+		/**
+		 *  @private
+		 */
+		public function set fieldOfView( value:Number ):void
+		{
+			if( _fieldOfView == value ) return;
+			
+			_fieldOfView = value;
+			_focalLength = NaN;
+			_projectionChanged = true;
+			invalidateTargetDisplayList();
+		}    
+		
+		
+		//----------------------------------
+		//  focalLength
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 *	Storage property for focalLength.
+		 */
+		private var _focalLength:Number = NaN;
+		
+		[Inspectable(category="General")]
+		/**
+		 *  focalLength
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function get focalLength():Number
+		{
+			return ( perspectiveProjection ) ? perspectiveProjection.focalLength : _focalLength;
+		}
+		/**
+		 *  @private
+		 */
+		public function set focalLength( value:Number ):void
+		{
+			if( _focalLength == value ) return;
+			
+			_focalLength = value;
+			_fieldOfView = NaN;
+			_projectionChanged = true;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		//----------------------------------
+		//  perspectiveProjection
+		//----------------------------------  
+		
+		/**
+		 *  @private
+		 */
+		private function get perspectiveProjection():PerspectiveProjection
+		{
+			return target.transform.perspectiveProjection;
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  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
+		{
+			super.target = value;
+			
+			_projectionChanged = true;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Returns the visible projection plane at a specific depth.
+		 *  
+		 *  @param z The depth of the projection plane.
+		 * 
+		 *  @return Rectangle A Rectangle object with the coordinates of the projection plane.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function getProjectionRectAtZ( z:Number ):Rectangle
+		{
+			const rectangle:Rectangle = new Rectangle();
+			rectangle.right = getProjectionCoord( projectionCenterX, unscaledWidth, z );
+			rectangle.left = getProjectionCoord( projectionCenterX, 0, z );
+			rectangle.bottom = getProjectionCoord( projectionCenterY, unscaledHeight, z );
+			rectangle.top = getProjectionCoord( projectionCenterY, 0, z );
+			return rectangle;
+		}
+		
+		/**
+		 *  @private
+		 *  Util function to return a side of the Rect.
+		 */
+		private function getProjectionCoord( center:Number, border:Number, z:Number ):Number
+		{
+//			private function angle( p1:Point, p2:Point ):Number
+//			{
+//				return ( Math.atan2( p2.y - p1.y, p2.x - p1.x ) * ( 180 / Math.PI ) ) % 360;
+//			}
+//			
+//			private function tanD( a:Number ):Number
+//			{
+//				return Math.tan( a * ( Math.PI / 180 ) );
+//			}
+//			a = 90 - angle( new Point( projectionCenterX.value, 0 ), new Point( 400, p.focalLength ) );
+//			displayRect.right =projectionCenterX.value + ( tanD( a ) * distance );
+//			a = 90 - angle( new Point( projectionCenterX.value, 0 ), new Point( 0, p.focalLength ) );
+//			displayRect.left = projectionCenterX.value + ( tanD( a ) * distance );
+//			a = 90 - angle( new Point( projectionCenterY.value, 0 ), new Point( 300, p.focalLength ) );
+//			displayRect.bottom = projectionCenterY.value + ( tanD( a ) * distance );
+//			a = 90 - angle( new Point( projectionCenterY.value, 0 ), new Point( 0, p.focalLength ) );
+//			displayRect.top = projectionCenterY.value + tanD( a ) * distance;
+			
+			// Find the angle from the center of the projection to the edge of the projection plane.
+			const angle:Number = ( Math.atan2( focalLength, border - center ) * ( 180 / Math.PI ) ) % 360;
+			// Find the edge of the plane at the specified z.
+			return center + ( Math.tan( ( 90 - angle ) * ( Math.PI / 180 ) ) * ( z + focalLength ) );
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		override protected function updateDisplayListBetween():void
+		{
+			
+			
+			if( target && _projectionChanged || ( sizeChangedInLayoutPass && !_projectionCenterXSet || !_projectionCenterYSet ) )
+			{
+				_projectionChanged = false;
+				
+				if( !perspectiveProjection ) target.transform.perspectiveProjection = new PerspectiveProjection();
+				
+				if( !_projectionCenterXSet || isNaN( _projectionCenterX ) ) _projectionCenterX = unscaledWidth / 2;
+				if( !_projectionCenterYSet || isNaN( _projectionCenterY ) ) _projectionCenterY = unscaledHeight / 2;
+				perspectiveProjection.projectionCenter = new Point( _projectionCenterX, _projectionCenterY );
+				
+				if( !isNaN( _fieldOfView ) ) perspectiveProjection.fieldOfView = _fieldOfView;
+				if( !isNaN( _focalLength ) ) perspectiveProjection.focalLength = _focalLength;
+			}
+			
+			super.updateDisplayListBetween();
+		}
+		
+		
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/0d3bf3b6/frameworks/projects/experimental/src/spark/layouts/supportClasses/PerspectiveNavigatorLayoutBase.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/layouts/supportClasses/PerspectiveNavigatorLayoutBase.as b/frameworks/projects/experimental/src/spark/layouts/supportClasses/PerspectiveNavigatorLayoutBase.as
new file mode 100644
index 0000000..83986f9
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/layouts/supportClasses/PerspectiveNavigatorLayoutBase.as
@@ -0,0 +1,223 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package spark.layouts.supportClasses
+{
+	import flash.geom.PerspectiveProjection;
+	import flash.geom.Point;
+	
+	import spark.components.supportClasses.GroupBase;
+	import spark.layouts.HorizontalAlign;
+	import spark.layouts.VerticalAlign;
+
+	public class PerspectiveNavigatorLayoutBase extends NavigatorLayoutBase
+	{
+		
+		private var _projectionChanged	: Boolean;
+		
+		private var _unscaledWidth	: Number;
+		private var _unscaledHeight	: Number;
+		
+		
+		public function PerspectiveNavigatorLayoutBase()
+		{
+			super();
+		}
+		
+		override public function set target(value:GroupBase):void
+		{
+			super.target = value;
+			
+			_projectionChanged = true;
+			invalidateTargetDisplayList();
+		}
+		
+		public function get projectionCenter():Point
+		{
+			return ( perspectiveProjection ) ? perspectiveProjection.projectionCenter : getProjectionCenter();
+		}
+		
+		private var _projectionCenterHorizontalAlign:String = HorizontalAlign.CENTER;
+		[Inspectable(category="General", enumeration="left,right,center", defaultValue="center")]
+		public function get projectionCenterHorizontalAlign():String
+		{
+			return _projectionCenterHorizontalAlign;
+		}
+		public function set projectionCenterHorizontalAlign(value:String):void
+		{
+			if( value == _projectionCenterHorizontalAlign ) return;
+			
+			_projectionCenterHorizontalAlign = value;
+			
+			invalidateTargetDisplayList();
+		}
+		
+		private var _projectionCenterVerticalAlign:String = VerticalAlign.MIDDLE;
+		[Inspectable(category="General", enumeration="top,bottom,middle", defaultValue="middle")]
+		public function get projectionCenterVerticalAlign():String
+		{
+			return _projectionCenterVerticalAlign;
+		}
+		public function set projectionCenterVerticalAlign(value:String):void
+		{
+			if( value == _projectionCenterVerticalAlign ) return;
+			
+			_projectionCenterVerticalAlign = value;
+			
+			invalidateTargetDisplayList();
+		}
+		
+		
+		private var _projectionCenterHorizontalOffset:Number = 0;
+		[Inspectable(category="General", defaultValue="0")]
+		public function get projectionCenterHorizontalOffset():Number
+		{
+			return _projectionCenterHorizontalOffset;
+		}
+		public function set projectionCenterHorizontalOffset(value:Number):void
+		{
+			if( _projectionCenterHorizontalOffset == value ) return;
+			
+			_projectionCenterHorizontalOffset = value;
+			invalidateTargetDisplayList();
+		}    
+		
+		private var _projectionCenterVerticalOffset:Number = 0;
+		[Inspectable(category="General", defaultValue="0")]
+		public function get projectionCenterVerticalOffset():Number
+		{
+			return _projectionCenterVerticalOffset;
+		}
+		public function set projectionCenterVerticalOffset(value:Number):void
+		{
+			if( _projectionCenterVerticalOffset == value ) return;
+			
+			_projectionCenterVerticalOffset = value;
+			invalidateTargetDisplayList();
+		}
+		
+		
+		private var _fieldOfView:Number = NaN;
+		[Inspectable(category="General", defaultValue="55")]
+		public function get fieldOfView():Number
+		{
+			return ( perspectiveProjection ) ? perspectiveProjection.fieldOfView : _fieldOfView;
+		}
+		public function set fieldOfView( value:Number ):void
+		{
+			if( _fieldOfView == value ) return;
+			
+			_fieldOfView = value;
+			_focalLength = NaN;
+			_projectionChanged = true;
+			invalidateTargetDisplayList();
+		}    
+		
+		private var _focalLength:Number = NaN;
+		[Inspectable(category="General")]
+		public function get focalLength():Number
+		{
+			return ( perspectiveProjection ) ? perspectiveProjection.focalLength : _focalLength;
+		}
+		public function set focalLength( value:Number ):void
+		{
+			if( _focalLength == value ) return;
+			
+			_focalLength = value;
+			_fieldOfView = NaN;
+			_projectionChanged = true;
+			invalidateTargetDisplayList();
+		}
+		
+		override public function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
+		{
+			super.updateDisplayList( unscaledWidth, unscaledHeight );
+			
+			if( _unscaledWidth != unscaledWidth || _unscaledHeight != unscaledHeight )
+			{
+				_unscaledWidth = unscaledWidth;
+				_unscaledHeight = unscaledHeight;
+				_projectionChanged = true;
+			}
+			
+			if( target && _projectionChanged )
+			{
+				_projectionChanged = false;
+				
+				if( !perspectiveProjection ) target.transform.perspectiveProjection = new PerspectiveProjection();
+				
+				perspectiveProjection.projectionCenter = getProjectionCenter();
+				if( !isNaN( _fieldOfView ) ) perspectiveProjection.fieldOfView = _fieldOfView;
+				if( !isNaN( _focalLength ) ) perspectiveProjection.focalLength = _focalLength;
+			}
+			
+		}
+		
+		
+		private function getProjectionCenter():Point
+		{
+			var p:Point = new Point();
+			switch( _projectionCenterHorizontalAlign )
+			{
+				case HorizontalAlign.LEFT :
+				{
+					p.x = _projectionCenterHorizontalOffset;
+					break;
+				}
+				case HorizontalAlign.CENTER :
+				{
+					p.x = ( _unscaledWidth / 2 ) + _projectionCenterHorizontalOffset;
+					break;
+				}
+				case HorizontalAlign.RIGHT :
+				{
+					p.x = _unscaledWidth + _projectionCenterHorizontalOffset;
+					break;
+				}
+			}
+			
+			switch( _projectionCenterVerticalAlign )
+			{
+				case VerticalAlign.TOP :
+				{
+					p.y = _projectionCenterVerticalOffset;
+					break;
+				}
+				case VerticalAlign.MIDDLE :
+				{
+					p.y = ( _unscaledHeight / 2 ) + _projectionCenterVerticalOffset;
+					break;
+				}
+				case VerticalAlign.BOTTOM :
+				{
+					p.y = _unscaledHeight + _projectionCenterVerticalOffset;
+					break;
+				}
+			}
+			
+			return p;
+		}
+		
+		private function get perspectiveProjection():PerspectiveProjection
+		{
+			return target.transform.perspectiveProjection;
+		}
+		
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/0d3bf3b6/frameworks/projects/experimental/src/spark/managers/INavigatorBrowserManager.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/managers/INavigatorBrowserManager.as b/frameworks/projects/experimental/src/spark/managers/INavigatorBrowserManager.as
new file mode 100644
index 0000000..5b12b7f
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/managers/INavigatorBrowserManager.as
@@ -0,0 +1,120 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package spark.managers
+{
+	import spark.layouts.supportClasses.INavigatorLayout;
+
+	/**
+	 *  The interface that the shared instance of the NavigtorBrowserManager
+	 *  implements, which is accessed with the <code>NavigtorBrowserManager.getInstance()</code> method.
+	 * 
+	 *  @see spark.managers.NavigtorBrowserManager
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	public interface INavigatorBrowserManager
+	{
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//----------------------------------
+		//  fragmentField
+		//----------------------------------
+		
+		/**
+		 *  The portion of current URL after the '#' as it appears 
+		 *  in the browser address bar, or the default fragment
+		 *  used in setup() if there is nothing after the '#'.  
+		 *  Use setFragment to change this value.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		function get fragmentField():String
+		/**
+		 *  @private
+		 */
+		function set fragmentField( value:String ):void
+		
+		
+		//----------------------------------
+		//  fragmentFunction
+		//----------------------------------
+		
+		/**
+		 *  The portion of current URL after the '#' as it appears 
+		 *  in the browser address bar, or the default fragment
+		 *  used in setup() if there is nothing after the '#'.  
+		 *  Use setFragment to change this value.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		function get fragmentFunction():Function
+		/**
+		 *  @private
+		 */
+		function set fragmentFunction( value:Function ):void
+			
+			
+			
+		//--------------------------------------------------------------------------
+		//
+		//  Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Registers a layout so that it can be managed.
+		 *  
+		 *  @param value The INavigatorLayout to be registered.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		function registerLayout( value:INavigatorLayout ):void
+		
+		/**
+		 *  Unregisters a layout so that it is no longer managed.
+		 *  
+		 *  @param value The INavigatorLayout to be unregistered.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		function unRegisterLayout( value:INavigatorLayout ):void
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/0d3bf3b6/frameworks/projects/experimental/src/spark/managers/NavigatorBrowserManager.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/managers/NavigatorBrowserManager.as b/frameworks/projects/experimental/src/spark/managers/NavigatorBrowserManager.as
new file mode 100644
index 0000000..4ab47e8
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/managers/NavigatorBrowserManager.as
@@ -0,0 +1,92 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package spark.managers
+{
+	
+	import mx.core.Singleton;
+	
+	/**
+	 *  @private
+	 *  The NavigatorBrowserManager is a Singleton manager that acts as
+	 *  a proxy between the BrowserManager and INavigatorLayout instances
+	 *  added to it.
+	 * 
+	 *  <p>It updates the <code>fragment</code> property of the IBrowserManager
+	 *  when a registered INavigatorLayout changes its <code>selectedindex</code>,
+	 *  and also sets the <code>selectedIndex</code> of registered INavigatorLayout instances
+	 *  when the <code>fragment</code> property of the IBrowserManager changes.
+	 *
+	 *  @see spark.managers.INavigatorBrowserManager
+	 *  @see spark.layouts.supportClasses.INavigatorLayout
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public class NavigatorBrowserManager
+	{
+
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Class Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 *  Linker dependency on implementation class.
+		 */
+		private static var implClassDependency:NavigatorBrowserManagerImpl;
+		
+		/**
+		 *  @private
+		 */
+		private static var instance:INavigatorBrowserManager;
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Class methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Returns the sole instance of this Singleton class;
+		 *  creates it if it does not already exist.
+		 *
+		 *  @return Returns the sole instance of this Singleton class;
+		 *  creates it if it does not already exist.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public static function getInstance():INavigatorBrowserManager
+		{
+			if( !instance ) instance = INavigatorBrowserManager( Singleton.getInstance( "spark.managers::INavigatorBrowserManager" ) );
+			return instance;
+		}
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/0d3bf3b6/frameworks/projects/experimental/src/spark/managers/NavigatorBrowserManagerImpl.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/managers/NavigatorBrowserManagerImpl.as b/frameworks/projects/experimental/src/spark/managers/NavigatorBrowserManagerImpl.as
new file mode 100644
index 0000000..79213de
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/managers/NavigatorBrowserManagerImpl.as
@@ -0,0 +1,589 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package spark.managers
+{
+	import flash.display.DisplayObjectContainer;
+	
+	import mx.core.IVisualElement;
+	import mx.events.BrowserChangeEvent;
+	import mx.events.FlexEvent;
+	import mx.managers.BrowserManager;
+	import mx.managers.IBrowserManager;
+	
+	import spark.components.DataGroup;
+	import spark.components.supportClasses.GroupBase;
+	import spark.events.IndexChangeEvent;
+	import spark.layouts.supportClasses.LayoutBase;
+	import spark.utils.LabelUtil;
+	
+	import spark.layouts.supportClasses.INavigatorLayout;
+
+	[ExcludeClass]
+	/**
+	 *  @private
+	 *  The NavigatorBrowserManager is a Singleton manager that acts as
+	 *  a proxy between the BrowserManager and INavigatorLayout instances
+	 *  added to it.
+	 * 
+	 *  <p>It updates the <code>fragment</code> property of the IBrowserManager
+	 *  when a registered INavigatorLayout changes its <code>selectedindex</code>,
+	 *  and also sets the <code>selectedIndex</code> of registered INavigatorLayout instances
+	 *  when the <code>fragment</code> property of the IBrowserManager changes.
+	 *
+	 *  @see mx.managers.IBrowserManager
+	 *  @see spark.layouts.supportClasses.INavigatorLayout
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public class NavigatorBrowserManagerImpl implements INavigatorBrowserManager
+	{
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Class Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		private static var _instance:NavigatorBrowserManagerImpl;
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Class Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		public static function getInstance():NavigatorBrowserManagerImpl
+		{
+			if( !_instance ) _instance = new NavigatorBrowserManagerImpl();
+			return _instance;
+		}
+		
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor. 
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function NavigatorBrowserManagerImpl()
+		{
+			super();
+			
+			_browserManager = BrowserManager.getInstance();
+			_browserManager.addEventListener( BrowserChangeEvent.BROWSER_URL_CHANGE, onBrowserManagerBrowserURLChange, false, 0, true ); 
+			_browserManager.init("", "");
+			
+			parseFrament();
+			updateFragment();
+		}
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 *  Instance of the browser manager to be used.
+		 */
+		private var _browserManager:IBrowserManager;
+		
+		/**
+		 *  @private
+		 *  The list of layouts being managed.
+		 */
+		private var _layouts:Vector.<INavigatorLayout> = new Vector.<INavigatorLayout>();
+		
+		/**
+		 *  @private
+		 *  The list of layouts that can still be parsed after a URL change.
+		 */
+		private var _layoutsToParse:Vector.<INavigatorLayout> = new Vector.<INavigatorLayout>();
+		
+		/**
+		 *  @private
+		 *  The list of layouts to ignore their <code>FlexEvent.VALUE_COMMIT</code> events.
+		 *  When the index of a layout is changed, we want to ignore the value commit, if
+		 *  the layouts <code>selectedIndex</code> is the same as the index set.
+		 */
+		private var _layoutsToIgnore:Vector.<LayoutToIgnore> = new Vector.<LayoutToIgnore>();
+		
+		/**
+		 *  @private
+		 *  A list of fragment parts that still need to be parsed.
+		 */
+		private var _fragmentsToParse:Array;
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//----------------------------------
+		//  fragmentField
+		//----------------------------------
+		
+		/**
+		 *  @private
+		 *  Storage property for fragmentField.
+		 */
+		private var _fragmentField:String;
+		
+		/**
+		 *  The portion of current URL after the '#' as it appears 
+		 *  in the browser address bar, or the default fragment
+		 *  used in setup() if there is nothing after the '#'.  
+		 *  Use setFragment to change this value.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function get fragmentField():String
+		{
+			return _fragmentField;
+		}
+		/**
+		 *  @private
+		 */
+		public function set fragmentField( value:String ):void
+		{
+			if( _fragmentField == value ) return;
+			
+			_fragmentField = value;
+			updateFragment();
+		}
+		
+		
+		//----------------------------------
+		//  fragmentFunction
+		//----------------------------------
+		
+		/**
+		 *  @private
+		 *  Storage property for fragmentFunction.
+		 */
+		private var _fragmentFunction:Function;
+		
+		/**
+		 *  The portion of current URL after the '#' as it appears 
+		 *  in the browser address bar, or the default fragment
+		 *  used in setup() if there is nothing after the '#'.  
+		 *  Use setFragment to change this value.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function get fragmentFunction():Function
+		{
+			return _fragmentFunction;
+		}
+		/**
+		 *  @private
+		 */
+		public function set fragmentFunction( value:Function ):void
+		{
+			if( _fragmentFunction == value ) return;
+			
+			_fragmentFunction = value;
+			updateFragment();
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function registerLayout( value:INavigatorLayout ):void
+		{
+			if( _layouts.indexOf( value ) == -1 )
+			{
+				value.addEventListener( FlexEvent.VALUE_COMMIT, onLayoutIndexChange, false, 0, true );
+				_layouts.push( value );
+				_layouts.sort( nestLevelCompareFunction );
+				
+				_layoutsToParse.push( value );
+				_layoutsToParse.sort( nestLevelCompareFunction );
+			}
+			
+			if( _fragmentsToParse && _fragmentsToParse.length )
+			{
+				parseFrament();
+			}
+			else
+			{
+				updateFragment();
+			}
+		}
+		
+		/**
+		 *  @inheritDoc
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function unRegisterLayout( value:INavigatorLayout ):void
+		{
+			const index:int = _layouts.indexOf( value )
+			if( index != -1 )
+			{
+				const l:INavigatorLayout = _layouts.splice( index, 1 )[ 0 ];
+				l.removeEventListener( IndexChangeEvent.CHANGE, onLayoutIndexChange, false );
+			}
+			
+			updateFragment();
+		}
+		
+		
+		/**
+		 *  @private
+		 *  Sorts the layouts into order depending on th nestLevel (how deep they are in the displayList).
+		 */
+		private function nestLevelCompareFunction( a:INavigatorLayout, b:INavigatorLayout ):int
+		{
+			const at:GroupBase = LayoutBase( a ).target;
+			const bt:GroupBase = LayoutBase( b ).target;
+			
+			if( !at && !bt )
+			{
+				return 0;
+			}
+			else if( !at )
+			{
+				return 1;
+			}
+			else if( !bt )
+			{
+				return -1;
+			}
+			else
+			{
+				return Math.min( 1, Math.max( -1, at.nestLevel - bt.nestLevel ) );
+			}
+		}
+		
+		
+		/**
+		 *  @private
+		 *  Parses the fragments by looking for the correct layouts to select the index on.
+		 */
+		private function parseFrament( override:Boolean = true ):void
+		{
+			if( !_fragmentsToParse || !_fragmentsToParse.length ) return;
+			
+			var target:GroupBase;
+			var part:String;
+			var layout:INavigatorLayout;
+			var elements:Array;
+				
+			const numLayouts:int = _layoutsToParse.length;
+			for( var i:int = 0; i < numLayouts; i++ )
+			{
+				part = _fragmentsToParse[ 0 ];
+				layout = _layoutsToParse[ 0 ];
+				target = LayoutBase( layout ).target;
+				
+				if( target )
+				{
+					elements = getElements( target );
+					var numElements:int = elements.length;
+					for( var e:int = 0; e < numElements; e++ )
+					{
+						if( LabelUtil.itemToLabel( elements[ e ], fragmentField, fragmentFunction ) == part )
+						{
+							// Remove both from their lists
+							_fragmentsToParse.splice( 0, 1 );
+							_layoutsToParse.splice( 0, 1 );
+							
+							// Make sure we ignore this layouts valueCommit.
+							_layoutsToIgnore.push( new LayoutToIgnore( layout, e ) );
+							
+							layout.selectedIndex = e;
+							
+							if( _fragmentsToParse.length )
+							{
+								break;
+							}
+							else
+							{
+								return;
+							}
+						}
+					}
+				}
+			}
+		}
+		
+		
+		
+		/**
+		 *  @private
+		 *  Util method to get a list of the items being rendrered.
+		 *  These could be visual items or data items.
+		 */
+		private function updateFragment():void
+		{
+			_layouts.sort( nestLevelCompareFunction );
+			
+			var target:GroupBase;
+			var fragment:String = "";
+			
+			var selectedElement:IVisualElement;
+			for each( var layout:INavigatorLayout in _layouts )
+			{
+				target = LayoutBase( layout ).target;
+				
+				if( target )
+				{
+					if( !selectedElement )
+					{
+						selectedElement = layout.selectedElement;
+						fragment += getFragment( layout, target );
+					}
+					// Make sure that this layouts target is a child of the
+					// previously selectedElement.
+					else if( selectedElement is DisplayObjectContainer && 
+							 DisplayObjectContainer( selectedElement ).contains( target ) )
+					{
+						fragment += getFragment( layout, target );
+						selectedElement = layout.selectedElement;
+					}
+				}
+			}
+			
+			if( _browserManager.fragment != fragment ) _browserManager.setFragment( fragment );
+		}
+		
+		/**
+		 *  @private
+		 *  Util method to get a list of the items being rendrered.
+		 *  These could be visual items or data items.
+		 */
+		protected function getElements( target:GroupBase ):Array
+		{
+			if( target is DataGroup )
+			{
+				return DataGroup( target ).dataProvider.toArray();
+			}
+			else
+			{
+				try
+				{
+					return target[ "getMXMLContent" ]();
+				}
+				catch( e:Error )
+				{
+					return target[ "toArray" ]();
+				}
+				catch( e:Error )
+				{
+					throw new Error( "NavigatorLayoutBase cannot be used as a layout for this kind of container" );
+					return new Array();
+				}
+			}
+			
+			return new Array();
+		}
+		
+		/**
+		 *  @private
+		 *  Util method get a framenet string for the selectedIndex.
+		 */
+		private function getFragment( l:INavigatorLayout, target:GroupBase ):String
+		{
+			const elements:Array = getElements( target );
+			return LabelUtil.itemToLabel( elements[ l.selectedIndex ], fragmentField, fragmentFunction ) + "/";
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Event Listeners
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 *  Invoked by the the URL is changed in the browser.
+		 */
+		private function onBrowserManagerBrowserURLChange( event:BrowserChangeEvent ):void
+		{
+			_layoutsToParse = _layouts.concat();
+			
+			_fragmentsToParse = _browserManager.fragment.split( "/" );
+			_fragmentsToParse.splice( _fragmentsToParse.length - 1, 1 );
+			parseFrament();
+		}
+		
+		/**
+		 *  @private
+		 *  Invoked when the selectedIndex changes in a layout.
+		 */
+		private function onLayoutIndexChange( event:FlexEvent ):void
+		{
+			const l:INavigatorLayout = INavigatorLayout( event.currentTarget );
+			const numLayouts:int = _layoutsToIgnore.length;
+			
+			for( var i:int = 0; i < numLayouts; i++ )
+			{
+				if( _layoutsToIgnore[ i ].layout == l && _layoutsToIgnore[ i ].selectedIndex == l.selectedIndex )
+				{
+					_layoutsToIgnore.splice( i, 1 );
+					return;
+				}
+			}
+			updateFragment();
+		}
+	}
+}
+
+
+
+import spark.layouts.supportClasses.INavigatorLayout;
+
+/**
+ *  @private
+ *  Util class used to store layouts whos valueCommit property
+ *  we want to ignore due to use setting their selectedIndex.
+ */
+internal class LayoutToIgnore
+{
+	
+	
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Constructor
+	//
+	//--------------------------------------------------------------------------
+	
+	/**
+	 *  Constructor.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	public function LayoutToIgnore( layout:INavigatorLayout, selectedIndex:int )
+	{
+		_layout = layout;
+	  	_selectedIndex = selectedIndex;
+	}
+	
+	
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Properties
+	//
+	//--------------------------------------------------------------------------
+	
+	//----------------------------------
+	//  index
+	//----------------------------------
+	
+	/**
+	 *  @private
+	 *  Storage property for selectedIndex.
+	 */
+	private var _selectedIndex:int;
+	
+	/**
+	 *  The selectedIndex that the NavigatorBrowserManager set on the layout. 
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public function get selectedIndex():int
+	{
+		return _selectedIndex;
+	}
+	
+	
+	//----------------------------------
+	//  layout
+	//----------------------------------
+	
+	/**
+	 *  @private
+	 *  Storage property for layout.
+	 */
+	private var _layout:INavigatorLayout;
+	
+	/**
+	 *  The layout that the NavigatorBroswerManager updated. 
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4
+	 */
+	public function get layout():INavigatorLayout
+	{
+		return _layout;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/0d3bf3b6/frameworks/projects/experimental/src/spark/skins/AccordionSkin.mxml
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental/src/spark/skins/AccordionSkin.mxml b/frameworks/projects/experimental/src/spark/skins/AccordionSkin.mxml
new file mode 100644
index 0000000..f66ef65
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/skins/AccordionSkin.mxml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+-->
+<!--- The default skin class for a Spark Accordion container.  
+
+@see spark.containers.Accordion
+
+@langversion 3.0
+@playerversion Flash 10
+@playerversion AIR 1.5
+@productversion Flex 4
+-->
+<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
+			 xmlns:s="library://ns.adobe.com/flex/spark" 
+			 xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
+			 xmlns:ns="http://flex.apache.org/experimental/ns"
+			 alpha.disabled="0.5">
+	
+	<fx:Metadata>
+		<![CDATA[ 
+		/** 
+		* @copy spark.skins.spark.ApplicationSkin#hostComponent
+		*/
+		[HostComponent("spark.containers.Accordion")]
+		]]>
+	</fx:Metadata> 
+	
+	<fx:Script fb:purpose="styling">
+		
+		/* Define the skin elements that should not be colorized. 
+		For list, the skin itself is colorized but the individual parts are not. */
+		static private const exclusions:Array = [ "contentGroup", "buttonBar", "background" ];
+		
+		/**
+		 * @private
+		 */
+		override public function get colorizeExclusions():Array {return exclusions;}
+		
+		/* Define the content fill items that should be colored by the "contentBackgroundColor" style. */
+		static private const contentFill:Array = [ "bgFill" ];
+		
+		/**
+		 * @private
+		 */
+		override public function get contentItems():Array { return contentFill };
+		
+		/**
+		 * @private
+		 */
+		override protected function initializationComplete():void
+		{
+			useChromeColor = true;
+			super.initializationComplete();
+		}
+		
+		/**
+		 * @private
+		 */
+		override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
+		{
+			if( getStyle( "borderVisible" ) == true )
+			{
+				border.visible = true;
+				background.left = background.top = background.right = background.bottom = 1;
+				contentGroup.left = contentGroup.top = contentGroup.right = contentGroup.bottom = 1;
+			}
+			else
+			{
+				border.visible = false;
+				background.left = background.top = background.right = background.bottom = 0;
+				contentGroup.left = contentGroup.top = contentGroup.right = contentGroup.bottom = 0;
+			}
+			
+			borderStroke.color = getStyle( "borderColor" );
+			borderStroke.alpha = getStyle( "borderAlpha" );
+			
+			super.updateDisplayList( unscaledWidth, unscaledHeight );
+		}
+		
+	</fx:Script>
+	
+	<s:states>
+		<s:State name="normal" />
+		<s:State name="disabled" />
+	</s:states>
+		
+	<!-- fill -->
+	<!--- Defines the background appearance of the list-based component. -->
+	<s:Rect id="background" left="1" right="1" top="1" bottom="1" >
+		<s:fill>
+			<!--- Defines the color of the background. The default color is 0xFFFFFF. -->
+			<s:SolidColor id="bgFill" color="0xFFFFFF" />
+		</s:fill>
+	</s:Rect>
+	
+	<!-- border -->
+	<!--- @private -->
+	<s:Rect left="0" right="0" top="0" bottom="0" id="border">
+		<s:stroke>
+			<!--- @private -->
+			<s:SolidColorStroke id="borderStroke" weight="1"/>
+		</s:stroke>
+	</s:Rect>
+	
+	<!--
+	Note: setting the minimum size to 0 here so that changes to the host component's
+	size will not be thwarted by this skin part's minimum size.   This is a compromise,
+	more about it here: http://bugs.adobe.com/jira/browse/SDK-21143
+	-->
+	<!--- @copy spark.containers.Navigator#contentGroup -->
+	<ns:NavigatorGroup id="contentGroup" left="0" right="0" top="0" bottom="0" minWidth="0" minHeight="0" clipAndEnableScrolling="true">
+		<ns:layout>
+			<!--- @copy spark.containers.Accordion#accordionLayout -->
+			<ns:AccordionLayout id="accordionLayout" layoutAllButtonBarBounds="true"/>
+		</ns:layout>
+	</ns:NavigatorGroup>
+	
+	<!--- @copy spark.containers.Accordion#buttonBar -->
+	<s:ButtonBar id="buttonBar"/>
+	
+</s:SparkSkin>


Mime
View raw message