Transferred from the Adobe Open Source Subversion Repository

Revision: 19887
Author:   jszeto@adobe.com
Date:     2011-01-22T00:21:36.826316Z

Log Message:
-----------
Mobile SoftKeyboard support updates

Changed Scroller.ensureFocusedElementIsVisible property to a function called ensureElementIsVisible
Changed Scroller auto-scroll behavior to only occur when the soft keyboard is opening

SDK-29211 - Focused TextInput doesn't autoscroll in Scroller when softKeyboard opens

Clear the focusedElement in focusOutHandler

SDK-29196 - If the SoftKeyboard is deactivated while the Scroller is currently animating a throw, the Scroller is left in a bad scroll position

Stop the throw animation when the softKeyboard is deactivated

SDK-29172 - Clicking on a nested List causes the outer scroll position to change

Removed the auto-scroll behavior of Scroller in most cases.

QE notes: none
Doc notes: Need to update the ASDoc of the new Scroller.ensureElementIsVisible function
Bugs: SDK-29211, SDK-29196, SDK-29172
Reviewer: Glenn
Tests run: checkintests
Is noteworthy for integration: no

Modified Paths:
--------------
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/mobiletheme/src/spark/skins/mobile/TextAreaSkin.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/Scroller.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/mobiletheme/src/spark/skins/mobile/ListSkin.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/Application.as</path>

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

