Transferred from the Adobe Open Source Subversion Repository

Revision: 22584
Author:   mhorn@adobe.com
Date:     2011-09-15T20:31:21.235617Z

Log Message:
-----------
asdoc updates

Modified Paths:
--------------
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobiletheme/src/spark/skins/mobile/DateSpinnerSkin.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobilecomponents/src/spark/components/calendarClasses/DateSpinnerItemRenderer.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobilecomponents/src/spark/components/SpinnerList.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobilecomponents/src/spark/components/DateSpinner.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobilecomponents/src/spark/components/SpinnerListContainer.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/spark/src/spark/components/calendarClasses/DateSelectorDisplayMode.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1264010 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/mobilecomponents/src/spark/components/SpinnerList.as
+++ frameworks/projects/mobilecomponents/src/spark/components/SpinnerList.as
@@ -39,7 +39,7 @@
 [Exclude(name="requireSelection", kind="property")]
 [Exclude(name="changing", kind="event")]
 [Exclude(name="itemRollOut", kind="event")]
-[Exclude(name="itemRollOver", kind="event")]
+[Exclude(name="itemRollOver", kind="event")]

 //--------------------------------------
 //  Other metadata
@@ -52,281 +52,370 @@
  *  The SpinnerList component displays a list of items. The item in the center of the
  *  list is always the selectedItem. By default, the list wraps around.
  *
+ *
The following images shows an example of a SpinnerList control:

+ *
+ *

+ *
+ *

+ *
+ *
You can have multiple SpinnerList controls arranged horizontally within a single border by
+ * wrapping then in a SpinnerListContainer.

+ *
+ *  @mxml
The <s:SpinnerList> tag inherits all of the tag
+ *  attributes of its superclass and adds the following tag attributes:

+ *
+ *

+ *  <s:SpinnerList
+ *    Properties
+ *    wrapElements="true|false"
+ *  />
+ *

+ *
+ * @see spark.components.SpinnerListContainer
+ *
  *  @includeExample examples/SpinnerListExample.mxml -noswf
  *  @includeExample examples/SpinnerListContainerExample.mxml -noswf
- *
  *
  *  @langversion 3.0
  *  @playerversion AIR 3
  *  @productversion Flex 4.6
  */
 public class SpinnerList extends ListBase