--- frameworks/projects/spark/src/spark/components/Scroller.as
+++ frameworks/projects/spark/src/spark/components/Scroller.as
@@ -12,6 +12,7 @@

 package spark.components
 {
+import flash.display.DisplayObject;
 import flash.events.Event;
 import flash.events.FocusEvent;
 import flash.events.KeyboardEvent;
@@ -46,6 +47,7 @@
 import spark.components.supportClasses.GroupBase;
 import spark.components.supportClasses.ScrollerLayout;
 import spark.components.supportClasses.SkinnableComponent;
+import spark.core.IGraphicElement;
 import spark.core.IViewport;
 import spark.core.NavigationUnit;
 import spark.effects.Animate;
@@ -394,7 +396,6 @@
  *

  *  <s:Scroller
  *   Properties
- *    ensureFocusedElementIsVisible="true"
  *    measuredSizeIncludesScrollBars="true"
  *    minViewportInset="0"
  *    viewport="null"
@@ -708,49 +709,40 @@
      */
     private var inTouchInteraction:Boolean = false;

-    /**
-     *  @private
-     *  Keeps track of whether the Scroller is listening for softKeyboardEvents
-     */
-    private var softKeyboardEventHandlersAdded:Boolean = false;
-
-    /**
-     *  @private
-     */
-    private var lastFocusedElement:IVisualElement;
-
-    //--------------------------------------------------------------------------
-    //
-    //  Properties
-    //
-    //--------------------------------------------------------------------------
-
-    //----------------------------------
-    //  ensureFocusedElementIsVisible
-    //----------------------------------
-
-    /**
+    //--------------------------------------------------------------------------
+    //
+    //  Variables: SoftKeyboard Support
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *
      *  Some devices do not support a hardware keyboard.
      *  Instead, these devices use a keyboard that opens on
      *  the screen when necessary.
      *  A value of true means that when a component in
      *  the container wrapped by the scroller receives focus,
-     *  the Scroller scrolls that component into view.
-     *
-     *
When the keyboard closes, the parent container might be smaller
-     *  than the available screen space.
-     *  If the container is smaller than the available screen space,
-     *  then the Scroller restores the scroll positions to 0,
-     *  the top of the wrapped container.

-     *
-     *  @default true
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
+     *  the Scroller scrolls that component into view if the keyboard is
+     *  opening
      */
-    public var ensureFocusedElementIsVisible:Boolean = true;
+    mx_internal var ensureElementIsVisibleForSoftKeyboard:Boolean = true;
+
+    /**
+     *  @private
+     */
+    private var lastFocusedElement:IVisualElement;
+
+    /**
+     *  @private
+     */
+    private var isSoftKeyboardActive:Boolean = false;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------

     //----------------------------------
     //  horizontalScrollBar
@@ -964,154 +956,35 @@

     //--------------------------------------------------------------------------
     //
-    // Event Handlers
-    //
-    //--------------------------------------------------------------------------
-
-    /**
-     *  @private
-     *  Helper function for checkScrollPositionsOnUpdateComplete.
-     */
-    private function getMotionPathCurrentVelocity(mp:MotionPath,currentTime:Number,totalTime:Number):Number
-    {
-        // Determine the fraction of the effect that has already played.
-        var fraction:Number = currentTime / totalTime;
-
-        // Now we need to determine the effective velocity at the effect's current position.
-        // Here we use a "poor man's" approximation that doesn't require us to know any of the
-        // derivative functions associated with the motion path.  We sample the position at two
-        // time values very close together and assume the velocity slope is a straight line
-        // between them.  The smaller the distance between the two time values, the closer the
-        // result will be to the "instantaneous" velocity.
-        const TINY_DELTA_TIME:Number = 0.00001;
-        var value1:Number = Number(mp.getValue(fraction));
-        var value2:Number = Number(mp.getValue(fraction + (TINY_DELTA_TIME / totalTime)));
-        return (value2 - value1) / TINY_DELTA_TIME;
-    }
-
-    /**
-     *  @private
-     */
-    private function checkScrollPositionsOnUpdateComplete(event:FlexEvent):void
-    {
-        viewport.removeEventListener(FlexEvent.UPDATE_COMPLETE,
-            checkScrollPositionsOnUpdateComplete);
-
-        var curVelocity:Point;
-
-        // Determine the new maximum valid scroll positions
-        var maxVSP:Number = viewport.contentHeight > viewport.height ?
-            viewport.contentHeight-viewport.height : 0;
-        var maxHSP:Number = viewport.contentWidth > viewport.width ?
-            viewport.contentWidth-viewport.width : 0;
-
-        // Determine whether we possibly need to re-throw because of changed max positions.
-        var didNotThrowFarEnough:Boolean = throwReachedMaximumScrollPosition &&
-            (throwFinalVSP < maxVSP || throwFinalHSP < maxHSP);
-        var threwTooFar:Boolean = (throwFinalVSP > maxVSP || throwFinalHSP > maxHSP);
-
-        if (throwEffect && throwEffect.isPlaying && (didNotThrowFarEnough || threwTooFar))
-        {
-            // There's currently a throw animation playing, and it's throwing to a
-            // now-incorrect position.  We're going to stop the animation and start
-            // a better one to continue the throw.
-
-            var velX:Number = 0;
-            var velY:Number = 0;
-
-            // Get the current position of the existing throw animation
-            var effectTime:Number = throwEffect.playheadTime;
-
-            // It's possible for playheadTime to not be set if we're getting it
-            // before the first animation timer call.
-            if (isNaN(effectTime))
-                effectTime = 0;
-
-            var effectDuration:Number = throwEffect.duration;
-
-            // Now get the current effective velocity for each motionpath in the animation.
-            for (var t:int = 0; t < throwEffect.motionPaths.length; t++)
-            {
-                var vel:Number = getMotionPathCurrentVelocity(throwEffect.motionPaths[t], effectTime, effectDuration);
-
-                // The property can only either be horizontalScrollPosition or verticalScrollPosition
-                if (throwEffect.motionPaths[t].property == "horizontalScrollPosition")
-                    velX = vel;
-                else
-                    velY = vel;
-            }
-
-            // Stop the existing throw animation now that we've determined its current velocities.
-            stoppedPreemptively = true;
-            throwEffect.stop();
-
-            // Now perform a new throw to get us to the right position.
-            performThrow(-velX, -velY);
-        }
-        else if (!inTouchInteraction)
-        {
-            // No touch interaction is in effect, but the content may be sitting at
-            // a scroll position that is now invalid.  Note that performThrow will
-            // only actually perform a throw if the positions actually are invalid.
-            performThrow(0, 0);
-        }
-    }
-
-    /**
-     *  @private
-     */
-    private function viewport_propertyChangeHandler(event:PropertyChangeEvent):void
-    {
-        switch(event.property)
-        {
-            case "contentWidth":
-            case "contentHeight":
-                invalidateSkin();
-                if (getStyle("interactionMode") == InteractionMode.TOUCH)
-                {
-                    // If the content size changed, then the valid scroll position ranges
-                    // may have changed.  In this case, we need to schedule an updateComplete
-                    // handler to check and potentially correct the scroll positions.
-                    viewport.addEventListener(FlexEvent.UPDATE_COMPLETE,
-                        checkScrollPositionsOnUpdateComplete);
-                }
-                break;
-        }
-    }
-
-    /**
-     *  @private
-     *  Listens for any focusIn events from descendants
+    // Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Scrolls the viewport so the element is visible in the viewable area
+     *  Adjusts for focusThickness.
+     *
+     *  @param element A descendant element of the Scroller
      */
-    override protected function focusInHandler(event:FocusEvent):void
-    {
-        super.focusInHandler(event);
-
-        // When we gain focus, make sure the focused element is visible
-        if (viewport && ensureFocusedElementIsVisible)
-        {
-            var elt:IVisualElement = focusManager.getFocus() as IVisualElement;
-            lastFocusedElement = elt;
-
-            if (elt)
-                scrollElementIntoView(elt);
-        }
-
-    }
-
-    /**
-     *  @private
-     *  Scrolls the viewport so the element is visible in the viewable area
-     */
-    private function scrollElementIntoView(element:IVisualElement):void
+    public function ensureElementIsVisible(element:IVisualElement):void
     {
+        // First check that the element is a descendant
+        // If we are a GraphicElement, use the element's parent
+        var possibleDescendant:DisplayObject = element as DisplayObject;
+
+        if (element is IGraphicElement)
+            possibleDescendant = IGraphicElement(element).parent as DisplayObject;
+
+        if (!possibleDescendant || !contains(possibleDescendant))
+            return;
+
         var layout:LayoutBase = null;

         if (viewport is GroupBase)
             layout = GroupBase(viewport).layout;
         else if (viewport is SkinnableContainer)
             layout = SkinnableContainer(viewport).layout;
-
+
         if (layout)
         {
             // Scroll the element into view
@@ -1141,11 +1014,153 @@
                     else if (viewport.horizontalScrollPosition + width < eltBounds.right + focusThickness)
                         viewport.horizontalScrollPosition = eltBounds.right + focusThickness - width;
                 }
-
+
                 if (viewport is UIComponent)
                     UIComponent(viewport).validateNow();
             }
         }
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Event Handlers
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *  Helper function for checkScrollPositionsOnUpdateComplete.
+     */
+    private function getMotionPathCurrentVelocity(mp:MotionPath,currentTime:Number,totalTime:Number):Number
+    {
+        // Determine the fraction of the effect that has already played.
+        var fraction:Number = currentTime / totalTime;
+
+        // Now we need to determine the effective velocity at the effect's current position.
+        // Here we use a "poor man's" approximation that doesn't require us to know any of the
+        // derivative functions associated with the motion path.  We sample the position at two
+        // time values very close together and assume the velocity slope is a straight line
+        // between them.  The smaller the distance between the two time values, the closer the
+        // result will be to the "instantaneous" velocity.
+        const TINY_DELTA_TIME:Number = 0.00001;
+        var value1:Number = Number(mp.getValue(fraction));
+        var value2:Number = Number(mp.getValue(fraction + (TINY_DELTA_TIME / totalTime)));
+        return (value2 - value1) / TINY_DELTA_TIME;
+    }
+
+    /**
+     *  @private
+     */
+    private function checkScrollPositionsOnUpdateComplete(event:FlexEvent):void
+    {
+        viewport.removeEventListener(FlexEvent.UPDATE_COMPLETE,
+            checkScrollPositionsOnUpdateComplete);
+
+        var curVelocity:Point;
+
+        // Determine the new maximum valid scroll positions
+        var maxVSP:Number = viewport.contentHeight > viewport.height ?
+            viewport.contentHeight-viewport.height : 0;
+        var maxHSP:Number = viewport.contentWidth > viewport.width ?
+            viewport.contentWidth-viewport.width : 0;
+
+        // Determine whether we possibly need to re-throw because of changed max positions.
+        var didNotThrowFarEnough:Boolean = throwReachedMaximumScrollPosition &&
+            (throwFinalVSP < maxVSP || throwFinalHSP < maxHSP);
+        var threwTooFar:Boolean = (throwFinalVSP > maxVSP || throwFinalHSP > maxHSP);
+
+        if (throwEffect && throwEffect.isPlaying && (didNotThrowFarEnough || threwTooFar))
+        {
+            // There's currently a throw animation playing, and it's throwing to a
+            // now-incorrect position.  We're going to stop the animation and start
+            // a better one to continue the throw.
+
+            var velX:Number = 0;
+            var velY:Number = 0;
+
+            // Get the current position of the existing throw animation
+            var effectTime:Number = throwEffect.playheadTime;
+
+            // It's possible for playheadTime to not be set if we're getting it
+            // before the first animation timer call.
+            if (isNaN(effectTime))
+                effectTime = 0;
+
+            var effectDuration:Number = throwEffect.duration;
+
+            // Now get the current effective velocity for each motionpath in the animation.
+            for (var t:int = 0; t < throwEffect.motionPaths.length; t++)
+            {
+                var vel:Number = getMotionPathCurrentVelocity(throwEffect.motionPaths[t], effectTime, effectDuration);
+
+                // The property can only either be horizontalScrollPosition or verticalScrollPosition
+                if (throwEffect.motionPaths[t].property == "horizontalScrollPosition")
+                    velX = vel;
+                else
+                    velY = vel;
+            }
+
+            // Stop the existing throw animation now that we've determined its current velocities.
+            stoppedPreemptively = true;
+            throwEffect.stop();
+
+            // Now perform a new throw to get us to the right position.
+            performThrow(-velX, -velY);
+        }
+        else if (!inTouchInteraction)
+        {
+            // No touch interaction is in effect, but the content may be sitting at
+            // a scroll position that is now invalid.  Note that performThrow will
+            // only actually perform a throw if the positions actually are invalid.
+            performThrow(0, 0);
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function viewport_propertyChangeHandler(event:PropertyChangeEvent):void
+    {
+        switch(event.property)
+        {
+            case "contentWidth":
+            case "contentHeight":
+                invalidateSkin();
+                if (getStyle("interactionMode") == InteractionMode.TOUCH)
+                {
+                    // If the content size changed, then the valid scroll position ranges
+                    // may have changed.  In this case, we need to schedule an updateComplete
+                    // handler to check and potentially correct the scroll positions.
+                    viewport.addEventListener(FlexEvent.UPDATE_COMPLETE,
+                        checkScrollPositionsOnUpdateComplete);
+                }
+                break;
+        }
+    }
+
+    /**
+     *  @private
+     *  Listens for any focusIn events from descendants
+     */
+    override protected function focusInHandler(event:FocusEvent):void
+    {
+        super.focusInHandler(event);
+
+        // When we gain focus, make sure the focused element is visible
+        if (viewport && ensureElementIsVisibleForSoftKeyboard)
+        {
+            var elt:IVisualElement = focusManager.getFocus() as IVisualElement;
+            lastFocusedElement = elt;
+        }
+    }
+
+    /**
+     *  @private
+     */
+    override protected function focusOutHandler(event:FocusEvent):void
+    {
+        super.focusOutHandler(event);
+        lastFocusedElement = null;
     }

     /**
@@ -1745,6 +1760,26 @@
     //  Overridden methods
     //
     //--------------------------------------------------------------------------
+
+    override protected function createChildren():void
+    {
+        super.createChildren();
+
+        var topLevelApp:Application = FlexGlobals.topLevelApplication as Application;
+
+        // Only listen for softKeyboardEvents if the
+        // softKeyboardBehavior attribute in the application descriptor equals "none"
+        // Check that the top level app has resizeForSoftKeyboard == true
+        if (topLevelApp && topLevelApp.resizeForSoftKeyboard && Application.softKeyboardBehavior == "none")
+        {
+            addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE,
+                softKeyboardActivateHandler, false,
+                EventPriority.DEFAULT, true);
+            addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE,
+                softKeyboardDeactivateHandler, false,
+                EventPriority.DEFAULT, true);
+        }
+    }

     /**
      *  @private
@@ -2436,23 +2471,6 @@
      */
     private function addedToStageHandler(event:Event):void
     {
-        var topLevelApp:Application = FlexGlobals.topLevelApplication as Application;
-
-        // Only listen for softKeyboardEvents if the
-        // softKeyboardBehavior attribute in the application descriptor equals "none"
-        // Check that the top level app has resizeForSoftKeyboard == true
-        if (topLevelApp && topLevelApp.resizeForSoftKeyboard && Application.softKeyboardBehavior == "none")
-        {
-            systemManager.stage.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE,
-                softKeyboardActivateHandler, false,
-                EventPriority.DEFAULT, true);
-            systemManager.stage.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE,
-                softKeyboardDeactivateHandler, false,
-                EventPriority.DEFAULT, true);
-
-            softKeyboardEventHandlersAdded = true;
-        }
-
         if (getStyle("interactionMode") == InteractionMode.TOUCH)
             systemManager.stage.addEventListener("orientationChange",orientationChangeHandler);
     }
@@ -2462,16 +2480,6 @@
      */
     private function removedFromStageHandler(event:Event):void
     {
-        if (softKeyboardEventHandlersAdded)
-        {
-            systemManager.stage.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE,
-                softKeyboardActivateHandler, false);
-            systemManager.stage.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE,
-                softKeyboardDeactivateHandler, false);
-
-            softKeyboardEventHandlersAdded = false;
-        }
-
         if (getStyle("interactionMode") == InteractionMode.TOUCH)
             systemManager.stage.removeEventListener("orientationChange",orientationChangeHandler);
     }
@@ -2484,8 +2492,15 @@
     private function softKeyboardActivateHandler(event:SoftKeyboardEvent):void
     {
         // Size of app has changed, so run this logic again
-        if (lastFocusedElement)
-            scrollElementIntoView(lastFocusedElement);
+        var keyboardRect:Rectangle = stage.softKeyboardRect;
+
+        if (keyboardRect.width > 0 && keyboardRect.height > 0)
+        {
+            if (lastFocusedElement && !isSoftKeyboardActive && ensureElementIsVisibleForSoftKeyboard)
+                ensureElementIsVisible(lastFocusedElement);
+
+            isSoftKeyboardActive = true;
+        }
     }

     /**
@@ -2494,31 +2509,24 @@
      *  application to resize itself and fix the scroll position if necessary
      */
     private function softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
-    {
+    {
         // Adjust the scroll position after the application's size is restored.
         adjustScrollPositionAfterSoftKeyboardDeactivate();
+        isSoftKeyboardActive = false;
     }

     /**
      *  @private
      */
     mx_internal function adjustScrollPositionAfterSoftKeyboardDeactivate():void
-    {
-        // If contentHeight is shorter than height, we no longer can scroll and we should reset to 0
-        // If contentHeight is taller than height, make sure the position doesn't
-        // exceed the max scroll position
-
-        if (viewport.contentHeight <= height)
-            viewport.verticalScrollPosition = 0;
+    {
+        // If the throw animation is still playing, stop it. Otherwise, fix the
+        // scroll position.
+        if (throwEffect && throwEffect.isPlaying)
+            stopThrowEffectOnMouseDown();
         else
-            viewport.verticalScrollPosition = Math.min(viewport.verticalScrollPosition, viewport.contentHeight - height);
-
-        if (viewport.contentWidth <= width)
-            viewport.horizontalScrollPosition = 0;
-        else
-            viewport.horizontalScrollPosition = Math.min(viewport.horizontalScrollPosition, viewport.contentWidth - width);
-    }
-
+            snapContentScrollPosition();
+    }

 }