-{
-	/**
-	 *  Constructor.
-	 *
-	 *  @langversion 3.0
-	 *  @playerversion AIR 3
-	 *  @productversion Flex 4.6
-	 */
-	public function SpinnerList()
-	{
-		super();
-
-		addEventListener(TouchInteractionEvent.TOUCH_INTERACTION_END, touchInteractionEnd);
+{
+    /**
+     *  Constructor.
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    public function SpinnerList()
+    {
+        super();
+
+        addEventListener(TouchInteractionEvent.TOUCH_INTERACTION_END, touchInteractionEnd);
         addEventListener(ResizeEvent.RESIZE, resizeHandler);
-
-		super.requireSelection = true;
-
-		useVirtualLayout = true;
-	}
-
-	//--------------------------------------------------------------------------
-	//
-	//  Variables
-	//
-	//--------------------------------------------------------------------------
-
-	mx_internal static const FORCE_NO_WRAP_ELEMENTS_CHANGE:String = "forceNoWrapElementsChange";
+
+        super.requireSelection = true;
+
+        useVirtualLayout = true;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+
+    mx_internal static const FORCE_NO_WRAP_ELEMENTS_CHANGE:String = "forceNoWrapElementsChange";
     mx_internal static const ENABLED_PROPERTY_NAME:String = "_enabled_";
-
-	private var scrollToSelection:Boolean = false;
-	private var numElementsChanged:Boolean = false;
+
+    private var scrollToSelection:Boolean = false;
+    private var numElementsChanged:Boolean = false;
     private var dispatchChangeEventOnAnimate:Boolean = false;
-
-	private function get spinnerLayout():VerticalSpinnerLayout
-	{
-		return layout as VerticalSpinnerLayout;
-	}
-
-	//--------------------------------------------------------------------------
-	//
-	//  Skin parts
-	//
-	//--------------------------------------------------------------------------
-
-	//----------------------------------
-	//  scroller
-	//----------------------------------
-
-	[SkinPart(required="false")]
-
-	/**
-	 *  The optional Scroller used to scroll the List.
-	 *
-	 *  @langversion 3.0
-	 *  @playerversion AIR 3
-	 *  @productversion Flex 4.6
-	 */
-	public var scroller:Scroller;
-
-	//--------------------------------------------------------------------------
-	//
-	//  Properties
-	//
-	//--------------------------------------------------------------------------
-
-	//----------------------------------
-	//  wrapElements
-	//----------------------------------
-
-	private var forceNoWrapElements:Boolean = false;
-	private var _wrapElements:Boolean = true;
-	private var wrapElementsChanged:Boolean = false;
-
-	/**
-	 *  When true, scrolling past the last element will scroll to the first element.
-	 *
-	 *  @langversion 3.0
-	 *  @playerversion AIR 3
-	 *  @productversion Flex 4.6
-	 *
-	 *  @default true
-	 */
-	public function get wrapElements():Boolean
-	{
-		if (forceNoWrapElements)
-			return false;
-		else
-			return _wrapElements;
-	}
-
-	public function set wrapElements(value:Boolean):void
-	{
-		if (_wrapElements == value)
-			return;
-
-		_wrapElements = value;
-		wrapElementsChanged = true;
-		invalidateProperties();
-	}
-
-	//--------------------------------------------------------------------------
-	//
-	//  Overridden Properties
-	//
-	//--------------------------------------------------------------------------
-
-	//----------------------------------
-	//  caretIndex
-	//----------------------------------
-
-	override public function get caretIndex():Number
-	{
-		// CaretIndex is always equivalent to the selectedIndex
-		return selectedIndex;
-	}
-
-	//----------------------------------
-	//  layout
-	//----------------------------------
-
-	override public function set layout(value:LayoutBase):void
-	{
-		// Layout is not allowed to be set
-		return;
-	}
-
-	override public function set requireSelection(value:Boolean):void
-	{
-		// Selection is always required
-		return;
-	}
-
-	override public function set dataProvider(value:IList):void
-	{
-		super.dataProvider = value;
-
-		numElementsChanged = true;
-		invalidateProperties();
-	}
-
-	//--------------------------------------------------------------------------
-	//
-	//  Overridden methods
-	//
-	//--------------------------------------------------------------------------
-
-	override protected function commitProperties():void
-	{
-		super.commitProperties();
-
-		if (numElementsChanged)
-		{
-			numElementsChanged = false;
-
-			// When the DP changes, the DataGroup sets the scroll position to 0
-			// So we need to wait for updateComplete before resetting the scroll position to
-			// display the selected item in the center
-			if (!scrollToSelection)
-			{
-				scrollToSelection = true;
-				addEventListener(FlexEvent.UPDATE_COMPLETE, updateCompleteHandler);
-			}
-		}
-
-		if (wrapElementsChanged)
-		{
-			if (spinnerLayout)
-			{
-				spinnerLayout.requestedWrapElements = _wrapElements;
-			}
-
-			if (scroller)
-			{
-				scroller.pullEnabled = !wrapElements;
-				scroller.bounceEnabled = !wrapElements;
-			}
-
-			wrapElementsChanged = false;
-		}
-	}
-
-	override protected function commitSelection(dispatchChangedEvents:Boolean=true):Boolean
-	{
-		var result:Boolean = super.commitSelection(dispatchChangedEvents);
-
-		// SnapElement requires a layout pass in order to properly center the selection
-		// The listener for updateComplete calls commitSelection
-		if (initialized && spinnerLayout)
-			scroller.snapElement(spinnerLayout.getClosestUnwrappedElementIndex(selectedIndex), false);
-
-		return result;
-	}
-
-	override protected function partAdded(partName:String, instance:Object):void
-	{
-		super.partAdded(partName, instance);
-
-		if (instance == scroller)
-		{
-			scroller.pullEnabled = !wrapElements;
-			scroller.bounceEnabled = !wrapElements;
-			scroller.scrollSnappingMode = ScrollSnappingMode.CENTER;
-		}
-		else if (instance == dataGroup)
-		{
-			if (dataGroup.layout)
-				dataGroup.layout.addEventListener(FORCE_NO_WRAP_ELEMENTS_CHANGE, forceNoWrapElementsChangeHandler);
-		}
-
-	}
-
-	override protected function partRemoved(partName:String, instance:Object):void
-	{
-		super.partRemoved(partName, instance);
-
-		if (instance == dataGroup)
-		{
-			if (dataGroup.layout)
-				dataGroup.layout.removeEventListener(FORCE_NO_WRAP_ELEMENTS_CHANGE, forceNoWrapElementsChangeHandler);
-		}
-	}
-
-	//--------------------------------------------------------------------------
-	//
-	//  Methods
-	//
-	//--------------------------------------------------------------------------
-
-	/**
-	 *   Animate a spin from the current position to the new index
-	 */
-	mx_internal function animateToSelectedIndex(index:int, dispatchChangeEvent:Boolean = false):void
-	{
-		if (scroller && spinnerLayout)
-		{
-			var animate:Animate = scroller.snapElement(
-				spinnerLayout.getClosestUnwrappedElementIndex(index), true);
-			if (animate)
+
+    /**
+     *  @private
+     */
+    private function get spinnerLayout():VerticalSpinnerLayout
+    {
+        return layout as VerticalSpinnerLayout;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Skin parts
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  scroller
+    //----------------------------------
+
+    [SkinPart(required="false")]
+
+    /**
+     *  The optional Scroller that is used to scroll the List.
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    public var scroller:Scroller;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  wrapElements
+    //----------------------------------
+
+    private var forceNoWrapElements:Boolean = false;
+    private var _wrapElements:Boolean = true;
+    private var wrapElementsChanged:Boolean = false;
+
+    /**
+     *  When true, scrolling past the last element scrolls to the first element.
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     *
+     *  @default true
+     */
+    public function get wrapElements():Boolean
+    {
+        if (forceNoWrapElements)
+            return false;
+        else
+            return _wrapElements;
+    }
+
+    /**
+     *  @private
+     */
+    public function set wrapElements(value:Boolean):void
+    {
+        if (_wrapElements == value)
+            return;
+
+        _wrapElements = value;
+        wrapElementsChanged = true;
+        invalidateProperties();
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  caretIndex
+    //----------------------------------
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    override public function get caretIndex():Number
+    {
+        // CaretIndex is always equivalent to the selectedIndex
+        return selectedIndex;
+    }
+
+    //----------------------------------
+    //  layout
+    //----------------------------------
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    override public function set layout(value:LayoutBase):void
+    {
+        // Layout is not allowed to be set
+        return;
+    }
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    override public function set requireSelection(value:Boolean):void
+    {
+        // Selection is always required
+        return;
+    }
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    override public function set dataProvider(value:IList):void
+    {
+        super.dataProvider = value;
+
+        numElementsChanged = true;
+        invalidateProperties();
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    override protected function commitProperties():void
+    {
+        super.commitProperties();
+
+        if (numElementsChanged)
+        {
+            numElementsChanged = false;
+
+            // When the DP changes, the DataGroup sets the scroll position to 0
+            // So we need to wait for updateComplete before resetting the scroll position to
+            // display the selected item in the center
+            if (!scrollToSelection)
             {
-				animate.addEventListener(EffectEvent.EFFECT_END, animateToIndex_effectEndHandler);
+                scrollToSelection = true;
+                addEventListener(FlexEvent.UPDATE_COMPLETE, updateCompleteHandler);
+            }
+        }
+
+        if (wrapElementsChanged)
+        {
+            if (spinnerLayout)
+            {
+                spinnerLayout.requestedWrapElements = _wrapElements;
+            }
+
+            if (scroller)
+            {
+                scroller.pullEnabled = !wrapElements;
+                scroller.bounceEnabled = !wrapElements;
+            }
+
+            wrapElementsChanged = false;
+        }
+    }
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    override protected function commitSelection(dispatchChangedEvents:Boolean=true):Boolean
+    {
+        var result:Boolean = super.commitSelection(dispatchChangedEvents);
+
+        // SnapElement requires a layout pass in order to properly center the selection
+        // The listener for updateComplete calls commitSelection
+        if (initialized && spinnerLayout)
+            scroller.snapElement(spinnerLayout.getClosestUnwrappedElementIndex(selectedIndex), false);
+
+        return result;
+    }
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    override protected function partAdded(partName:String, instance:Object):void
+    {
+        super.partAdded(partName, instance);
+
+        if (instance == scroller)
+        {
+            scroller.pullEnabled = !wrapElements;
+            scroller.bounceEnabled = !wrapElements;
+            scroller.scrollSnappingMode = ScrollSnappingMode.CENTER;
+        }
+        else if (instance == dataGroup)
+        {
+            if (dataGroup.layout)
+                dataGroup.layout.addEventListener(FORCE_NO_WRAP_ELEMENTS_CHANGE, forceNoWrapElementsChangeHandler);
+        }
+
+    }
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 3
+     *  @productversion Flex 4.6
+     */
+    override protected function partRemoved(partName:String, instance:Object):void
+    {
+        super.partRemoved(partName, instance);
+
+        if (instance == dataGroup)
+        {
+            if (dataGroup.layout)
+                dataGroup.layout.removeEventListener(FORCE_NO_WRAP_ELEMENTS_CHANGE, forceNoWrapElementsChangeHandler);
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *   Animate a spin from the current position to the new index.
+     */
+    mx_internal function animateToSelectedIndex(index:int, dispatchChangeEvent:Boolean = false):void
+    {
+        if (scroller && spinnerLayout)
+        {
+            var animate:Animate = scroller.snapElement(
+                spinnerLayout.getClosestUnwrappedElementIndex(index), true);
+            if (animate)
+            {
+                animate.addEventListener(EffectEvent.EFFECT_END, animateToIndex_effectEndHandler);
                 dispatchChangeEventOnAnimate = dispatchChangeEvent;
             }
-		}
-	}
-
-	mx_internal function animateToIndex_effectEndHandler(event:EffectEvent):void
-	{
-		if (spinnerLayout)
-		{
-			// Commit the center item as the selectedItem
-			var centerElementIndex:int = spinnerLayout.getIndexAtVerticalCenter();
+        }
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function animateToIndex_effectEndHandler(event:EffectEvent):void
+    {
+        if (spinnerLayout)
+        {
+            // Commit the center item as the selectedItem
+            var centerElementIndex:int = spinnerLayout.getIndexAtVerticalCenter();
             if (dispatchChangeEventOnAnimate)
                 setSelectedIndex(centerElementIndex, true);
             else
-			    selectedIndex = centerElementIndex;
-		}
-
-		Animate(event.currentTarget).removeEventListener(EffectEvent.EFFECT_END, animateToIndex_effectEndHandler);
-	}
-
-	//--------------------------------------------------------------------------
-	//
-	//  Event handlers
-	//
-	//--------------------------------------------------------------------------
-
+                selectedIndex = centerElementIndex;
+        }
+
+        Animate(event.currentTarget).removeEventListener(EffectEvent.EFFECT_END, animateToIndex_effectEndHandler);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Event handlers
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
     private function resizeHandler(event:ResizeEvent):void
     {
         if ((event.oldWidth != width || event.oldHeight != height) && !scrollToSelection)
@@ -336,106 +425,115 @@
         }
     }

-	private function touchInteractionEnd(event:TouchInteractionEvent):void
-	{
-		// Commit the center item as the selectedItem when the scroll has completed
-		if (spinnerLayout)
-		{
-			var centerElementIndex:int = spinnerLayout.getIndexAtVerticalCenter();
-			setSelectedIndex(centerElementIndex, true);
-		}
-	}
-
-	override protected function dataProvider_collectionChangeHandler(event:Event):void
-	{
-		super.dataProvider_collectionChangeHandler(event);
-
-		if (event is CollectionEvent)
-		{
-			var ce:CollectionEvent = CollectionEvent(event);
-
-			if (ce.kind == CollectionEventKind.ADD ||
-				ce.kind == CollectionEventKind.REMOVE ||
-				ce.kind == CollectionEventKind.RESET ||
-				ce.kind == CollectionEventKind.REFRESH)
-			{
-				numElementsChanged = true;
-				invalidateProperties();
-			}
-		}
-	}
-
-	/**
-	 *  @private
-	 *  Called when an item has been added to this component.
-	 */
-	override protected function dataGroup_rendererAddHandler(event:RendererExistenceEvent):void
-	{
-		super.dataGroup_rendererAddHandler(event);
-		var renderer:IVisualElement = event.renderer;
-
-		if (!renderer)
-			return;
-
-		renderer.addEventListener(MouseEvent.CLICK, item_mouseClickHandler);
-	}
-
-	/**
-	 *  @private
-	 *  Called when an item has been removed from this component.
-	 */
-	override protected function dataGroup_rendererRemoveHandler(event:RendererExistenceEvent):void
-	{
-		super.dataGroup_rendererRemoveHandler(event);
-
-		var renderer:Object = event.renderer;
-
-		if (!renderer)
-			return;
-
-		renderer.removeEventListener(MouseEvent.CLICK, item_mouseClickHandler);
-	}
-
-	/**
-	 *  When an item is clicked, animate it to the center
-	 */
-	private function item_mouseClickHandler(event:MouseEvent):void
-	{
-		var newIndex:int;
-
-		if (event.currentTarget is IItemRenderer)
-			newIndex = IItemRenderer(event.currentTarget).itemIndex;
-		else
-			newIndex = dataGroup.getElementIndex(event.currentTarget as IVisualElement);
-
-		// If an item is disabled, then don't animate to that item
-		if (event.currentTarget["enabled"] == undefined ||
-			event.currentTarget["enabled"] == true)
-			animateToSelectedIndex(newIndex, true);
-	}
-
-	/**
-	 *  Animate the selectedItem to the center once we have performed a layout pass
-	 */
-	private function updateCompleteHandler(event:FlexEvent):void
-	{
-		if (scrollToSelection && spinnerLayout)
-		{
-			scrollToSelection = false;
-			scroller.snapElement(spinnerLayout.getClosestUnwrappedElementIndex(selectedIndex), false);
-
-			removeEventListener(FlexEvent.UPDATE_COMPLETE, updateCompleteHandler);
-		}
-	}
-
-	/**
-	 *  Called if the layout has automatically switched wrap modes
-	 */
-	private function forceNoWrapElementsChangeHandler(event:Event):void
-	{
-		invalidateProperties();
-		forceNoWrapElements = spinnerLayout.forceNoWrapElements;
-		wrapElementsChanged = true;
-	}
+    /**
+     *  @private
+     */
+    private function touchInteractionEnd(event:TouchInteractionEvent):void
+    {
+        // Commit the center item as the selectedItem when the scroll has completed
+        if (spinnerLayout)
+        {
+            var centerElementIndex:int = spinnerLayout.getIndexAtVerticalCenter();
+            setSelectedIndex(centerElementIndex, true);
+        }
+    }
+
+    /**
+     *  @private
+     */
+    override protected function dataProvider_collectionChangeHandler(event:Event):void
+    {
+        super.dataProvider_collectionChangeHandler(event);
+
+        if (event is CollectionEvent)
+        {
+            var ce:CollectionEvent = CollectionEvent(event);
+
+            if (ce.kind == CollectionEventKind.ADD ||
+                ce.kind == CollectionEventKind.REMOVE ||
+                ce.kind == CollectionEventKind.RESET ||
+                ce.kind == CollectionEventKind.REFRESH)
+            {
+                numElementsChanged = true;
+                invalidateProperties();
+            }
+        }
+    }
+
+    /**
+     *  @private
+     *  Called when an item has been added to this component.
+     */
+    override protected function dataGroup_rendererAddHandler(event:RendererExistenceEvent):void
+    {
+        super.dataGroup_rendererAddHandler(event);
+        var renderer:IVisualElement = event.renderer;
+
+        if (!renderer)
+            return;
+
+        renderer.addEventListener(MouseEvent.CLICK, item_mouseClickHandler);
+    }
+
+    /**
+     *  @private
+     *  Called when an item has been removed from this component.
+     */
+    override protected function dataGroup_rendererRemoveHandler(event:RendererExistenceEvent):void
+    {
+        super.dataGroup_rendererRemoveHandler(event);
+
+        var renderer:Object = event.renderer;
+
+        if (!renderer)
+            return;
+
+        renderer.removeEventListener(MouseEvent.CLICK, item_mouseClickHandler);
+    }
+
+    /**
+     * @private
+     *  When an item is clicked, animate it to the center
+     */
+    private function item_mouseClickHandler(event:MouseEvent):void
+    {
+        var newIndex:int;
+
+        if (event.currentTarget is IItemRenderer)
+            newIndex = IItemRenderer(event.currentTarget).itemIndex;
+        else
+            newIndex = dataGroup.getElementIndex(event.currentTarget as IVisualElement);
+
+        // If an item is disabled, then don't animate to that item
+        if (event.currentTarget["enabled"] == undefined ||
+            event.currentTarget["enabled"] == true)
+            animateToSelectedIndex(newIndex, true);
+    }
+
+    /**
+     * @private
+     *  Animate the selectedItem to the center once we have performed a layout pass
+     */
+    private function updateCompleteHandler(event:FlexEvent):void
+    {
+        if (scrollToSelection && spinnerLayout)
+        {
+            scrollToSelection = false;
+            scroller.snapElement(spinnerLayout.getClosestUnwrappedElementIndex(selectedIndex), false);
+
+            removeEventListener(FlexEvent.UPDATE_COMPLETE, updateCompleteHandler);
+        }
+    }
+
+    /**
+     * @private
+     * Called if the layout has automatically switched wrap modes.
+     */
+    private function forceNoWrapElementsChangeHandler(event:Event):void
+    {
+        invalidateProperties();
+        forceNoWrapElements = spinnerLayout.forceNoWrapElements;
+        wrapElementsChanged = true;
+    }
 }
 }


Transferred from the Adobe Open Source Subversion Repository

Revision: 9708
Author:   cframpto@adobe.com
Date:     2009-08-27T20:22:38.464977Z

Log Message:
-----------
Add TLFTextInput which allows Halo controls to use the spark FTE/TLF-based TextInput component wherever a Halo TextInput can be used.

This is done by introducing a new style for Halo called textInputClass.  In the global selector, in defaults.css, it defaults to mx.controls.TextInput.  This style only applies for Flex version 4 and up.

To use TLFText apply the new TLFText.css style sheet as a theme to your application.  Alternatively you may apply this style sheet in your application but you will see compiler warnings for any unused selectors.

Note that mx.controls.TLFTextInput lives in spark.swc since it is build on spark.components.TextInput.

Modified ColorPicker, DateField, ComboBox, NumericStepper and TextInput to look at the textInputClass field to determine whether to use a Halo TextInput or a Spark TextInput.

QE notes:
Doc notes:
Bugs:
Reviewer: Gordon
Tests run: mx ColorPicker,DateField,ComboBox,NumericStepper and TextInput as well as checkintests
one ColorPicker_events_toolTipHide failed - the timer does fire eventually but it seems to take much longer than the hideDelay=10000.
Is noteworthy for integration: yes

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/ComboBox.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/ComboBase.as</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/spark/src/mx/controls/TLFTextInput.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/defaults.css</path>
<path kind="dir" action="A">/flex/sdk/trunk/frameworks/projects/spark/src/mx</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/managers/IFocusManagerComponent.as</path>
<path kind="dir" action="A">/flex/sdk/trunk/frameworks/projects/spark/src/mx/controls</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/framework/src/mx/core/ITextInput.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/colorPickerClasses/SwatchPanel.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/TextInput.as</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/spark/TLFText.css</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/NumericStepper.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1268687 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/mx/src/mx/controls/colorPickerClasses/SwatchPanel.as
+++ frameworks/projects/mx/src/mx/controls/colorPickerClasses/SwatchPanel.as
@@ -12,6 +12,7 @@
 package mx.controls.colorPickerClasses
 {

+import flash.display.DisplayObject;
 import flash.events.Event;
 import flash.events.EventPhase;
 import flash.events.KeyboardEvent;
@@ -24,6 +25,7 @@
 import mx.controls.TextInput;
 import mx.core.FlexVersion;
 import mx.core.IFlexDisplayObject;
+import mx.core.ITextInput;
 import mx.core.UIComponent;
 import mx.core.mx_internal;
 import mx.events.ColorPickerEvent;
@@ -352,7 +354,7 @@
     /**
      *  @private
      */
-    mx_internal var textInput:TextInput;
+    mx_internal var textInput:ITextInput;

     /**
      *  @private
@@ -950,7 +952,17 @@
         // Create the hex text field
         if (!textInput)
 		{
-			textInput = new TextInput();
+            // Mechanism to use TLFTextInput.
+            var textInputClass:Class = getStyle("textInputClass");
+            if (!textInputClass ||
+                FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_0)
+            {
+                textInput = new TextInput();
+            }
+            else
+            {
+                textInput = new textInputClass();
+            }

 			if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_3_0)
 			{
@@ -978,7 +990,7 @@
 			textInput.addEventListener(Event.CHANGE, textInput_changeHandler);
 			textInput.addEventListener(KeyboardEvent.KEY_DOWN, textInput_keyDownHandler);

-			addChild(textInput);
+			addChild(DisplayObject(textInput));
 		}

         // Create the swatches grid
@@ -1490,7 +1502,7 @@
     private function textInput_changeHandler(event:Event):void
     {
         // Handle events from hex TextField.
-        var color:String = TextInput(event.target).text;
+        var color:String = ITextInput(event.target).text;
         if (color.charAt(0) == "#")
         {
             textInput.maxChars = 7;


Transferred from the Adobe Open Source Subversion Repository

Revision: 23243
Author:   cframpto@adobe.com
Date:     2011-12-20T00:59:57.384047Z

Log Message:
-----------
In frameworks, remove Adobe headers from all files except xml/mxml file types.  There are also a few .txt files that are license files that I didn't touch yet.

Modified Paths:
--------------
2361 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1273841 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/rpc/src/mx/messaging/events/MessagePersisterEvent.as
+++ frameworks/projects/rpc/src/mx/messaging/events/MessagePersisterEvent.as
@@ -1,13 +1,3 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-//  ADOBE SYSTEMS INCORPORATED
-//  Copyright 2005-2007 Adobe Systems Incorporated
-//  All Rights Reserved.
-//
-//  NOTICE: Adobe permits you to use, modify, and distribute this file
-//  in accordance with the terms of the license agreement accompanying it.
-//
-////////////////////////////////////////////////////////////////////////////////

 package mx.messaging.events
 {


Transferred from the Adobe Open Source Subversion Repository

Revision: 7980
Author:   hmuller@adobe.com
Date:     2009-06-18T21:55:51.288721Z

Log Message:
-----------
Fix default values for delegated Skinnable{Data}Container scroll position properties.  Default was NaN, correct default is 0.

QE Notes: Fixes a problem caused by SVN 7929, "Range et al PARB changes, Opus #1"
Doc Notes:
Bugs:  sdk-21891, sdk21878
Reviewer: Evtim

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/SkinnableContainer.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/SkinnableDataContainer.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1280709 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/components/SkinnableDataContainer.as
+++ frameworks/projects/spark/src/spark/components/SkinnableDataContainer.as
@@ -14,13 +14,10 @@

 import mx.collections.IList;
 import mx.core.IFactory;
-import mx.core.IVisualElement;
-import mx.events.FlexEvent;
+import mx.core.IVisualElement;
 import mx.events.PropertyChangeEvent;
-import mx.managers.IFocusManagerContainer;
 import mx.utils.BitFlagUtil;

-import spark.components.supportClasses.ItemRenderer;
 import spark.components.supportClasses.SkinnableContainerBase;
 import spark.core.IViewport;
 import spark.events.RendererExistenceEvent;
@@ -422,9 +419,11 @@
      */
     public function get horizontalScrollPosition():Number
     {
-        return (dataGroup)
-            ? dataGroup.horizontalScrollPosition
-            : dataGroupProperties.horizontalScrollPosition;
+        if (dataGroup)
+            return dataGroup.horizontalScrollPosition;
+
+        var hsp:Number = dataGroupProperties.horizontalScrollPosition;
+        return isNaN(hsp) ? 0 : hsp;
     }

     /**
@@ -596,9 +595,11 @@
      */
     public function get verticalScrollPosition():Number
     {
-        return (dataGroup)
-            ? dataGroup.verticalScrollPosition
-            : dataGroupProperties.verticalScrollPosition;
+        if (dataGroup)
+            return dataGroup.verticalScrollPosition;
+
+        var vsp:Number = dataGroupProperties.verticalScrollPosition;
+        return isNaN(vsp) ? 0 : vsp;
     }

     /**


Transferred from the Adobe Open Source Subversion Repository

Revision: 10190
Author:   jszeto@adobe.com
Date:     2009-09-12T00:12:31.165372Z

Log Message:
-----------
Adding cornerRadius support to Spark ContainerBorderSkin for mx containers

http://bugs.adobe.com/jira/browse/SDK-23014 - Setting cornerRadius on Tab does nothing

This bug actually affected all Halo containers. The ContainerBorderSkin didn’t have any support for cornerRadius. I added the cornerRadius property to BorderSkin. BorderSkin doesn't grab the cornerRadius style, so it will always have a cornerRadius of 0. ContainerBorderSkin will set cornerRadius property to the cornerRadius style value.

QE notes: None
Doc notes: None
Bugs: SDK-23014
Reviewer: Glenn
Tests run: containers
Is noteworthy for integration: No

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/development/eclipse/flex/airframework/.project</path>
<path kind="file" action="M">/flex/sdk/trunk/development/eclipse/flex/spark/.actionScriptProperties</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/sparkskins/src/mx/skins/spark/BorderSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/development/eclipse/flex/spark/.flexLibProperties</path>
<path kind="file" action="M">/flex/sdk/trunk/development/eclipse/flex/spark/.project</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/sparkskins/src/mx/skins/spark/ContainerBorderSkin.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1288259 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/sparkskins/src/mx/skins/spark/ContainerBorderSkin.as
+++ frameworks/projects/sparkskins/src/mx/skins/spark/ContainerBorderSkin.as
@@ -26,6 +26,11 @@
      */
     override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
     {
+        var cr:Number = getStyle("cornerRadius");
+
+        if (cornerRadius != cr)
+            cornerRadius = cr;
+
         // Push backgroundColor and backgroundAlpha directly.
         // Handle undefined backgroundColor by hiding the background object.
         if (isNaN(getStyle("backgroundColor")))
@@ -41,5 +46,6 @@

         super.updateDisplayList(unscaledWidth, unscaledHeight);
     }
+
 }
 }


Transferred from the Adobe Open Source Subversion Repository

Revision: 8847
Author:   aharui@adobe.com
Date:     2009-07-28T02:07:59.326177Z

Log Message:
-----------
Fix an injection from Frame1 cleanup.  Also a side-effect of the tabChildren change

QE Notes: None
Doc Notes: None
Bugs: SDK-22222
Reviewer: Mustella
API Change: No
Is noteworthy for integration: No
tests: checkintests mustella/components/ComboBox, NumericStepper, DateField, PopUpButton, mustella/gumbo/DropDownList mustella/MarshallPlan

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/ComboBox.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/spark/src/spark/components/DropDownList.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/ComboBase.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/managers/systemClasses/MarshallingSupport.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/PopUpButton.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/DateField.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/controls/NumericStepper.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1268032 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/mx/src/mx/controls/ComboBox.as
+++ frameworks/projects/mx/src/mx/controls/ComboBox.as
@@ -2076,7 +2076,7 @@
         // the dropdown and then click outside the application.

         // If the dropdown is open...
-        if (_showingDropdown && _dropdown)
+        if (_showingDropdown && _dropdown && event.target == this)
         {
             // If focus is moving outside the dropdown...
             if (!event.relatedObject ||


updated doc

updated doc

--- actionscript/src/com/freshplanet/ane/AirDeviceId.as
+++ actionscript/src/com/freshplanet/ane/AirDeviceId.as
@@ -103,8 +103,8 @@
 		/**
 		 *
 		 * @param 	salt		a developer specific salt
-		 * @param	callback
-		 * @return				unique id for this device
+		 * @param	callback	method which accepts a param for a unique id for this device </br>
+		 * 						function( id:String ) : void
 		 */
 		public function getID( salt:String, callback:Function ) : void {

@@ -122,8 +122,8 @@
 		}

 		/**
-		 * @param	callback	d
-		 * @return 				vendor id or null on unavailable/Android
+		 * @param	callback	method which accepts a param for a vendor id or null on unavailable/Android </br>
+		 * 						function( idfv:String ) : void
 		 */
 		public function getIDFV( callback:Function ) : void {

@@ -144,8 +144,8 @@
 		}

 		/**
-		 * @param	callback	d
-		 * @return 				advertiser id
+		 * @param	callback	method which accepts a param for an advertiser id </br>
+		 * 						function( idfa:String ) : void
 		 */
 		public function getIDFA( callback:Function ) : void {

@@ -154,7 +154,7 @@
 				callback( null );
 				return;
 			}
-
+
 			if ( _idfa ) {
 				callback( _idfa == '00000000-0000-0000-0000-000000000000' ? null : _idfa );
 			}


render for null texture

render for null texture

--- client/Anim/src/com/genome2d/components/renderables/jointanim/JAnim.as
+++ client/Anim/src/com/genome2d/components/renderables/jointanim/JAnim.as
@@ -551,6 +551,10 @@
                         _local19 = 0;
                         while (true)
                         {
+							if (_local20.animFrameNum < 0)
+							{
+								break;
+							}
                             _local11 = _JointAnimate.imageVector[_local20.resNum];
                             _local13 = _local24.TransformSrc(_local11.transform, _local24);
                             _local23 = _helpDrawSpriteASrcRect;


create animation format in miracle

create animation format in miracle

--- src/com/merlinds/miracle_tool/viewer/ViewerView.as
+++ src/com/merlinds/miracle_tool/viewer/ViewerView.as
@@ -11,6 +11,7 @@
 	import com.merlinds.miracle.Miracle;
 	import com.merlinds.miracle.display.MiracleImage;
 	import com.merlinds.miracle.utils.Asset;
+	import com.merlinds.miracle.utils.MafReader;
 	import com.merlinds.miracle.utils.MtfReader;
 	import com.merlinds.miracle_tool.models.AppModel;

@@ -69,7 +70,12 @@

 		private function getAnimations(bytes:ByteArray):Array {
 			var result:Array = [];
-
+			var reader:MafReader = new MafReader();
+			reader.execute(bytes);
+			var animations:Vector.<Object> = reader.animations;
+			for each(var animation:Object in animations){
+				result.push(animation.name);
+			}
 			return result;
 		}
 		//} endregion PRIVATE\PROTECTED METHODS ========================================


[Performance] instance level length var access adds a small speedup over requesting byteLength from the ArrayBuffer

--- frameworks/projects/Core/src/main/flex/org/apache/flex/utils/BinaryData.as
+++ frameworks/projects/Core/src/main/flex/org/apache/flex/utils/BinaryData.as
@@ -56,6 +56,7 @@
     public function BinaryData(bytes:ArrayBuffer = null)
     {
         ba = bytes ? bytes : new ArrayBuffer(0);
+        _len = ba.byteLength;
     }

     /**
@@ -481,9 +482,9 @@
         {
             //do we need to check offset and length and sanitize or throw an error?

-            if (length == 0) length = ba.byteLength - _position ;
+            if (length == 0) length = _len - _position ;
             //extend the destination length if necessary
-            var extra:int = offset + length - destination.ba.byteLength;
+            var extra:int = offset + length - destination._len;
             if (extra > 0)
                 destination.growBuffer(extra);
             var src:Uint8Array = new Uint8Array(ba, _position,length);
@@ -546,7 +547,7 @@
         }
         COMPILE::JS
         {
-            if (idx >= ba.byteLength) {
+            if (idx >= _len) {
                 setBufferSize(idx+1);
             }
             getTypedArray()[idx] = byte;
@@ -713,6 +714,9 @@
         }
     }

+    COMPILE::JS
+    private var _len:uint;
+

     public function get length():int
     {
@@ -722,7 +726,7 @@
         }
         COMPILE::JS
         {
-            return ba.byteLength;
+            return _len;;
         }
     }

@@ -743,7 +747,7 @@
     COMPILE::JS
     protected function setBufferSize(newSize):void
     {
-        var n:uint = ba.byteLength;
+        var n:uint = _len;
         if (n != newSize) {
             //note: ArrayBuffer.slice could be better for buffer size reduction
             //looks like it is only IE11+, so not using it here
@@ -754,6 +758,7 @@
             ba = newView.buffer;
             if (_position > newSize) _position = newSize;
             _typedArray = newView;
+            _len = newSize;
         }
     }
     /**
@@ -772,7 +777,7 @@
         }
         COMPILE::JS
         {
-            return ba.byteLength - _position;
+            return _len - _position;
         }
     }

@@ -837,13 +842,13 @@

         COMPILE::JS
         {
-            setBufferSize(ba.byteLength + extra);
+            setBufferSize(_len + extra);
         }
     }

     COMPILE::JS
     protected function ensureWritableBytes(len:uint):void{
-        if (_position + len > ba.byteLength) {
+        if (_position + len > _len) {
             setBufferSize( _position + len );
         }
     }
@@ -998,7 +1003,7 @@
     private function mergeInToArrayBuffer(offset:uint, newBytes:Uint8Array):uint {
         var newContentLength:uint = newBytes.length;
         var dest:Uint8Array;
-        if (offset + newContentLength > ba.byteLength) {
+        if (offset + newContentLength > _len) {
             dest = new Uint8Array(offset + newContentLength);
             dest.set(new Uint8Array(ba, 0, offset));
             dest.set(newBytes, offset);


Transferred from the Adobe Open Source Subversion Repository

Revision: 12850
Author:   jimurphy@adobe.com
Date:     2009-12-11T14:57:14.623098Z

Log Message:
-----------
add 6 new DMV projects to the SDK:
automation
automation_air
automation_dmv
automation_flashflexkit
automation_spark
datavisualization

These projects are setup to build in an ant main call.  There are currently several warnings in the datavisualization project that will be cleaned up.  No checkintests exist for these projects as of yet.

I also modified the exisitng projects build files for easier management of the localization targets, bundle and fat-swc. If the projects that I updated:airframework,airspark,framework,playerglobal,rpc,and spark.  All the new projects have been implemented this same way.

QE notes: DMV folks should run through their tests
Doc notes: probably
Bugs: nope
Reviewer:
Tests run: ran the following targets: compile,checkintests,other.locales and doc
Is noteworthy for integration: no

Modified Paths:
--------------
1404 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1290241 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/advancedgrids/src/mx/collections/GroupingCollection.as
+++ frameworks/projects/advancedgrids/src/mx/collections/GroupingCollection.as
@@ -0,0 +1,1736 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  ADOBE SYSTEMS INCORPORATED
+//  Copyright 2009 Adobe Systems Incorporated
+//  All Rights Reserved.
+//
+//  NOTICE: Adobe permits you to use, modify, and distribute this file
+//  in accordance with the terms of the license agreement accompanying it.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.collections
+{
+
+import flash.events.TimerEvent;
+import flash.utils.Dictionary;
+import flash.utils.Timer;
+import flash.xml.XMLNode;
+
+import mx.collections.errors.ItemPendingError;
+import mx.core.mx_internal;
+import mx.events.CollectionEvent;
+import mx.events.CollectionEventKind;
+import mx.utils.UIDUtil;
+
+use namespace mx_internal;
+
+//--------------------------------------
+//  Other metadata
+//--------------------------------------
+
+[DefaultProperty("grouping")]
+
+/**
+ *  The GroupingCollection class lets you create grouped data from flat data
+ *  for display in the AdvancedDataGrid control.
+ *  When you create the instance of the GroupingCollection from your flat data,
+ *  you specify the field or fields of the data used to create the hierarchy.
+ *
+ *
To populate the AdvancedDataGrid control with grouped data,
+ *  you create an instance of the GroupingCollection class from your flat data,
+ *  and then pass that GroupingCollection instance to the data provider
+ *  of the AdvancedDataGrid control.
+ *  To specify the grouping fields of your flat data,
+ *  you pass a Grouping instance to
+ *  the GroupingCollection.grouping property.
+ *  The Grouping instance contains an Array of GroupingField instances,
+ *  one per grouping field.

+ *
+ *
The following example uses the GroupingCollection class to define
+ *  two grouping fields: Region and Territory.

+ *
+ *

+ *  <mx:AdvancedDataGrid id="myADG"
+ *    <mx:dataProvider>
+ *      <mx:GroupingCollection id="gc" source="{dpFlat}">
+ *        <mx:grouping>
+ *          <mx:Grouping>
+ *            <mx:GroupingField name="Region"/>
+ *            <mx:GroupingField name="Territory"/>
+ *          </mx:Grouping>
+ *        </mx:grouping>
+ *      </mx:GroupingCollection>
+ *    </mx:dataProvider>
+ *
+ *    <mx:columns>
+ *      <mx:AdvancedDataGridColumn dataField="Region"/>
+ *      <mx:AdvancedDataGridColumn dataField="Territory"/>
+ *      <mx:AdvancedDataGridColumn dataField="Territory_Rep"/>
+ *      <mx:AdvancedDataGridColumn dataField="Actual"/>
+ *      <mx:AdvancedDataGridColumn dataField="Estimate"/>
+ *    </mx:columns>
+ *  </mx:AdvancedDataGrid>
+ *

+ *
+ *  @mxml
+ *
+ *  The <mx.GroupingCollection> inherits all the tag attributes of its superclass,
+ *  and defines the following tag attributes:

+ *
+ *

+ *  <mx:GroupingCollection
+ *  Properties
+ *    grouping="No default"
+ *    source="No default"
+ *    summaries="No default"
+ *  />
+ *

+ *
+ *
This Class has been deprecated and replaced by a new Class
+ *  GroupingCollection2 which provide faster,
+ *  improved performance and a new summary calculation mechanism.
+ *  Class SummaryField has also been deprecated and
+ *  replaced by a new Class SummaryField2.
+ *  Properties operation and summaryFunction are
+ *  not present in the Class SummaryField2.
+ *  A new property summaryOperation is introduced in
+ *  SummaryField2.

+ *
+ *  @see mx.controls.AdvancedDataGrid
+ *  @see mx.collections.Grouping
+ *  @see mx.collections.GroupingField
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Deprecated(replacement="GroupingCollection2", since="4.0")]
+
+public class GroupingCollection extends HierarchicalData implements IGroupingCollection
+{
+    include "../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function GroupingCollection()
+    {
+        super();
+
+        newCollection = new ArrayCollection();
+        super.source = newCollection;
+
+        objectSummaryMap = new Dictionary(false);
+
+        parentMap = {};
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *
+     *  denotes if the refresh is asynchronous.
+     */
+    private var async:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var newCollection:ArrayCollection;
+
+    /**
+     *  @private
+     */
+    private var _sourceCol:ICollectionView;
+
+    /**
+     *  @private
+     *
+     *  the object summary map.
+     *  keeps summaries corresponding to different objects
+     */
+    private var objectSummaryMap:Dictionary;
+
+    /**
+     *  @private
+     *
+     *  the original sort applied to the source collection
+     */
+    private var oldSort:Sort;
+
+    /**
+     *  @private
+     */
+    private var prepared:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var flatView:ICollectionView;
+
+    /**
+     *  @private
+     */
+    private var flatCursor:IViewCursor;
+
+    /**
+     *  @private
+     */
+    private var hView:ICollectionView;
+
+    /**
+     *  @private
+     */
+    private var treeCursor:IViewCursor;
+
+    /**
+     *  @private
+     */
+    private var currentPosition:CursorBookmark = CursorBookmark.FIRST;
+
+    /**
+     *  @private
+     */
+    private var gf:Array;
+
+    /**
+     *  @private
+     */
+    private var fieldCount:int;
+
+    /**
+     *  @private
+     *
+     *  contains current data being compared
+     */
+    private var currentData:Object;
+
+    /**
+     *  @private
+     *
+     *  contains current group objects for different group fields
+     */
+    private var currentGroups:Array;
+
+    /**
+     *  @private
+     *
+     *  contains current group labels for different group fields
+     */
+    private var currentGroupLabels:Array;
+
+    /**
+     *  @private
+     *
+     *  contains next index for different group fields
+     */
+    private var currentIndices:Array;
+
+    /**
+     *  @private
+     *
+     *  item index
+     */
+    private var itemIndex:int;
+
+    /**
+     *  @private
+     *
+     *  the children array for the group
+     */
+    private var childrenArray:Array;
+
+    /**
+     *  @private
+     */
+    private var summaryPresent:Boolean;
+
+    /**
+     *  @private
+     */
+    mx_internal var optimizeSummaries:Boolean = false;
+
+    /**
+     *  The timer which is associated with an asynchronous refresh operation.
+     *  You can use it to change the timing interval, pause the refresh,
+     *  or perform other actions.
+     *
+     *  The default value for the delay property of the
+     *  Timer instance is 1, corresponding to 1 millisecond.
+     *
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected var timer:Timer;
+
+    /**
+     *  @private
+     *  Mapping of UID to parents.  Must be maintained as things get removed/added
+     *  This map is created as objects are visited
+     */
+    protected var parentMap:Object;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    // grouping
+    //----------------------------------
+
+    private var _grouping:Grouping;
+
+    /**
+     *  Specifies the Grouping instance applied to the source data.
+     *  Setting the grouping property
+     *  does not automatically refresh the view,
+     *  so you must call the refresh() method
+     *  after setting this property.
+     *
+     *  @see mx.collections.GroupingCollection#refresh()
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get grouping():Grouping
+    {
+        return _grouping;
+    }
+
+    /**
+     *  @private
+     */
+    public function set grouping(value:Grouping):void
+    {
+        _grouping = value;
+    }
+
+    //----------------------------------
+    // summaries
+    //----------------------------------
+
+    /**
+     *  Array of SummaryRow instances that define any root-level data summaries.
+     *  Specify one or more SummaryRow instances to define the data summaries,
+     *  as the following example shows:
+     *
+     *

+     *  <mx:AdvancedDataGrid id="myADG"
+     *     width="100%" height="100%"
+     *     initialize="gc.refresh();">
+     *     <mx:dataProvider>
+     *         <mx:GroupingCollection id="gc" source="{dpFlat}">
+     *             <mx:summaries>
+     *                 <mx:SummaryRow summaryPlacement="last">
+     *                     <mx:fields>
+     *                         <mx:SummaryField dataField="Actual"
+     *                             label="Min Actual" operation="MIN"/>
+     *                         <mx:SummaryField dataField="Actual"
+     *                             label="Max Actual" operation="MAX"/>
+     *                     </mx:fields>
+     *                   </mx:SummaryRow>
+     *                 </mx:summaries>
+     *             <mx:Grouping>
+     *                 <mx:GroupingField name="Region"/>
+     *                 <mx:GroupingField name="Territory"/>
+     *             </mx:Grouping>
+     *         </mx:GroupingCollection>
+     *     </mx:dataProvider>
+     *
+     *     <mx:columns>
+     *         <mx:AdvancedDataGridColumn dataField="Region"/>
+     *         <mx:AdvancedDataGridColumn dataField="Territory_Rep"
+     *             headerText="Territory Rep"/>
+     *         <mx:AdvancedDataGridColumn dataField="Actual"/>
+     *         <mx:AdvancedDataGridColumn dataField="Estimate"/>
+     *         <mx:AdvancedDataGridColumn dataField="Min Actual"/>
+     *         <mx:AdvancedDataGridColumn dataField="Max Actual"/>
+     *     </mx:columns>
+     *  </mx:AdvancedDataGrid>

+     *
+     *  @see mx.collections.SummaryRow
+     *  @see mx.collections.SummaryField
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var summaries:Array;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overriden Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  The source collection containing the flat data to be grouped.
+     *
+     *  If the source is not a collection, it will be auto-wrapped into a collection.
+     *
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function get source():Object
+    {
+        return _sourceCol;
+    }
+
+    override public function set source(value:Object):void
+    {
+        if (_sourceCol)
+            _sourceCol.removeEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
+
+        if (!value)
+        {
+            _sourceCol = null;
+            return;
+        }
+
+        _sourceCol = getCollection(value);
+
+        if(_sourceCol is ICollectionView)
+            _sourceCol.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
+    }
+
+    /**
+     * @private
+     */
+    override public function getChildren(node:Object):Object
+    {
+        var children:Object = super.getChildren(node);
+
+        // populate the parentMap
+        // parentMap will be populated only if the children is ICollectionView
+        var uid:String;
+        if (children != null)
+        {
+        	if (children is ICollectionView)
+            {
+	            var cursor:IViewCursor = ICollectionView(children).createCursor();
+	            while (!cursor.afterLast)
+	            {
+	                uid = UIDUtil.getUID(cursor.current);
+	                parentMap[uid] = node;
+	                cursor.moveNext();
+	            }
+            }
+            else
+            {
+            	//if the children is not ICollectionView then
+            	//it was not introduced by GC. (this happens in the case of XML.)
+            	return null;
+            }
+        }
+
+        return children;
+    }
+
+    /**
+     *  Return super.source, if the grouping property is set,
+     *  and an ICollectionView instance that refers to super.source if not.
+     *
+     *  @return The object to return.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function getRoot():Object
+    {
+        return super.source;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function refresh(async:Boolean = false):Boolean
+    {
+        this.async = async;
+        var resetEvent:CollectionEvent;
+
+        // return if no grouping or groupingFields are supplied
+        if (!grouping || grouping.fields.length < 1 )
+        {
+            super.source = source;
+            // dispatch collection change event of kind reset.
+            resetEvent =
+                    new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+            resetEvent.kind = CollectionEventKind.RESET;
+            dispatchEvent(resetEvent);
+            return true;
+        }
+
+        super.source = newCollection;
+
+        // dispatch collection change event of kind reset.
+        resetEvent =
+                new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+        resetEvent.kind = CollectionEventKind.RESET;
+        dispatchEvent(resetEvent);
+
+        // reset the parent map
+        parentMap = {};
+
+        // reset the object summary map
+        objectSummaryMap = new Dictionary(false);
+
+        // check if any summary is specified
+        summaryPresent = false;
+        var n:int = grouping.fields.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            if (GroupingField(grouping.fields[i]).summaries)
+            {
+                summaryPresent = true;
+                break;
+            }
+        }
+
+        var grouped:Boolean;
+        if(source && grouping)
+        {
+            grouped = makeGroupedCollection();
+        }
+
+        return grouped;
+    }
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function cancelRefresh():void
+    {
+        if (timer)
+        {
+            timer.stop();
+            timer = null;
+            cleanUp();
+        }
+    }
+
+    /**
+     *  @private
+     *
+     *  check for the existing groups if they can accomodate the item
+     *  otherwise create new group and place the item.
+     */
+    private function addItem(node:Object, depth:int = 0):void
+    {
+        var coll:ICollectionView = super.source as ICollectionView;
+        var parent:Object = null;
+        var i:int = 0;
+        while (i < grouping.fields.length)
+        {
+            // check for the parent item
+            var obj:Object = checkForParentExistence(coll, node, i);
+            // if no parent, then use the previous parent
+            if (!obj)
+                break;
+            // change the parent to point to its parent and start looking for parent again
+            parent = obj;
+
+            if (parent)
+            {
+                coll = getChildren(parent) as ICollectionView;
+                i++;
+            }
+        }
+
+        // parent found
+        if (parent)
+        {
+            coll = getChildren(parent) as ICollectionView;
+
+            // create groups for the item as no existing group matched with the item
+            if (i <= grouping.fields.length-1)
+            {
+                // create groups and place item
+                createGroupsAndInsertItem(coll, node, i);
+                // update the summary for the parents
+                updateSummary(node);
+                return;
+            }
+            // if there already exist a group for the item and insert the item in that group
+            if (coll is IList)
+            {
+                // insert the item
+                IList(coll).addItem(node);
+                // update the parent map
+                updateParentMap(parent, node);
+                // update the summary for the parents
+                updateSummary(node);
+            }
+        }
+        else
+        {
+            // no groups for the item, create groups and add item to them
+            createGroupsAndInsertItem(super.source as ICollectionView, node);
+            // update the summary for the parents
+            updateSummary(node);
+        }
+
+    }
+
+    /**
+     *  @private
+     *
+     *  check for existence of the groups for an item in the collection
+     *  and return all the parent of that item.
+     */
+    private function checkForParentExistence(coll:ICollectionView, node:Object, depth:int):Object
+    {
+        var cursor:IViewCursor = coll.createCursor();
+
+        var label:String = getDataLabel(node, grouping.fields[depth]);
+
+        while (!cursor.afterLast)
+        {
+            var current:Object = cursor.current;
+            // check for matching fields
+            if (current.hasOwnProperty(grouping.label) &&
+                current[grouping.label] == label)
+            {
+                return current;
+            }
+            cursor.moveNext();
+        }
+
+        return null;
+    }
+
+    /**
+     *  @private
+     *
+     *  creating the group for the item in the collection
+     *  and placing it there.
+     */
+    private function createGroupsAndInsertItem(coll:ICollectionView, node:Object, depth:int = 0):void
+    {
+        var parent:Object;
+        var n:int = grouping.fields.length;
+        for (var i:int = depth; i < n ; i++)
+        {
+            // get the dataField and value
+            var dataField:String = grouping.fields[i].name;
+            var value:String = getDataLabel(node, grouping.fields[i]);
+
+            if (!value)
+                return;
+
+            // create a new group
+            var obj:Object;
+            if (grouping.fields[i].groupingObjectFunction != null)
+                obj = grouping.fields[i].groupingObjectFunction(value);
+            else if (grouping.groupingObjectFunction != null)
+                obj = grouping.groupingObjectFunction(value);
+            else
+                obj = {};
+
+            obj[childrenField] = new ArrayCollection();
+
+            obj[grouping.label] = value;
+
+            if (coll is IList)
+            {
+                IList(coll).addItem(obj);
+
+                // get the parent and update parent map
+                parent = parent != null ? parent : getParent(coll.createCursor().current);
+                updateParentMap(parent, obj);
+
+                coll = getChildren(obj) as ICollectionView;
+                parent = obj;
+                // if we reach the end of the fields, just insert the item in the collection
+                if (i == n - 1)
+                {
+                    IList(coll).addItem(node);
+                    // update the parent map
+                    updateParentMap(obj, node);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * @private
+     *
+     * returns the collection view of the given object
+     */
+    private function getCollection(value:Object):ICollectionView
+    {
+        // handle strings and xml
+        if (typeof(value)=="string")
+            value = new XML(value);
+        else if (value is XMLNode)
+            value = new XML(XMLNode(value).toString());
+        else if (value is XMLList)
+            value = new XMLListCollection(value as XMLList);
+
+        if (value is XML)
+        {
+            var xl:XMLList = new XMLList();
+            xl += value;
+            return new XMLListCollection(xl);
+        }
+        //if already a collection dont make new one
+        else if (value is ICollectionView)
+        {
+            return ICollectionView(value);
+        }
+        else if (value is Array)
+        {
+            return new ArrayCollection(value as Array);
+        }
+        //all other types get wrapped in an ArrayCollection
+        else if (value is Object)
+        {
+            // convert to an array containing this one item
+            var tmp:Array = [];
+            tmp.push(value);
+            return new ArrayCollection(tmp);
+        }
+        else
+        {
+            return new ArrayCollection();
+        }
+    }
+
+    /**
+     *  @private
+     *  get the data label from user specified function.
+     *  otherwise get the label from the data.
+     */
+    private function getDataLabel(data:Object,field:GroupingField):String
+    {
+        if (field.groupingFunction != null)
+            return field.groupingFunction(data, field);
+
+        // should we create a defaultGroupLabelValue property
+        return data.hasOwnProperty(field.name) ? data[field.name] : "Not Available";
+    }
+
+    /**
+     *  Returns the parent of a node.
+     *  The parent of a top-level node is null.
+     *
+     *  @param node The Object that defines the node.
+     *
+     *  @return The parent node containing the node as child,
+     *  null for a top-level node,
+     *  and undefined if the parent cannot be determined.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function getParent(node:Object):*
+    {
+        var uid:String = UIDUtil.getUID(node);
+        if (parentMap.hasOwnProperty(uid))
+            return parentMap[uid];
+
+        return undefined;
+    }
+
+    /**
+     *  @private
+     *
+     *  generate the root summaries.
+     *  different for flat data and grouped data.
+     *
+     */
+    private function generateRootSummaries(flatData:Boolean = false):void
+    {
+        var coll:ICollectionView = super.source as ICollectionView;
+
+        if (flatData)
+            coll = coll.createCursor().current as ICollectionView;
+
+        var summaryObj:Array = [];
+        // computing all the summaries
+        var n:int = summaries.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var summaryRow:SummaryRow = summaries[i];
+            if (coll.length > 0)
+            {
+                summaryObj[i] =
+                    summaryRow.summaryObjectFunction != null ? summaryRow.summaryObjectFunction() : new SummaryObject();
+
+                // for all summary fields
+                var m:int = summaryRow.fields.length;
+                for (var j:int = 0; j < m; j++)
+                {
+                    var summaryField:SummaryField = summaryRow.fields[j];
+                    var summary:Number = 0.0;
+                    var label:String = summaryField.label ? summaryField.label : summaryField.dataField;
+
+                    var cursor:IViewCursor = coll.createCursor();
+                    // if data is flat then go through each object and calculate summary.
+                    if (flatData)
+                    {
+                        while (!cursor.afterLast)
+                        {
+                            var current:Object = cursor.current;
+                            var temp:Number = current.hasOwnProperty(label) ? current[label] : 0.0;;
+
+                            if (summaryField.operation == "SUM" || summaryField.operation == "COUNT")
+                                summary += temp;
+                            else if (summaryField.operation == "MAX")
+                                summary = temp;
+                            else if (summaryField.operation == "MIN")
+                                summary = temp;
+
+                            cursor.moveNext();
+                        }
+                    }
+                    else
+                    {
+                        if (!optimizeSummaries)
+                        {
+                            var hd:HierarchicalData = new HierarchicalData(coll);
+                            hd.childrenField = this.childrenField;
+                            var hColl:ICollectionView = new HierarchicalCollectionView(hd, {});
+                            var hCursor:IViewCursor = new LeafNodeCursor(HierarchicalCollectionView(hColl), hColl, hd);
+
+                            if (summaryField.summaryFunction != null)
+                            {
+                                summary = summaryField.summaryFunction(
+                                    hCursor, summaryField.dataField, summaryField.operation);
+                            }
+                            else
+                            {
+                                summary = summaryUtil(
+                                    hCursor, summaryField.dataField, summaryField.operation);
+                            }
+                        }
+                        else
+                        {
+                            summary = getSummaryFromCursor(cursor, summaryField.dataField, summaryField.operation);
+                        }
+                    }
+
+                    summaryObj[i][label] = summary;
+                }
+
+                if (objectSummaryMap[coll] == undefined)
+                    objectSummaryMap[coll] = [];
+
+                objectSummaryMap[coll].push(summaryObj[i]);
+            }
+        }
+        insertRootSummary(summaryObj);
+    }
+
+    /**
+     *  @private
+     *
+     *  calculate the summaries for a given parent,
+     *  populate the objectSummaryMap and
+     *  insert the summary in the collection
+     *
+     */
+    private function getSummaries(parent:Object, depth:int):void
+    {
+        if (depth > grouping.fields.length - 1)
+            return;
+
+        var children:ICollectionView = this.getChildren(parent) as ArrayCollection;
+
+        if (!children || children.length == 0)
+            return;
+
+        var summaries:Array = grouping.fields[depth].summaries;
+        if (!summaries)
+            return;
+
+        var summaryObj:Array = [];
+        // computing all the summaries
+        var n:int = summaries.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var summaryRow:SummaryRow = summaries[i];
+            summaryObj[i] =
+                summaryRow.summaryObjectFunction != null ?
+                summaryRow.summaryObjectFunction() : new SummaryObject();
+
+            // for all summary fields
+            var m:int = summaryRow.fields.length;
+            for (var j:int = 0; j < m; j++)
+            {
+                var summaryField:SummaryField = summaryRow.fields[j];
+                var summary:Number = 0.0;
+                var label:String = summaryField.label ? summaryField.label : summaryField.dataField;
+
+                // calculate the summary at the last level
+                var calculateSummaries:Boolean = true;
+                if (optimizeSummaries)
+                {
+                    if (depth == grouping.fields.length - 1)
+                    {
+                        calculateSummaries = true;
+                    }
+                    // assume that summary is already present and fetch it from the map
+                    else
+                    {
+                        calculateSummaries = false;
+                        summary = getSummaryFromMap(parent, label, summaryField.operation);
+                    }
+                }
+                if (calculateSummaries)
+                {
+                    var hd:HierarchicalData = new HierarchicalData(children);
+                    hd.childrenField = this.childrenField;
+                    var hColl:ICollectionView = new HierarchicalCollectionView(hd, {});
+                    var hCursor:IViewCursor = new LeafNodeCursor(HierarchicalCollectionView(hColl), hColl, hd);
+
+                    if (summaryField.summaryFunction != null)
+                    {
+                        summary = summaryField.summaryFunction(
+                            hCursor, summaryField.dataField, summaryField.operation);
+                    }
+                    else
+                    {
+                        summary = summaryUtil(
+                            hCursor, summaryField.dataField, summaryField.operation);
+                    }
+                }
+
+                // populate the summary object
+                summaryObj[i][label] = summary;
+            }
+
+            // populate the object summary map
+            if (objectSummaryMap[parent] == undefined)
+                objectSummaryMap[parent] = [];
+
+            objectSummaryMap[parent].push(summaryObj[i]);
+        }
+        // insert the summary
+        insertSummary(parent, summaryObj, summaries);
+    }
+
+    /**
+     *  @private
+     *
+     *  computes the summary for the parent node.
+     *  will fetch the summaries from the object summary map
+     *
+     */
+    private function getSummaryFromMap(parent:Object, label:String, operation:String):Number
+    {
+        var cursor:IViewCursor = ArrayCollection(getChildren(parent)).createCursor();
+
+        return getSummaryFromCursor(cursor, label, operation);
+    }
+
+    /**
+     *  @private
+     *
+     *  calculates the summary by traversing over the iterator.
+     *
+     */
+    private function getSummaryFromCursor(cursor:IViewCursor, label:String, operation:String):Number
+    {
+        var result:Number = 0;
+        while (!cursor.afterLast)
+        {
+            var temp:Array = objectSummaryMap[cursor.current];
+            var n:int = temp.length;
+            for (var i:int = 0; i < n; i++)
+            {
+                if (temp[i] && temp[i].hasOwnProperty(label))
+                {
+                    if (operation == "SUM" || operation == "COUNT")
+                        result += temp[i][label];
+                    else if (operation == "MAX")
+                        result = result < temp[i][label] ? temp[i][label] : result;
+                    else if (operation == "MIN")
+                        result = result > temp[i][label] ? temp[i][label] : result;
+                }
+            }
+
+            cursor.moveNext();
+        }
+        return result;
+    }
+
+    /**
+     *  @private
+     *
+     *  initialize the variables
+     *
+     */
+    private function initialize():void
+    {
+        currentData = null;
+        currentGroups = [];
+
+        currentGroupLabels = [];
+        currentIndices = [] ;
+
+        childrenArray = null;
+    }
+
+    /**
+     *  @private
+     *
+     *  insert the root summaries
+     *
+     */
+    private function insertRootSummary(summaryObj:Array):void
+    {
+        var coll:ICollectionView = super.source as ICollectionView;
+
+        if (!grouping)
+            coll = coll.createCursor().current as ICollectionView;
+
+        if (!(coll is IList))
+            return;
+
+        var n:int = summaryObj.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var summaryRow:SummaryRow = summaries[i];
+
+            if (summaryRow.summaryPlacement.indexOf("first") != -1)
+            {
+                IList(coll).addItemAt(summaryObj[i], 0);
+            }
+
+            if (summaryRow.summaryPlacement.indexOf("last") != -1)
+            {
+                IList(coll).addItem(summaryObj[i]);
+            }
+        }
+    }
+
+    /**
+     *  @private
+     *
+     *  inserts the summaries in the children collection of the parent node
+     */
+    private function insertSummary(parent:Object, summaryObj:Array, summaries:Array):void
+    {
+    	var n:int = summaries.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var summaryRow:SummaryRow = summaries[i];
+            if (summaryRow.summaryPlacement.indexOf("group") != -1)
+            {
+                for (var p:String in summaryObj[i])
+                    parent[p] = summaryObj[i][p];
+            }
+
+            var children:IList;
+            if (summaryRow.summaryPlacement.indexOf("first") != -1)
+            {
+                children = (getChildren(parent) as ArrayCollection);
+                if (children)
+                    children.addItemAt(summaryObj[i], 0);
+            }
+
+            if (summaryRow.summaryPlacement.indexOf("last") != -1)
+            {
+                children = (getChildren(parent) as ArrayCollection);
+                if (children)
+                    children.addItem(summaryObj[i]);
+            }
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function makeGroupedCollection():Boolean
+    {
+        // save the sorting information of the source collection
+        // sort the source collection and create a grouped collection
+        // restore the sort of the original source collection
+
+        var fields:Array = [];
+        var n:int = grouping.fields.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var groupingField:GroupingField = grouping.fields[i];
+            var sortField:SortField = new SortField(groupingField.name,
+                        groupingField.caseInsensitive,
+                        groupingField.descending, groupingField.numeric);
+            sortField.compareFunction = groupingField.compareFunction;
+            fields.push(sortField);
+        }
+
+        oldSort = source.sort;
+        source.sort = new Sort();
+
+        // Set the compare function
+        if (grouping.compareFunction != null)
+            source.sort.compareFunction = grouping.compareFunction;
+
+        source.sort.fields = fields;
+
+        var refreshed:Boolean = source.refresh();
+        if (!refreshed)
+            return refreshed;
+
+        if (async)
+        {
+            timer = new Timer(1);
+            timer.addEventListener(TimerEvent.TIMER, timerHandler);
+            timer.start();
+        }
+        else
+        {
+            return buildGroups();
+        }
+
+        return true;
+    }
+
+    /**
+     *  @private
+     */
+    private function timerHandler(event:TimerEvent):void
+    {
+        if (buildGroups())
+        {
+            timer.stop();
+            timer = null;
+        }
+
+    }
+
+    /**
+     *  @private
+     *
+     *  Start building the groups
+     */
+    private function buildGroups():Boolean
+    {
+        if (!prepared)
+        {
+            var _openItems:Object = {};
+
+            // initialize the variables
+            initialize();
+
+            // remove the items from the source collection if there are any.
+            newCollection.removeAll();
+
+            if ((source as ICollectionView).length == 0)
+                return false;
+
+            var hierarchicalData:IHierarchicalData = new HierarchicalData(newCollection);
+            HierarchicalData(hierarchicalData).childrenField = childrenField;
+
+            hView = new HierarchicalCollectionView(
+                                        hierarchicalData, _openItems);
+            treeCursor = hView.createCursor();
+
+            flatView = source as ICollectionView;
+            flatCursor = flatView.createCursor();
+
+            gf = grouping.fields;
+            fieldCount = gf.length;
+
+            if (gf)
+            {
+                prepared = true;
+
+                if (async)
+                    return false;
+            }
+
+            if (async)
+                return true;
+        }
+
+        flatCursor.seek(currentPosition);
+
+        while(!flatCursor.afterLast && currentPosition != CursorBookmark.LAST)
+        {
+            currentData = flatCursor.current;
+
+            for (var i:int = 0; i < fieldCount ; ++i)
+            {
+                var groupingField:String = gf[i].name;
+
+                var label:String = getDataLabel(currentData, gf[i]);
+
+                if(label != currentGroupLabels[i])
+                {
+                    if (childrenArray && childrenArray.length)
+                    {
+                        ArrayCollection(currentGroups[fieldCount - 1][childrenField]).source = childrenArray;
+                        childrenArray = [];
+                    }
+
+                    currentGroupLabels.splice(i+1);
+                    currentGroups.splice(i+1);
+                    currentIndices.splice(i+1);
+
+                    currentGroupLabels[i] = label;
+
+                    // check for grouping Object Function
+                    if (gf[i].groupingObjectFunction != null)
+                        currentGroups[i] = gf[i].groupingObjectFunction(label);
+                    else if (grouping.groupingObjectFunction != null)
+                        currentGroups[i] = grouping.groupingObjectFunction(label);
+                    else
+                        currentGroups[i] = {};
+
+                    currentGroups[i][childrenField] = new ArrayCollection();
+
+                    currentGroups[i][grouping.label] = currentGroupLabels[i];
+
+                    itemIndex = currentIndices[i-1];
+                    // create the group
+                    IHierarchicalCollectionView(hView).addChild(currentGroups[i-1], currentGroups[i]);
+                    currentIndices[i-1] = ++itemIndex;
+                }
+
+                // insert the node as a child of the group
+                if ( i == fieldCount - 1)
+                {
+                    itemIndex = currentIndices[i];
+                    if (!childrenArray)
+                        childrenArray = [];
+                    childrenArray.push(currentData);
+                    currentIndices[i] = ++itemIndex;
+                }
+            }
+
+            try
+            {
+                flatCursor.moveNext();
+                currentPosition = flatCursor.bookmark;
+                // return in case of async refresh
+                if (async)
+                    return false;
+            }
+            catch (e:ItemPendingError)
+            {
+                cleanUp();
+                e.addResponder(new ItemResponder(
+                    function(data:Object, token:Object=null):void
+                    {
+                        makeGroupedCollection();
+                    },
+                    function(info:Object, token:Object=null):void
+                    {
+                        //no-op
+                    }));
+            }
+        }
+        if (currentPosition == CursorBookmark.LAST)
+        {
+            if (childrenArray && childrenArray.length)
+            {
+                ArrayCollection(currentGroups[fieldCount - 1][childrenField]).source = childrenArray;
+            }
+
+            if (summaryPresent)
+            	applyFunctionForParentNodes(super.source as ICollectionView, getSummaries);
+
+            if (source && summaries)
+            {
+                if (!super.source)
+                    super.source = new ArrayCollection([source]) as Object;
+
+                generateRootSummaries(grouping == null);
+            }
+
+            // dispatch collection change event of kind refresh.
+            var refreshEvent:CollectionEvent =
+                    new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+            refreshEvent.kind = CollectionEventKind.REFRESH;
+            dispatchEvent(refreshEvent);
+
+            cleanUp();
+        }
+        return true;
+    }
+
+    /**
+     *  @private
+     *
+     *  Restores the original sort in the source collection
+     *  and clean up all the variables.
+     */
+    private function cleanUp():void
+    {
+        source.sort = oldSort;
+        source.refresh();
+
+        prepared = false;
+        currentPosition = CursorBookmark.FIRST;
+        oldSort = null;
+        flatCursor = null;
+        treeCursor = null;
+    }
+
+    /**
+     *  @private
+     *
+     *  It will call the function func on each node of the collection.
+     */
+    private function applyFunctionForParentNodes(coll:ICollectionView, func:Function, depth:int = 0):void
+    {
+        if (coll.length > 0)
+        {
+            var masterCursor:IViewCursor = coll.createCursor();
+
+            while(!masterCursor.afterLast)
+            {
+                var child:Object = getChildren(masterCursor.current);
+                if (child is ArrayCollection)
+                {
+                    var childCursor:IViewCursor = ArrayCollection(child).createCursor();
+
+                    while (!childCursor.afterLast)
+                    {
+                        var current:Object = childCursor.current;
+                        // recurse over each child
+                        if (this.hasChildren(current))
+                        {
+                            applyFunctionForParentNodes(child as ArrayCollection, func, depth + 1);
+                            break;
+                        }
+
+                        childCursor.moveNext();
+                    }
+                }
+
+                // calculate for the parent node
+                func(masterCursor.current, depth);
+                masterCursor.moveNext();
+            }
+        }
+    }
+
+    /**
+     *  @private
+     *
+     *  removes the root summaries and
+     *  generates them again.
+     *
+     */
+    private function regenerateRootSummaries():void
+    {
+        if(!summaries)
+            return;
+
+        var coll:ICollectionView = super.source as ICollectionView;
+        if (!grouping)
+            coll = coll.createCursor().current as ICollectionView;
+
+        var summaryObj:Array = objectSummaryMap[coll];
+
+        // for the first time there will be no summaries
+        // so, this check will fail and root summaries wont
+        // be removed and regenerated again.
+        // for all the other times, the root summaries will be
+        // regenerated.
+        if (!summaryObj || !(coll is IList))
+            return;
+
+        // delete all the root level summaries
+        var n:int = summaryObj.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var index:int = IList(coll).getItemIndex(summaryObj[i]);
+            if (index != -1)
+                IList(coll).removeItemAt(index);
+        }
+
+        delete objectSummaryMap[coll];
+
+        // generate the root level summaries
+        generateRootSummaries(grouping == null);
+    }
+
+    /**
+     *  @private
+     *
+     *  removes all the summaries from the collection
+     */
+    private function removeAllSummaries():void
+    {
+        // call generate summary with remove summary function as parameter
+        applyFunctionForParentNodes(super.source as ICollectionView, removeSummary);
+    }
+
+    /**
+     *  @private
+     *
+     *  remove the summaries for an item and its parents.
+     *  return the parents of the node going one level up each time.
+     *
+     */
+    private function removeItemAndSummaries(coll:ICollectionView, node:Object, removeItem:Boolean = false):Array
+    {
+        var parentNodes:Array = [];
+        var parent:Object = getParent(node);
+        while (parent != null)
+        {
+            var index:int;
+            var addParent:Boolean = true;
+            var children:ICollectionView = getChildren(parent) as ArrayCollection;
+            if (children)
+            {
+                if (children.contains(node))
+                {
+                    if (children is IList)
+                    {
+                        if (removeItem)
+                        {
+                            // remove the item from the group
+                            index = IList(children).getItemIndex(node);
+                            if (index != -1)
+                            {
+                                IList(children).removeItemAt(index);
+                                // delete item from parent map
+                                var uid:String = UIDUtil.getUID(node);
+                                if (parentMap[uid])
+                                    delete parentMap[uid];
+                            }
+                        }
+
+                        if (objectSummaryMap[parent])
+                        {
+                            var temp:Array = objectSummaryMap[parent];
+                            var n:int = temp.length;
+                            for (var i:int = 0; i < n; i++)
+                            {
+                                index = IList(children).getItemIndex(temp[i]);
+                                if (index != -1)
+                                {
+                                    // remove the summary information for the group
+                                    IList(children).removeItemAt(index);
+                                }
+                            }
+                            // delete summary from parent summary map
+                            delete objectSummaryMap[parent];
+                        }
+
+                        if (removeItem)
+                        {
+                            // remove the group if no children is present
+                            if (children.length == 0 && getParent(parent) != null)
+                            {
+                                addParent = false;
+                            }
+                            else
+                                removeItem = false;
+                        }
+                    }
+                }
+                if (addParent)
+                    parentNodes.push(parent);
+
+                node = parent;
+
+                parent  = getParent(parent);
+                if (!parent)
+                {
+                    // remove the parent node from the collection if its the only one remaining.
+                    // first check for the child collection length
+                    if (parentNodes.length == 1)
+                    {
+                        if ((getChildren(parentNodes[0]) as ICollectionView).length == 0 && coll is IList)
+                        {
+                            index = IList(coll).getItemIndex(node);
+                            if (index != -1)
+                            {
+                                IList(coll).removeItemAt(index);
+                                return null;
+                            }
+                        }
+                    }
+                    return parentNodes.reverse();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     *  @private
+     *
+     *  removes the summaries from the parent node and all its children.
+     *
+     */
+    private function removeSummary(parent:Object, depth:int):void
+    {
+        var children:ICollectionView = this.getChildren(parent) as ArrayCollection;
+
+        if (!children)
+            return;
+
+        // remove summaries from the parents of the current object
+        removeItemAndSummaries(super.source as ICollectionView, children.createCursor().current);
+    }
+
+    /**
+     *  @private
+     *
+     *  Default implementation for operations - "SUM", "MIN", "MAX", "COUNT"
+     */
+    private function summaryUtil(iterator:IViewCursor, dataField:String, operation:String):Number
+    {
+        if (!iterator)
+            return 0.0;
+
+        var result:Number = 0;
+        var temp:Number = 0;
+        var once:Boolean;
+
+        if (operation == "SUM" || operation == "COUNT" || operation == "AVG")
+        {
+            var count:int = 0;
+            while (!iterator.afterLast)
+            {
+                if (iterator.current.hasOwnProperty(dataField))
+                {
+                    count++;
+                    result += Number(iterator.current[dataField]);
+                }
+
+                iterator.moveNext();
+            }
+
+            if (operation == "SUM")
+                return result;
+
+            if (operation == "COUNT")
+                return count;
+
+            if (operation == "AVG")
+                return result / count;
+        }
+        else if (operation == "MIN")
+        {
+            while (!iterator.afterLast)
+            {
+                temp = iterator.current.hasOwnProperty(dataField) ? iterator.current[dataField] : 0.0;
+
+                if (!once)
+                {
+                    result = temp;
+                    once = true;
+                }
+
+                if (temp < result)
+                    result = temp;
+
+                iterator.moveNext();
+            }
+
+            return result;
+        }
+        else if (operation == "MAX")
+        {
+            while (!iterator.afterLast)
+            {
+                temp = iterator.current.hasOwnProperty(dataField) ? iterator.current[dataField] : 0.0;
+
+                if (!once)
+                {
+                    result = temp;
+                    once = true;
+                }
+
+                if (temp > result)
+                    result = temp;
+
+                iterator.moveNext();
+            }
+
+            return result;
+        }
+
+        return 0.0;
+    }
+
+    /**
+     *  @private
+     *
+     *  updates the parent map
+     */
+    private function updateParentMap(parent:Object, node:Object):void
+    {
+        var uid:String = UIDUtil.getUID(node);
+        parentMap[uid] = parent;
+    }
+
+    /**
+     *  @private
+     *
+     *  removes the summary information and regenrates it for a particular node
+     *  and its parents.
+     *  optionally removes the item from the group also.
+     */
+    private function updateSummary(node:Object, removeItem:Boolean = false):void
+    {
+        var coll:ICollectionView = super.source as ICollectionView;
+
+        var parentNodes:Array;
+        if (summaryPresent || removeItem)
+            parentNodes = removeItemAndSummaries(coll, node, removeItem);
+
+        if (summaryPresent && parentNodes)
+        {
+        	var n:int = parentNodes.length;
+            for (var i:int = n - 1; i >= 0; i--)
+            {
+                getSummaries(parentNodes[i], i);
+            }
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Event handlers
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *
+     *  collection change handler.
+     *
+     */
+    private function collectionChangeHandler(event:CollectionEvent):void
+    {
+        if (!grouping)
+            return;
+
+        var i:int = 0;
+        var j:int = 0;
+        var n:int = 0;
+        var m:int = 0;
+        var obj:Object;
+
+        if (event.kind == CollectionEventKind.UPDATE)
+        {
+        	n = event.items.length;
+            for (i = 0; i < n; i++)
+            {
+                var summaryCalculated:Boolean;
+                // take the source property to get the updated object
+                obj = event.items[i].source;
+
+                if (!obj)
+                    continue;
+
+                m = grouping.fields.length;
+                for (j = 0; j < m; j++)
+                {
+                    // check if the property corresponding to the group fields changed
+                    if (event.items[i].property == grouping.fields[j].name)
+                    {
+                        summaryCalculated = true;
+                        // update summaries - first remove the item from its group
+                        updateSummary(obj,true);
+                        // add the item to the group
+                        addItem(obj);
+                        break;
+                    }
+                }
+                // for other properties just update the summaries
+                if (!summaryCalculated)
+                    updateSummary(obj);
+            }
+        }
+
+        if (event.kind == CollectionEventKind.ADD)
+        {
+        	n = event.items.length;
+            for (i = 0; i < n; i++)
+            {
+                obj = event.items[i];
+                // add the item to the group
+                addItem(obj);
+            }
+        }
+
+        if (event.kind == CollectionEventKind.REMOVE)
+        {
+        	n = event.items.length;
+            for (i = 0; i < n; i++)
+            {
+                obj = event.items[i];
+                // update summaries - first remove the item from its group
+                updateSummary(obj,true);
+            }
+        }
+
+        if (event.kind == CollectionEventKind.REPLACE)
+        {
+        	n = event.items.length;
+            for (i = 0; i < n; i++)
+            {
+                var oldValue:Object = event.items[i].oldValue;
+                var newValue:Object = event.items[i].newValue;
+                // update summaries - first remove the item from its group
+                updateSummary(oldValue,true);
+                // add the item to the group
+                addItem(newValue);
+            }
+        }
+
+        // generate the root summaries
+        regenerateRootSummaries();
+    }
+}
+
+}