Transferred from the Adobe Open Source Subversion Repository

Revision: 16575
Author:   clucier@adobe.com
Date:     2010-06-16T14:10:14.394565Z

Log Message:
-----------
Bug fix for image cache. We now use a more robust scheme for detecting when a request is 'complete'.

QE notes: None
Doc notes: None
Bugs: SDK-26709
Reviewer: Darrell
Tests run: Checkin
Is noteworthy for integration: No

Modified Paths:
--------------
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/core/ContentRequest.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/core/ContentCache.as</path>

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

--- frameworks/projects/spark/src/spark/core/ContentRequest.as
+++ frameworks/projects/spark/src/spark/core/ContentRequest.as
@@ -126,20 +126,28 @@
      *  @playerversion AIR 1.5
      *  @productversion Flex 4.5
      */
-    public function ContentRequest(contentLoader:IContentLoader,content:*,shared:Boolean=false)
+    public function ContentRequest(contentLoader:IContentLoader, content:*,
+                                   shared:Boolean=false, complete:Boolean=false)
     {
         super();
         this.content = content;
         _shared = shared;
+        _complete = complete;
         contentLoader.addEventListener("invalidateLoader", contentLoader_invalidateLoaderHandler, false, 0, true);
     }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+    private var _shared:Boolean;

     //--------------------------------------------------------------------------
     //
     //  Properties
     //
     //--------------------------------------------------------------------------
-    private var _shared:Boolean;

     //----------------------------------
     //  content
@@ -180,6 +188,8 @@
     //  complete
     //----------------------------------

+    private var _complete:Boolean;
+
     /**
      *  Read-only flag. Returns true if content is
      *  considered fully loaded and accessible.
@@ -189,12 +199,9 @@
     public function get complete():Boolean
     {
         if (_content && _content is LoaderInfo)
-        {
-            return (_content.bytesTotal > 0 &&
-                    _content.bytesTotal == _content.bytesLoaded);
-        }
-
-        return (_content != null);
+            return _complete;
+        else
+            return (_content != null);
     }

     //--------------------------------------------------------------------------
@@ -246,6 +253,7 @@
     {
         if (e.target == _content)
         {
+            _complete = true;
             dispatchEvent(e);
             removeLoaderListeners();
         }


Transferred from the Adobe Open Source Subversion Repository

Revision: 5098
Author:   gauravj@adobe.com
Date:     2009-02-27T02:21:27.489350Z

Log Message:
-----------
Update action script files with asdoc version tags.

QE Notes: None.
Doc Notes: Please review and update as necessary.
tests: checkintests

Modified Paths:
--------------
151 paths were modified

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

--- frameworks/projects/spark/src/spark/effects/easing/Sine.as
+++ frameworks/projects/spark/src/spark/effects/easing/Sine.as
@@ -14,12 +14,22 @@
  * Provides easing functionality using a Sine function and a
  * parameter that specifies how much time to spend easing in
  * and out.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
  */
 public class Sine extends EaseInOut
 {
     /**
      * Constructs a Sine instance with an optional
      * easeInFraction parameter.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
      */
     public function Sine(easeInFraction:Number = .5)
     {
@@ -31,6 +41,11 @@
      *
      * The easeIn calculation for Sine is equal to
      * 1 - cos(fraction*PI/2).
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
      */
     override protected function easeIn(fraction:Number):Number
     {
@@ -42,6 +57,11 @@
      *
      * The easeOut calculation for Sine is equal to
      * sin(fraction*PI/2).
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
      */
     override protected function easeOut(fraction:Number):Number
     {


DisplayInjector can now be directed to use a specific ApplicationDomain.

inject now takes an optional argument that specifies the ApplicationDomain
to use when instantiating adapter classes. This is necessary when a child
AppDomain uses a parent's definition of DisplayInjector with classes that
only exist in the child.

--- raw/src/org/yellcorp/lib/display/inject/DisplayInjector.as
+++ raw/src/org/yellcorp/lib/display/inject/DisplayInjector.as
@@ -2,8 +2,8 @@
 {
 import flash.display.DisplayObject;
 import flash.display.DisplayObjectContainer;
+import flash.system.ApplicationDomain;
 import flash.utils.describeType;
-import flash.utils.getDefinitionByName;

 /**
@@ -114,6 +114,9 @@
      * @param container  The DisplayObjectContainer containing named
      *                   children to assign to target.
      * @param target  The instance to populate.
+     * @param domain  The ApplicationDomain to use when resolving adapter
+     *                classes. Defaults to the domain where this class is first
+     *                defined.
      *
      * @throws org.yellcorp.lib.display.inject.DisplayPathError
      *         If a child with the default or overridden name could not be
@@ -125,8 +128,13 @@
      * @throws org.yellcorp.lib.display.inject.DisplayMetadataError
      *         If a metadata parameter is invalid.
      */
-    public static function inject(container:DisplayObjectContainer, target:*):void
-    {
+    public static function inject(container:DisplayObjectContainer, target:*, domain:ApplicationDomain = null):void
+    {
+        if (!domain)
+        {
+            domain = ApplicationDomain.currentDomain;
+        }
+
         var type:XML = describeType(target);

         var displayMetadata:XMLList = type.*.(
@@ -135,13 +143,13 @@

         for each (var metadata:XML in displayMetadata)
         {
-            injectProperty(metadata.parent(), metadata, container, target);
+            injectProperty(metadata.parent(), metadata, container, target, domain);
         }
     }

     private static function injectProperty(property:XML, metadata:XML,
-            source:DisplayObjectContainer, target:*):void
+            source:DisplayObjectContainer, target:*, domain:ApplicationDomain):void
     {
         var args:Object = { name: null, adapter: null, optional: null };

@@ -157,7 +165,7 @@

             if (args.adapter !== null)
             {
-                child = construct(args.adapter, child);
+                child = construct(args.adapter, child, domain);
             }

             target[property.@name] = child;
@@ -263,9 +271,9 @@
     }

-    private static function construct(adapter:String, displayObject:*):*
-    {
-        var clazz:Object = getDefinitionByName(adapter);
+    private static function construct(adapter:String, displayObject:*, domain:ApplicationDomain):*
+    {
+        var clazz:Object = domain.getDefinition(adapter);
         return new clazz(displayObject);
     }
 }


Alter the drawing in the Ring class to use two fills rather than a line

--- src/org/flintparticles/common/displayObjects/Ring.as
+++ src/org/flintparticles/common/displayObjects/Ring.as
@@ -44,12 +44,12 @@

         /**
          * The constructor creates a Ring with the specified inner and outer radius.
+         * @param inner Inner radius of the ring
          * @param outer Outer radius of the ring
-         * @param inner Inner radius of the ring
          * @param color Color of the ring
          * @param bm    Blend mode of the ring
          */
-        public function Ring( outer:Number = 0.9, inner:Number = 1.1, color:uint = 0xFFFFFF, bm:String = "normal" )
+        public function Ring( inner:Number = 1, outer:Number = 2, color:uint = 0xFFFFFF, bm:String = "normal" )
         {
             _outerRadius = outer;
             _innerRadius = inner;
@@ -61,8 +61,10 @@
         private function draw():void
         {
             graphics.clear();
-            graphics.lineStyle( _outerRadius - _innerRadius, _color );
-            graphics.drawCircle( 0, 0, (_outerRadius + _innerRadius)/2 );
+            graphics.beginFill( _color );
+            graphics.drawCircle( 0, 0, _outerRadius );
+            graphics.drawCircle( 0, 0, _innerRadius );
+            graphics.endFill();
         }

         public function get outerRadius():Number


Ajout de la partie de lecture du Sudoku, debut de la partie de l'affichage et de la solution

--- tp3.as
+++ tp3.as
@@ -4,7 +4,7 @@
 */

-.global Main 		!Point d'entrée, début du programme
+.global Main 		!Point d\'entrée, début du programme
 .global Afficher	!Fonction qui affiche un entier.

 .section ".text"
@@ -13,3 +13,68 @@
 /* Début du programme */

 Main:
+  set   vecteur, %l0
+  mov   0, %l1 ! Initialiser l1 à 0 pour s\'en servir dans Sudoku00
+
+  ba  Sudoku00
+  nop
+
+/* Lecture des 81 chiffres formant le Sudoku */
+Sudoku00:
+
+  ! Afficher la demande du chifre
+  set   demandechif, %o0
+  mov   %l1, %o1
+  call  printf
+  nop
+
+  ! Recevoir le chiffre
+  set   lecture, %o0
+  call  scanf
+  nop
+
+  ! Concerver le chiffre
+  mul   %l1, 4, %l2     ! Emplacement où converver le chiffre
+  st    %l1, [%l0+%l2]  ! Placer le chiffre dans le vecteur
+
+  ! Véfifier si nous avons tout nos chiffres ou on doit continuer
+  inc   %l1
+  bl    %l1, 81
+  Sudoku00           ! Continuer a recevoir des chiffres
+  nop
+
+  ba ValiderLignes   ! Valider le contenu du Sudoku
+  nop
+
+
+/* Afficher le Sudoku */
+AfficherSudoku:
+  mov   %l1, 0    ! %l1 va servir pour savoir on est rendu sur quelle ligne (0-8)
+  mov   %l2, 0    ! %l2 va servir pour savoir on est rendu sur quelle colonne (0-8)
+
+
+/* Valider le sudoku sur les 9 lignes */
+ValiderLignes:
+  mov   %l1, 0    ! %l1 va servir pour savoir on est rendu sur quelle ligne
+
+
+ValiderColonnes:
+  mov   %l1, 0    ! %l1 va servir pour savoir on est rendu sur quelle colonne
+
+ValiderDiagonnales:
+
+
+/* Variables */
+
+.section ".rodata"
+  demandechif:  .asciz  "Veuillez entrer le chiffre allant dans la case %d : "
+	lignepleine:  .asciz 	"|---------|---------|---------|\n"
+  lignenombre:  .asciz  "| %d  %d  %d | %d  %d  %d | %d  %d  %d |"
+
+
+/* Espace mémoire */
+
+.section ".bss"
+  .align 	4	          ! Mots
+  vecteur: 	.skip	324	! 81 espaces mémoire pour le vecteur du Sudoku
+  lecture:	.skip	 4  ! Espace pour la lecture du chiffre en entrée


Trying to use inverse kinematic armature for probes. Not complete yet.

git-svn-id: 9ce4c3524d875f8080d1dced2eac547b3d68c750@20398 6e01202a-0783-4428-890a-84243c50cc2b

--- demos/resistor-colors/actionscript/org/concord/sparks/circuit/Multimeter.as
+++ demos/resistor-colors/actionscript/org/concord/sparks/circuit/Multimeter.as
@@ -1,5 +1,7 @@
 package org.concord.sparks.circuit {

+    import fl.ik.IKArmature;
+    import fl.ik.IKBone;
     import fl.ik.IKManager;

     import flash.display.MovieClip;
@@ -40,8 +42,10 @@

             var redCord = IKManager.getArmatureByName('Armature_9');

-            redLead = new Lead('red_lead', root['probeRed_mc'], 0, 0, 18, 143, redCord);
-            blackLead = new Lead('black_lead', root['probeBlack_mc'], 0, 0, 28, 147, redCord);
+            //redLead = new Lead('red_lead', root['probeRed_mc'], 0, 0, 18, 143, redCord);
+            //blackLead = new Lead('black_lead', root['probeBlack_mc'], 0, 0, 28, 147, redCord);
+            redLead = new Lead('red_lead', getBone('Armature_18', 'ikBoneName552'), 0, 0, 18, 143, redCord);
+            blackLead = new Lead('black_lead', root['probeBlack_mc'], getBone('Armature_16', 'ikBoneName169'), 0, 0, 28, 147, redCord);
         }

         public function setDisplayText(s:String) {
@@ -148,4 +152,9 @@
             }
         }
     }
+
+    private function getBone(armatureName:String, boneName:String):IKBone {
+        var armature:IKArmature = IKManager.getArmatureByName(armatureName);
+        return armature.getBoneByName(boneName);
+    }
 }


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@1248412 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/advancedgrids/src/mx/collections/GroupingCollection2.as
+++ frameworks/projects/advancedgrids/src/mx/collections/GroupingCollection2.as
@@ -0,0 +1,1782 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 GroupingCollection2 class lets you create grouped data from flat data
+ *  for display in the AdvancedDataGrid control.
+ *  When you create the instance of the GroupingCollection2 from your flat data,
+ *  you specify the field or fields of the data used to create the hierarchy.
+ *
+ *
Note: In the previous release of Flex, you used the GroupingCollection class
+ *  with the AdvancedDataGrid control.
+ *  The GroupingCollection2 class is new for Flex 4 and provides better performance
+ *  than GroupingCollection.

+ *
+ *
To populate the AdvancedDataGrid control with grouped data,
+ *  you create an instance of the GroupingCollection2 class from your flat data,
+ *  and then pass that GroupingCollection2 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 GroupingCollection2.grouping property.
+ *  The Grouping instance contains an Array of GroupingField instances,
+ *  one per grouping field.

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

+ *
+ *

+ *  <mx:AdvancedDataGrid id="myADG"
+ *    <mx:dataProvider>
+ *      <mx:GroupingCollection2 id="gc" source="{dpFlat}">
+ *        <mx:grouping>
+ *          <mx:Grouping>
+ *            <mx:GroupingField name="Region"/>
+ *            <mx:GroupingField name="Territory"/>
+ *          </mx:Grouping>
+ *        </mx:grouping>
+ *      </mx:GroupingCollection2>
+ *    </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.GroupingCollection2> inherits all the tag attributes of its superclass,
+ *  and defines the following tag attributes:

+ *
+ *

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

+ *
+ *  @see mx.controls.AdvancedDataGrid
+ *  @see mx.collections.Grouping
+ *  @see mx.collections.GroupingField
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+public class GroupingCollection2 extends HierarchicalData implements IGroupingCollection2
+{
+    include "../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 3
+     */
+    public function GroupingCollection2()
+    {
+        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
+     *
+     *  if true, dispatch collection change events
+     */
+    private var dispatchCollectionEvents: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 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;
+
+    /**
+     *  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 10
+     *  @playerversion AIR 1.5
+     *  @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;
+
+    /**
+     *  @private
+     *  A Dictionary to maintain summaries
+     */
+    private var summariesTracker:Dictionary;
+
+    /**
+     *  @private
+     *  An array to store all the summary fields.
+     */
+    private var summaryFields:Array;
+
+    //--------------------------------------------------------------------------
+    //
+    //  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.GroupingCollection2#refresh()
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @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:GroupingCollection2 id="gc" source="{dpFlat}">
+     *             <mx:summaries>
+     *                 <mx:SummaryRow summaryPlacement="last">
+     *                     <mx:fields>
+     *                         <mx:SummaryField2 dataField="Actual"
+     *                             label="Min Actual" summaryOperation="MIN"/>
+     *                         <mx:SummaryField2 dataField="Actual"
+     *                             label="Max Actual" summaryOperation="MAX"/>
+     *                     </mx:fields>
+     *                   </mx:SummaryRow>
+     *                 </mx:summaries>
+     *             <mx:Grouping>
+     *                 <mx:GroupingField name="Region"/>
+     *                 <mx:GroupingField name="Territory"/>
+     *             </mx:Grouping>
+     *         </mx:GroupingCollection2>
+     *     </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.SummaryField2
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @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 10
+     *  @playerversion AIR 1.5
+     *  @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 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 3
+     */
+    override public function getRoot():Object
+    {
+        return super.source;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 3
+     */
+    public function refresh(async:Boolean = false, dispatchCollectionEvents:Boolean = false):Boolean
+    {
+        this.async = async;
+        this.dispatchCollectionEvents = async ? true : dispatchCollectionEvents;
+
+        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);
+
+        // reset the summaryTracker
+        summariesTracker = null;
+
+        // check if any summary is specified
+        summaryPresent = false;
+        prepareSummaryFields();
+
+        var grouped:Boolean;
+        if(source && grouping)
+        {
+            grouped = makeGroupedCollection();
+        }
+
+        return grouped;
+    }
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @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 10
+     *  @playerversion AIR 1.5
+     *  @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 level summaries
+     */
+    private function generateRootSummaries(flatData:Boolean = false):void
+    {
+        var coll:ICollectionView = super.source as ICollectionView;
+
+        getSummaries(coll, -1);
+    }
+
+    /**
+     *  @private
+     *  Calculate summaries for a node.
+     */
+    private function getSummariesForRow(node:Object, collection:ICollectionView, depth:int):void
+    {
+        // calculate the summary at the last level
+        var hd:HierarchicalData = new HierarchicalData(collection);
+        hd.childrenField = this.childrenField;
+        var hColl:ICollectionView = new HierarchicalCollectionView(hd, {});
+        var hCursor:IViewCursor = new LeafNodeCursor(HierarchicalCollectionView(hColl), hColl, hd);
+
+        // for all summary fields
+        var m:int = summaryFields.length;
+        var i:int = 0;
+
+        var defaultSummaryCalculator:DefaultSummaryCalculator = new DefaultSummaryCalculator();
+        var summaryMap:Dictionary = new Dictionary(false);
+        var summaryField:SummaryField2;
+        var summaryCalculator:ISummaryCalculator;
+
+        for (i = 0; i < m; i++)
+        {
+            summaryField = summaryFields[i];
+
+            if (!(summaryField.summaryOperation is String) &&
+                summaryField.summaryOperation is ISummaryCalculator)
+                summaryCalculator = ISummaryCalculator(summaryField.summaryOperation);
+            else
+                summaryCalculator = defaultSummaryCalculator;
+
+            summaryMap[summaryField] = summaryCalculator.summaryCalculationBegin(summaryField);
+        }
+
+        while (!hCursor.afterLast)
+        {
+            for (i = 0; i < m; i++)
+            {
+                summaryField = summaryFields[i];
+
+                if (!(summaryField.summaryOperation is String) &&
+                    summaryField.summaryOperation is ISummaryCalculator)
+                    summaryCalculator = ISummaryCalculator(summaryField.summaryOperation);
+                else
+                    summaryCalculator = defaultSummaryCalculator;
+
+                summaryCalculator.calculateSummary(summaryMap[summaryField], summaryField, hCursor.current);
+            }
+
+            hCursor.moveNext();
+        }
+
+        for (i = 0; i < m; i++)
+        {
+            var summary:Number = 0.0;
+            summaryField = summaryFields[i];
+
+            if (!(summaryField.summaryOperation is String) &&
+                summaryField.summaryOperation is ISummaryCalculator)
+                summaryCalculator = ISummaryCalculator(summaryField.summaryOperation);
+            else
+                summaryCalculator = defaultSummaryCalculator;
+
+            summary = summaryCalculator.returnSummary(summaryMap[summaryField], summaryField);
+
+            populateSummary(node, summaryField, summaryMap[summaryField], summary);
+        }
+    }
+
+    /**
+     *  @private
+     *  Store the summary in a dictionary for later use.
+     */
+    private function populateSummary(node:Object, summaryField:SummaryField2, summaryObject:Object, summary:Number):void
+    {
+        var op:String = summaryField.summaryOperation.toString();
+
+        if (summariesTracker == null)
+            summariesTracker = new Dictionary(false);
+
+        if (summariesTracker[node] == undefined)
+            summariesTracker[node] = new Dictionary(false);
+        if (summariesTracker[node][op] == undefined)
+            summariesTracker[node][op] = new Dictionary(false);
+        if (summariesTracker[node][op][summaryField.dataField] == undefined)
+            summariesTracker[node][op][summaryField.dataField] = new Dictionary(false);
+
+        summariesTracker[node][op][summaryField.dataField] = {summaryObject:summaryObject, value:summary};
+    }
+
+    /**
+     *  @private
+     *  Get the summary from the dictionary
+     */
+    private function getSummary(node:Object, summaryField:SummaryField2):Object
+    {
+        var op:String = summaryField.summaryOperation.toString();
+
+        if (summariesTracker == null ||
+            summariesTracker[node] == undefined ||
+            summariesTracker[node][op] == undefined ||
+            summariesTracker[node][op][summaryField.dataField] == undefined)
+        return null;
+
+        return summariesTracker[node][op][summaryField.dataField];
+    }
+
+    /**
+     *  @private
+     *  Calcualte and insert summary for a node
+     */
+    private function getSummaries(node:Object, depth:int):void
+    {
+        if (depth > grouping.fields.length - 1)
+            return;
+
+        var children:ICollectionView = this.getChildren(node) as ArrayCollection;
+
+        if (node == super.source)
+            children = node as ICollectionView;
+
+        if (!children || children.length == 0)
+            return;
+
+        if (depth == grouping.fields.length - 1)
+        {
+            // calculate actual summaries here
+            getSummariesForRow(node, children, depth);
+        }
+        else
+        {
+            var cursor:IViewCursor = children.createCursor();
+            var isFirst:Boolean = true;
+
+            var defaultSummaryCalculator:DefaultSummaryCalculator = new DefaultSummaryCalculator();
+            var summaryField:SummaryField2;
+            var summaryMap:Dictionary = new Dictionary(false);
+            var summaryCalculator:ISummaryCalculator;
+
+            while (!cursor.afterLast)
+            {
+                var current:Object = cursor.current;
+                if (!(current is SummaryObject))
+                {
+                    // for all summary fields
+                    var m:int = summaryFields.length;
+                    var i:int = 0;
+
+                    for (i = 0; i < m; i++)
+                    {
+                        summaryField = summaryFields[i];
+
+                        if (!(summaryField.summaryOperation is String) &&
+                            summaryField.summaryOperation is ISummaryCalculator)
+                            summaryCalculator = ISummaryCalculator(summaryField.summaryOperation);
+                        else
+                            summaryCalculator = defaultSummaryCalculator;
+
+                        var summaryObject:Object = getSummary(current, summaryField);
+
+                        if (isFirst)
+                        {
+                            summaryMap[summaryField] = summaryCalculator.summaryOfSummaryCalculationBegin(summaryObject["summaryObject"], summaryField);
+                        }
+                        else
+                        {
+                            summaryCalculator.calculateSummaryOfSummary(summaryMap[summaryField], summaryObject["summaryObject"], summaryField);
+                        }
+                    }
+                }
+
+                isFirst = false;
+                cursor.moveNext();
+            }
+
+            // check if there were some items
+            if (!isFirst)
+            {
+                for (i = 0; i < m; i++)
+                {
+                    summaryField = summaryFields[i];
+
+                    if (!(summaryField.summaryOperation is String) &&
+                        summaryField.summaryOperation is ISummaryCalculator)
+                        summaryCalculator = ISummaryCalculator(summaryField.summaryOperation);
+                    else
+                        summaryCalculator = defaultSummaryCalculator;
+
+                    var summary:Number = summaryCalculator.returnSummaryOfSummary(summaryMap[summaryField], summaryField);
+
+                    populateSummary(node, summaryField, summaryMap[summaryField], summary);
+                }
+            }
+        }
+
+        if (depth == -1)
+            insertSummaries(super.source as ICollectionView, -1, true);
+        else
+            insertSummaries(node, depth);
+    }
+
+    private function insertSummaries(node:Object, depth:int, rootSummary:Boolean = false):void
+    {
+        var summaries:Array = this.summaries;
+
+        if (!rootSummary)
+            summaries = grouping.fields[depth].summaries;
+
+        if (!summaries)
+            return;
+
+        var summaryObj:Array = [];
+
+        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:SummaryField2 = summaryRow.fields[j];
+                var summary:Number = 0.0;
+                var label:String = summaryField.label ? summaryField.label : summaryField.dataField;
+
+                var summaryObject:Object = getSummary(node, summaryField);
+
+                if (summaryObject != null)
+                {
+                    summary = summaryObject["value"];
+                    // populate the summary object
+                    summaryObj[i][label] = summary;
+                }
+            }
+            // populate the object summary map
+            if (objectSummaryMap[node] == undefined)
+                objectSummaryMap[node] = [];
+
+            objectSummaryMap[node].push(summaryObj[i]);
+        }
+
+        // insert the summary
+        if (rootSummary)
+            insertRootSummary(summaryObj);
+        else
+            insertSummary(node, summaryObj, summaries);
+
+    }
+
+    /**
+     *  @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 (!(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;
+
+            if (dispatchCollectionEvents)
+            {
+                var hierarchicalData:IHierarchicalData = new HierarchicalData(newCollection);
+                HierarchicalData(hierarchicalData).childrenField = childrenField;
+
+                hView = new HierarchicalCollectionView(
+                                            hierarchicalData, _openItems);
+            }
+
+            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;
+
+            var n:int = 0;
+
+            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 = [];
+                    }
+
+                    // calculate summaries for created groups
+                    if (summaryPresent)
+                    {
+                        for (n = currentGroups.length - 1; n >= i; n--)
+                            getSummaries(currentGroups[n], n);
+                    }
+
+                    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
+                    if (dispatchCollectionEvents)
+                    {
+                        IHierarchicalCollectionView(hView).addChild(currentGroups[i-1], currentGroups[i]);
+                    } else
+                    {
+                        if (i > 0)
+                        {
+                            currentGroups[i-1][childrenField].source.push(currentGroups[i]);
+                        }
+                        else
+                        {
+                            newCollection.source.push(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;
+
+                // calculate summaries for created groups
+                if (summaryPresent)
+                {
+                    for (n = fieldCount - 1; n >= 0; n--)
+                        getSummaries(currentGroups[n], n);
+                }
+            }
+
+            // calculate root summaries
+            if (source && summaries)
+            {
+                if (!super.source)
+                    super.source = new ArrayCollection([source]) as Object;
+
+                generateRootSummaries(grouping == null);
+            }
+
+			// refresh the collection to reflect the changes
+			// we made while grouping.
+			// This is needed as we made changes directly to
+			// the source of the collection when
+			// dispatchCollectionEvents is false
+			newCollection.refresh();
+
+            // 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
+     *  Get all the summary fields and store them in an Array
+     */
+    private function prepareSummaryFields():void
+    {
+        summaryFields = [];
+
+        var sr:SummaryRow
+
+        // for grouping fields summaries
+        if (grouping.fields != null)
+        {
+            for (var i:int = 0; i < grouping.fields.length; i++)
+            {
+                var gf:GroupingField = grouping.fields[i];
+                if (gf.summaries != null)
+                {
+                    for (var j:int = 0; j < gf.summaries.length; j++)
+                    {
+                        sr = gf.summaries[j];
+                        if (sr.fields != null)
+                        {
+                            for (var k:int = 0; k < sr.fields.length; k++)
+                            {
+                                summaryPresent = true;
+                                summaryFields.push(sr.fields[k]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // for root level summaries
+        if (summaries != null)
+        {
+            for (i = 0; i < summaries.length; i++)
+            {
+                sr = summaries[i];
+                if (sr.fields != null)
+                {
+                    for (j = 0; j < sr.fields.length; j++)
+                    {
+                        summaryPresent = true;
+                        summaryFields.push(sr.fields[j]);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     *  @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;
+    }
+
+    /**
+     *  @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 (summariesTracker != null && summariesTracker[parent])
+                            summariesTracker[parent] = new Dictionary(false);
+
+                        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
+     *
+     *  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();
+    }
+}
+
+}


Transferred from the Adobe Open Source Subversion Repository

Revision: 23247
Author:   cframpto@adobe.com
Date:     2011-12-20T19:21:13.134833Z

Log Message:
-----------
Remove ADOBE SYSTEMS license and replace with Apache license in headers - frameworks.  A 2nd pass will be needed to get the files not handled up by the scripts.

Modified Paths:
--------------
4959 paths were modified

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

--- frameworks/projects/mobilecomponents/src/spark/components/ArrowDirection.as
+++ frameworks/projects/mobilecomponents/src/spark/components/ArrowDirection.as
@@ -1,11 +1,19 @@
 ////////////////////////////////////////////////////////////////////////////////
 //
-//  ADOBE SYSTEMS INCORPORATED
-//  Copyright 2011 Adobe Systems Incorporated
-//  All Rights Reserved.
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
 //
-//  NOTICE: Adobe permits you to use, modify, and distribute this file
-//  in accordance with the terms of the license agreement accompanying it.
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
 //
 ////////////////////////////////////////////////////////////////////////////////


Transferred from the Adobe Open Source Subversion Repository

Revision: 13170
Author:   klin@adobe.com
Date:     2009-12-22T23:51:28.763100Z

Log Message:
-----------
Fix for an RTE in TrackBase and SliderBase when the track doesn't exist. Needed null check in the mouse move handlers.

QE notes: No
Doc notes: No
Bugs: SDK-24793
Reviewer: Jason
Tests run: checkintests
Is noteworthy for integration: No

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

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

--- frameworks/projects/spark/src/spark/components/supportClasses/SliderBase.as
+++ frameworks/projects/spark/src/spark/components/supportClasses/SliderBase.as
@@ -641,6 +641,9 @@
      */
     override protected function system_mouseMoveHandler(event:MouseEvent):void
     {
+        if (!track)
+            return;
+
         var p:Point = track.globalToLocal(new Point(event.stageX, event.stageY));
         var newValue:Number = pointToValue(p.x - clickOffset.x, p.y - clickOffset.y);
         newValue = nearestValidValue(newValue, snapInterval);


CSVDataSource: dataType for each column is now cached so it will appear in the metadata editor.

--- WeaveData/src/weave/data/DataSources/CSVDataSource.as
+++ WeaveData/src/weave/data/DataSources/CSVDataSource.as
@@ -111,11 +111,13 @@
 		 * Contains the csv data that should be used elsewhere in the code
 		 */
 		private var parsedRows:Array;
+		private var cachedDataTypes:Object = {};
 		private var columnIds:Array = [];
 		private var keysVector:Vector.<IQualifiedKey>;

 		protected function handleParsedRows(rows:Array):void
 		{
+			cachedDataTypes = {};
 			parsedRows = rows;
 			columnIds = rows && rows[0] is Array ? (rows[0] as Array).concat() : [];
 			// make sure column names are unique - if not, use index values for columns with duplicate names
@@ -161,11 +163,11 @@
 		}
 		/**
 		 * Convenience function for setting session state of csvData.
-		 * @param rows
+		 * @param csvDataString CSV string using comma as a delimiter.
 		 */
 		public function setCSVDataString(csvDataString:String):void
 		{
-			asyncParser.parseCSV(csvDataString);
+			csvData.setSessionState(WeaveAPI.CSVParser.parseCSV(csvDataString));
 		}

 		/**
@@ -220,6 +222,8 @@
 			var metadata:Object = {};
 			metadata[ColumnMetadata.TITLE] = getColumnTitle(id);
 			metadata[ColumnMetadata.KEY_TYPE] = keyType.value || DataType.STRING;
+			if (cachedDataTypes[id])
+				metadata[ColumnMetadata.DATA_TYPE] = cachedDataTypes[id];

 			// get column metadata from session state
 			var meta:Object = getColumnMetadata(id);
@@ -548,6 +552,7 @@
 					(newColumn as StringColumn).setRecords(keysVector, strings);
 				}
 			}
+			cachedDataTypes[columnId] = newColumn.getMetadata(ColumnMetadata.DATA_TYPE);
 			proxyColumn.setInternalColumn(newColumn);
 		}

@@ -615,7 +620,7 @@
 		// backwards compatibility
 		[Deprecated] public function set csvDataString(value:String):void
 		{
-			asyncParser.parseCSV(value);
+			setCSVDataString(value);
 		}

 		[Deprecated(replacement="getColumnById")] public function getColumnByName(name:String):IAttributeColumn { return getColumnById(name); }