added more code for compiling statements.

--- WeaveCore/src/weave/compiler/Compiler.as
+++ WeaveCore/src/weave/compiler/Compiler.as
@@ -58,40 +58,63 @@
 		private static const INDEX_TRUE:int = 1;
 		private static const INDEX_FALSE:int = 2;

-		private static const STATEMENT_IF:String = 'if';
-		private static const STATEMENT_ELSE:String = 'else';
-		private static const STATEMENT_FOR:String = 'for';
-		private static const STATEMENT_EACH:String = 'each';
-		private static const STATEMENT_DO:String = 'do';
-		private static const STATEMENT_WHILE:String = 'while';
-		private static const STATEMENT_RETURN:String = 'return';
-		private static const STATEMENT_BREAK:String = 'break';
-		private static const STATEMENT_CONTINUE:String = 'continue';
-		private static const STATEMENT_SWITCH:String = 'switch';
-		private static const STATEMENT_CASE:String = 'case';
-		private static const STATEMENT_DEFAULT:String = 'default';
-		private static const STATEMENT_THROW:String = 'throw';
-		private static const STATEMENT_TRY:String = 'try';
-		private static const STATEMENT_CATCH:String = 'catch';
-		private static const STATEMENT_FINALLY:String = 'finally';
+		private static const ST_IF:String = 'if';
+		private static const ST_ELSE:String = 'else';
+
+		private static const ST_FOR:String = 'for';
+		private static const ST_EACH:String = 'each';
+		private static const ST_FOR_EACH:String = 'for each';
+
+		private static const ST_DO:String = 'do';
+		private static const ST_WHILE:String = 'while';
+
+		private static const ST_SWITCH:String = 'switch';
+		private static const ST_CASE:String = 'case';
+		private static const ST_DEFAULT:String = 'default';
+
+		private static const ST_TRY:String = 'try';
+		private static const ST_CATCH:String = 'catch';
+		private static const ST_FINALLY:String = 'finally';
+
+		private static const ST_BREAK:String = 'break';
+		private static const ST_CONTINUE:String = 'continue';
+
+		private static const ST_RETURN:String = 'return';
+		private static const ST_THROW:String = 'finally';

 		private static const _statementsWithoutParams:Array = [
-			STATEMENT_ELSE, STATEMENT_DO, STATEMENT_RETURN, STATEMENT_BREAK, STATEMENT_CONTINUE,
-			STATEMENT_CASE, STATEMENT_DEFAULT, STATEMENT_THROW, STATEMENT_TRY, STATEMENT_FINALLY
+			ST_ELSE, ST_DO, ST_BREAK, ST_CONTINUE, ST_CASE, ST_DEFAULT,
+			ST_TRY, ST_FINALLY, ST_RETURN, ST_THROW
 		];
 		private static const _statementsWithParams:Array = [
-			STATEMENT_IF, STATEMENT_FOR, STATEMENT_EACH, STATEMENT_WHILE, STATEMENT_SWITCH, STATEMENT_CATCH
+			ST_IF, ST_FOR, ST_FOR_EACH, ST_WHILE, ST_SWITCH, ST_CATCH
 		];
-
+
+		private static const _PARAMS:String = 'PARAMS'; // must be enclosed in ()
+		private static const _STMT:String = 'STMT'; // may contain multiple statements enclosed in {}
+		private static const _EXPR:String = 'EXPR'; // may only contain one expression, optionally enclosed in (), no statements
+		// longer patterns appear earlier so they will match before shorter patterns when checked in order
+		private static const _validStatementPatterns:Array = [
+			[ST_IF, _PARAMS, _STMT, ST_ELSE, _STMT],
+			[ST_IF, _PARAMS, _STMT],
+			[ST_FOR_EACH, _PARAMS, _STMT],
+			[ST_FOR, _PARAMS, _STMT],
+			[ST_DO, _STMT, ST_WHILE, _PARAMS],
+			[ST_WHILE, _PARAMS, _STMT],
+			[ST_TRY, _STMT, ST_CATCH, _PARAMS, _STMT, ST_FINALLY, _STMT],
+			[ST_TRY, _STMT, ST_FINALLY, _STMT],
+			[ST_TRY, _STMT, ST_CATCH, _PARAMS, _STMT],
+			[ST_BREAK],
+			[ST_CONTINUE],
+			[ST_RETURN, _EXPR],
+			[ST_RETURN],
+			[ST_THROW, _EXPR]
+		];
+
 		/**
 		 * (statement name):String -> (true if requires parentheses):Boolean
 		 */
 		private static var statements:Object = null;
-
-		/**
-		 * String->Array.  Examples: "else"->["if"], "while"->["do"], "finally"->["try", "catch"], "catch"->["try"]
-		 */
-		private static var statementSiblingsLookup:Object = null;

 		/**
 		 * This is the prefix used for the function notation of infix operators.
@@ -272,14 +295,6 @@
 					statements[stmt] = true;
 				for each (stmt in _statementsWithoutParams)
 					statements[stmt] = false;
-
-				statementSiblingsLookup = {};
-				statementSiblingsLookup[STATEMENT_CASE] = [STATEMENT_SWITCH, STATEMENT_CASE, STATEMENT_DEFAULT];
-				statementSiblingsLookup[STATEMENT_DEFAULT] = [STATEMENT_SWITCH, STATEMENT_CASE];
-				statementSiblingsLookup[STATEMENT_WHILE] = [STATEMENT_DO];
-				statementSiblingsLookup[STATEMENT_ELSE] = [STATEMENT_IF];
-				statementSiblingsLookup[STATEMENT_CATCH] = [STATEMENT_TRY];
-				statementSiblingsLookup[STATEMENT_FINALLY] = [STATEMENT_TRY, STATEMENT_CATCH];
 			}
 			constants = {};
 			operators = {};
@@ -563,10 +578,10 @@
 		 * This function will recursively compile a set of tokens into a compiled object representing a function that takes no parameters and returns a value.
 		 * Example set of input tokens:  pow ( - ( - 2 + 1 ) ** - 4 , 3 ) - ( 4 + - 1 )
 		 * @param tokens An Array of tokens for an expression.  This array will be modified in place.
-		 * @param allowEmptyExpression If tokens is an empty Array, setting this to true will return an empty compiled object instead of throwing an error.
+		 * @param allowSemicolons Set to true to allow multiple statements and empty expressions.
 		 * @return A CompiledConstant or CompiledFunctionCall generated from the tokens, or null if the tokens do not represent a valid expression.
 		 */
-		private function compileTokens(tokens:Array, allowEmptyExpression:Boolean):ICompiledObject
+		private function compileTokens(tokens:Array, allowSemicolons:Boolean):ICompiledObject
 		{
 			// there are no more parentheses, so the remaining tokens are operators, constants, and variable names.
 			if (debug)
@@ -608,6 +623,13 @@
 					tokens.splice(i, 2, new CompiledConstant(OPERATOR_ESCAPE + token, operators[token]));
 				}
 			}
+
+			// next step: combine 'for each' into a single token
+			if (tokens[0] == ST_EACH)
+				throw new Error("Invalid statement 'each'");
+			for (i = tokens.length; i > 0; i--)
+				if (tokens[i] == ST_EACH && tokens[i - 1] == ST_FOR)
+					tokens.splice(i - 1, 2, ST_FOR_EACH);

 			// next step: compile unary '#' operators (except those immediately followed by other operators)
 			if (operators.hasOwnProperty('#'))
@@ -744,8 +766,17 @@
 				return compileOperator(',', compileArray(tokens, ','));

 			if (tokens.indexOf(';') >= 0)
-				return compileOperator(';', compileArray(tokens, ';'));
-
+			{
+				if (allowSemicolons)
+					return compileOperator(';', compileArray(tokens, ';'));
+
+				// decompile each token for the error message
+				var str:String = '';
+				for each (var tok:* in tokens)
+					str += (str ? ' ' : '') + (tok as String || decompileObject(tok));
+				throw new Error("Unexpected semicolon: " + str);
+			}
+
 			// next step: compile statements
 			compileStatements(tokens);

@@ -760,7 +791,7 @@
 				throw new Error("Missing operator between " + leftToken + ' and ' + rightToken);
 			}

-			if (allowEmptyExpression)
+			if (allowSemicolons)
 				return compileOperator(';', tokens);

 			throw new Error("Empty expression");
@@ -903,7 +934,7 @@
 					//replace code between brackets with an int like {0} so the resulting string can be passed to StringUtil.substitute() with compiledObject as the next parameter
 					output += input.substring(searchIndex, bracketIndex) + '{' + compiledObjects.length + '}';
 					searchIndex = escapeIndex + 1;
-					compiledObjects.push(compileTokens(tokens, false));
+					compiledObjects.push(compileTokens(tokens, true));
 				}
 			}
 			throw new Error("unreachable");
@@ -977,7 +1008,7 @@
 				var subArray:Array = tokens.splice(open + 1, close - open - 1);
 				if (debug)
 					trace("compiling tokens", leftBracket, subArray.join(' '), rightBracket);
-				var separator:String = (leftBracket == '{' || token == STATEMENT_FOR) ? ';' : ',';
+				var separator:String = (leftBracket == '{' || statements.hasOwnProperty(token)) ? ';' : ',';
 				compiledParams = compileArray(subArray, separator);

 				if (leftBracket == '[') // this is either an array or a property access
@@ -1117,6 +1148,12 @@
 		 */
 		private function compileStatements(tokens:Array, startIndex:int = 0):void
 		{
+			return;
+			// TODO: use _validStatementPatterns
+			//TODO: if first token is a statement, then use _validStatementPatterns.  any leftover tokens means there is an error
+			// determine types of all tokens, then array compare on items in _validStatementParams.
+
+
 			var i:int;
 			var j:int;
 			var stmt:String;
@@ -1145,7 +1182,8 @@
 			if (i >= tokens.length)
 				return;

-			if (statements[tokens[i]]) // requires params.  Example:  if () {}
+			stmt = tokens[i];
+			if (statements[stmt]) // requires params.  Example:  if () {}
 			{
 				compileStatements(tokens, i + 2);
 			}
@@ -1156,96 +1194,80 @@

 			// now everything to the right of the current statement and its params have been taken care of.

-
-
-			switch (tokens[i])
-			{
-				case STATEMENT_FOR: // for () {}
-				case STATEMENT_WHILE: // while () {}
-				case STATEMENT_IF: // if () {} else {}
-				case STATEMENT_ELSE: // else {}
-				case STATEMENT_EACH: // for each () {}
-				case STATEMENT_DO: // do {} while ()
-				case STATEMENT_RETURN: // return EXPR
-				case STATEMENT_BREAK: // break
-				case STATEMENT_CONTINUE: // continue
-				case STATEMENT_SWITCH: // switch () {}
-				case STATEMENT_CASE: // case EXPR :
-				case STATEMENT_DEFAULT: // default :
-				case STATEMENT_THROW: // throw EXPR
-				case STATEMENT_TRY: // try {} catch () {} finally {}
-				case STATEMENT_CATCH: // catch () {}
-				case STATEMENT_FINALLY: // finally {}
+			var cfc:CompiledFunctionCall;
+			var cc:CompiledConstant = new CompiledConstant(stmt, stmt);
+
+			if (stmt == ST_FOR || stmt == ST_FOR_EACH)
+			{
+
+			}
+
+			if (stmt == ST_IF) // if () {} else {}
+			{
+			}
+			switch (stmt)
+			{
+				case ST_WHILE: // while () {}
+					tokens.splice(i, 3, compileFunctionCall(cc, tokens.slice(i + 1, 2)));
+					return;
+				case ST_IF: // if () {} else {}
+					if (tokens[i + 3] == ST_ELSE)
+						tokens.splice(i, 5, compileFunctionCall(cc, [ tokens[i + 1], tokens[i + 2], tokens[i + 4] ]));
+				case ST_ELSE: // else {}
+
+				case ST_BREAK: // break
+				case ST_CONTINUE: // continue
+
+				case ST_RETURN: // return EXPR
+
+				case ST_FOR: // for () {}
+				case ST_FOR_EACH: // "for each" () {}
+				case ST_DO: // do {} while ()
+
+				case ST_TRY: // try {} catch () {} finally {}
+				case ST_CATCH: // catch () {}
+				case ST_FINALLY: // finally {}
+
+				case ST_SWITCH: // switch () {}
+				case ST_CASE: // case EXPR :
+				case ST_DEFAULT: // default :
+
 				default:
 					return;
 			}
 		}
-		private function compileStatements1(tokens:Array):void
-		{
-			var tokenIndex:int = tokens.length;
-			while (tokenIndex--) // right to left
-			{
-				var token:String = tokens[tokenIndex] as String;
-				if (!statements.hasOwnProperty(token))
-					continue;
-
-				var firstSiblingIndex:int = tokenIndex;
-				var siblings:Array = statementSiblingsLookup[token] as Array;
-				var i:int = tokenIndex;
-				while (siblings && i--)
-				{
-					var sibTok:String = tokens[i] as String
-					// skip non-statement tokens
-					if (!statements.hasOwnProperty(sibTok))
-						continue;
-					if (siblings.indexOf(sibTok) >= 0)
-					{
-						// found sibling
-						firstSiblingIndex = i;
-						// now check for siblings of this sibling
-						siblings = statementSiblingsLookup[sibTok] as Array;
-						break;
-					}
-					// stop if we found the same type of token and it's not a valid sibling
-					if (sibTok == token)
-						break;
-				}
-
-//				assertValidStatementParams(tokens, firstSiblingIndex, tokenIndex);
-			}
-		}

 		private function assertValidStatementParams(tokens:Array, index:int):void
 		{
 			var statement:String = tokens[index] as String;
 			if (statements[statement]) // requires parameters?
 			{
+				// statement parameters must be wrapped in operator ';' call
 				var params:CompiledFunctionCall = tokens[index + 1] as CompiledFunctionCall;
-				if (!params)
+				if (!params || params.evaluatedMethod != operators[';'])
 					throwInvalidSyntax(statement);

-				var separator:String = statement == STATEMENT_FOR ? ';' : ',';
-				if (params.evaluatedMethod == operators[separator])
-				{
-					var cpl:int = params.compiledParams.length;
-					if (statement == STATEMENT_FOR)
-					{
-						if (cpl == 3)
-							return;
-						if (cpl == 1)
-						{
-							var cfc:CompiledFunctionCall = params.compiledParams[0] as CompiledFunctionCall;
-							if (cfc && cfc.evaluatedMethod == operators['in'])
-								return;
-						}
+				var cpl:int = params.compiledParams.length;
+				if (statement == ST_FOR || statement == ST_FOR_EACH)
+				{
+					// 'for' and 'for each' require either 3 or 1 statement params
+					if (cpl != 3 && cpl != 1)
 						throwInvalidSyntax(statement);
-					}
-					else if (cpl != 1)
-					{
-						throwInvalidSyntax(statement);
-					}
-				}
-				else
+
+					if (cpl == 1)
+					{
+						// if 'for' or 'for each' has only one param, it must be the 'in' operator
+						var cfc:CompiledFunctionCall = params.compiledParams[0] as CompiledFunctionCall;
+						if (!cfc || cfc.evaluatedMethod != operators['in'])
+							throwInvalidSyntax(statement);
+
+						// the 'in' operator must have a variable or property reference as its first parameter
+						cfc = cfc.compiledParams[0];
+						if (cfc.compiledParams != null || cfc.evaluatedMethod != operators['.']) // not a variable and not a property
+							throwInvalidSyntax(statement);
+					}
+				}
+				else if (cpl != 1)
 				{
 					throwInvalidSyntax(statement);
 				}


Synchronizer now listens for linkableVariable dispose

--- WeaveCore/src/weave/core/Synchronizer.as
+++ WeaveCore/src/weave/core/Synchronizer.as
@@ -35,6 +35,7 @@
 		public function Synchronizer(linkableVariable:ILinkableVariable, bindableParent:Object, bindablePropertyName:String, delay:uint = 0, onlyWhenFocused:Boolean = false):void
 		{
 			sm.registerDisposableChild(bindableParent, this);
+			sm.registerDisposableChild(linkableVariable, this);
 			this.linkableVariable = linkableVariable;
 			this.bindableParent = bindableParent;
 			this.bindablePropertyName = bindablePropertyName;
@@ -55,12 +56,21 @@

 			// when the session state changes, set the bindable property
 			if (this.callbackCollection)
+			{
 				this.callbackCollection.addImmediateCallback(bindableParent, synchronize);
+				this.callbackCollection.addDisposeCallback(bindableParent, linkableVariableDisposeCallback);
+			}
+		}
+
+		private function linkableVariableDisposeCallback():void
+		{
+			WeaveAPI.SessionManager.disposeObject(this);
 		}

 		public function dispose():void
 		{
-			this.callbackCollection.removeCallback(synchronize);
+			if (this.callbackCollection)
+				this.callbackCollection.removeCallback(synchronize);
 			if (this.watcher)
 				this.watcher.unwatch();


fixed bug where variable wasn't set at the right time.

--- WeaveCore/src/weave/core/Synchronizer.as
+++ WeaveCore/src/weave/core/Synchronizer.as
@@ -45,6 +45,7 @@
 			this.delay = delay;
 			this.onlyWhenFocused = onlyWhenFocused;
 			this.callbackCollection = sm.getCallbackCollection(linkableVariable);
+			this.uiComponent = bindableParent as UIComponent;

 			// Copy session state over to bindable property now, before calling BindingUtils.bindSetter(),
 			// because that will copy from the bindable property to the sessioned property.
@@ -76,9 +77,9 @@
 		private var delay:uint;
 		private var onlyWhenFocused:Boolean;
 		private var watcher:ChangeWatcher;
+		private var uiComponent:UIComponent;
 		private var useLinkableValue:Boolean = true;
 		private var callLaterTime:int = 0;
-		private var uiComponent:UIComponent = bindableParent as UIComponent;
 		private var recursiveCall:Boolean = false;

 		// When given zero parameters, this function copies the linkable value to the bindable value.


Transferred from the Adobe Open Source Subversion Repository

Revision: 22769
Author:   chiedozi@adobe.com
Date:     2011-09-28T18:01:15.715672Z

Log Message:
-----------
ASDoc and comment updates to SplitViewNavigator and FlipViewTransition

QE notes:
Doc notes:
Bugs:
Reviewer:
Tests run:
Is noteworthy for integration: No

Modified Paths:
--------------
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobilecomponents/src/spark/transitions/FlipViewTransition.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobilecomponents/src/spark/components/SplitViewNavigator.as</path>

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

--- frameworks/projects/mobilecomponents/src/spark/components/SplitViewNavigator.as
+++ frameworks/projects/mobilecomponents/src/spark/components/SplitViewNavigator.as
@@ -107,6 +107,10 @@
  *  This method always returns the correct navigator regardless of whether
  *  a navigator is in a popup or not.

  *
+ *
By default, when the popup is opened, it is sized to the preferred width
+ *  and height of the first navigator.  The size of the popup can be changed by
+ *  explicitly setting its width and height or by reskinning the component.

+ *
  *
Note: When a SplitViewNavigator is used as a child of a
  *  TabbedViewNavigator, changes to the tabBarVisible on the
  *  active views will not be honored by the parent TabbedViewNavigator.

@@ -303,7 +307,7 @@
     //  numViewNavigators
     //----------------------------------
     /**
-     *  The number of navigators managed by this container.
+     *  The number of view navigators managed by this container.
      *
      *  @langversion 3.0
      *  @playerversion AIR 3
@@ -435,8 +439,6 @@
      */
     mx_internal function showNavigatorAtIndexInPopUp(index:int, owner:DisplayObjectContainer):void
     {
-        // TODO (chiedozi): Consider replacing the navigator in the popup if
-        // it is already open.
         if (index >= numElements || !viewNavigatorPopUp|| viewNavigatorPopUp.isOpen)
             return;

@@ -713,7 +715,7 @@
         if (!dataArray)
             return;

-        // Restore each navigators persistence data
+        // Restore each navigators' persistence data
         for (var i:int = 0; i < numViewNavigators; i++)
         {
             if (i >= dataArray.length)


Transferred from the Adobe Open Source Subversion Repository

Revision: 12570
Author:   egeorgie@adobe.com
Date:     2009-12-05T00:37:35.278281Z

Log Message:
-----------
Fix http://bugs.adobe.com/jira/browse/SDK-23746 Side-effecting the x/y properties on a component and invalidating the properties causes parent display list invalidation and http://bugs.adobe.com/jira/browse/SDK-23986 make UIComponent.transformAround so it OPTIONALLY invalidates parent displayList

Problem: We are invalidating parent based on checks of x & y against oldX & oldY in validateProperties.
Fix: Move the checks to the x & y setters. Additionally add the optional parameter "invalidateLayout" to ILayoutElement.transformAround method.

QE notes: None
Doc notes: None
Bugs: SDK-2374, SDK-23986
Reviewer: Deepa
Tests run: checkintests, mustella gumbo/layout, gumbo/core/Group
Is noteworthy for integration: No

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/spark/src/spark/core/SpriteVisualElement.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/spark/src/spark/primitives/supportClasses/GraphicElement.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flash-integration/src/mx/flash/UIMovieClip.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/core/ILayoutElement.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/core/UIComponent.as</path>

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

--- frameworks/projects/spark/src/spark/primitives/supportClasses/GraphicElement.as
+++ frameworks/projects/spark/src/spark/primitives/supportClasses/GraphicElement.as
@@ -2164,7 +2164,8 @@
                                     translation:Vector3D = null,
                                     postLayoutScale:Vector3D = null,
                                     postLayoutRotation:Vector3D = null,
-                                    postLayoutTranslation:Vector3D = null):void
+                                    postLayoutTranslation:Vector3D = null,
+                                    invalidateLayout:Boolean = true):void
     {
         // FIXME (egreenfi): optimize for simple translations
         allocateLayoutFeatures();
@@ -2173,7 +2174,7 @@
         var prevY:Number = layoutFeatures.layoutY;
         var prevZ:Number = layoutFeatures.layoutZ;
         layoutFeatures.transformAround(transformCenter,scale,rotation,translation,postLayoutScale,postLayoutRotation,postLayoutTranslation);
-        invalidateTransform(previous != needsDisplayObject);
+        invalidateTransform(previous != needsDisplayObject, invalidateLayout);
         if (prevX != layoutFeatures.layoutX)
             dispatchPropertyChangeEvent("x", prevX, layoutFeatures.layoutX);
         if (prevY != layoutFeatures.layoutY)


Put Upload New button at top of media picker list

--- flexEditor/src/org/arisgames/editor/components/ItemEditorMediaPickerView.as
+++ flexEditor/src/org/arisgames/editor/components/ItemEditorMediaPickerView.as
@@ -172,6 +172,15 @@
 		var numIconDefaults:Number = 0;
 		for (var k:Number = 0; k <= 1; k++) //Iterates over list twice; once for uploaded items, again for default
 		{
+			//Add "Upload new" in between uploaded and default pictures
+			if(k==0 && (!this.isIconPicker && !this.isNPC)){
+				xmlData.node.(@label == AppConstants.MEDIATYPE_IMAGE).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
+				xmlData.node.(@label == AppConstants.MEDIATYPE_AUDIO).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
+				xmlData.node.(@label == AppConstants.MEDIATYPE_VIDEO).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
+			}
+			else if(k == 0){
+				xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
+			}
 			for (var j:Number = 0; j < media.length; j++)
 			{
 				var o:Object = media[j];
@@ -237,16 +246,6 @@
 					}
 				}
 			}
-
-			//Add "Upload new" in between uploaded and default pictures
-			if(k==0 && (!this.isIconPicker && !this.isNPC)){
-				xmlData.node.(@label == AppConstants.MEDIATYPE_IMAGE).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
-				xmlData.node.(@label == AppConstants.MEDIATYPE_AUDIO).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
-				xmlData.node.(@label == AppConstants.MEDIATYPE_VIDEO).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
-			}
-			else if(k == 0){
-				xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
-			}
 		}
         trace("ItemEditorMediaPickerView: handleLoadingOfMediaIntoXML: Just finished loading Media Objects into XML.  Here's what the new XML looks like:");
         this.printXMLData();


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@1290245 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: 21960
Author:   aaltman@adobe.com
Date:     2011-08-12T21:09:59.193901Z

Log Message:
-----------
Gave StageTextAreaSkin the same default height as mobile TextAreaSkin
Fixed StageText-based skins to not send negative dimensions to StageText
Fixed popup visibility event dispatching and handling by StyleableStageText

QE notes: None
Doc notes: None
Bugs: SDK-31154, SDK-31128, SDK-31111, SDK-31062, SDK-30976
Reviewer: cframpto, aharui
Tests run: checkintests, mustella, mustella-AIR, mustella-mobile, mxunit
Is noteworthy for integration: No

Modified Paths:
--------------
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/StyleableStageText.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/framework/src/mx/managers/PopUpManagerImpl.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobiletheme/src/spark/skins/mobile/StageTextAreaSkin.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/4.y/frameworks/projects/mobiletheme/src/spark/skins/mobile/StageTextInputSkin.as</path>

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

--- frameworks/projects/mobiletheme/src/spark/skins/mobile/StageTextAreaSkin.as
+++ frameworks/projects/mobiletheme/src/spark/skins/mobile/StageTextAreaSkin.as
@@ -11,6 +11,8 @@

 package spark.skins.mobile
 {
+import mx.core.DPIClassification;
+
 import spark.components.TextArea;
 import spark.components.supportClasses.StyleableTextField;
 import spark.skins.mobile.supportClasses.StageTextSkinBase;
@@ -43,6 +45,25 @@
     {
         super();
         multiline = true;
+
+        switch (applicationDPI)
+        {
+            case DPIClassification.DPI_320:
+            {
+                measuredDefaultHeight = 106;
+                break;
+            }
+            case DPIClassification.DPI_240:
+            {
+                measuredDefaultHeight = 70;
+                break;
+            }
+            default:
+            {
+                measuredDefaultHeight = 53;
+                break;
+            }
+        }
     }

     //--------------------------------------------------------------------------
@@ -77,8 +98,8 @@
         var paddingTop:Number = getStyle("paddingTop");
         var paddingBottom:Number = getStyle("paddingBottom");

-        var unscaledTextWidth:Number = unscaledWidth - paddingLeft - paddingRight;
-        var unscaledTextHeight:Number = unscaledHeight - paddingTop - paddingBottom;
+        var unscaledTextWidth:Number = Math.max(0, unscaledWidth - paddingLeft - paddingRight);
+        var unscaledTextHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);

         if (textDisplay)
         {


Transferred from the Adobe Open Source Subversion Repository

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

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

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

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

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

 package mx.messaging.channels.amfx
 {


Transferred from the Adobe Open Source Subversion Repository

Revision: 4677
Author:   cframpto@adobe.com
Date:     2009-01-26T22:20:26.166607Z

Log Message:
-----------
Add back damage handler for TextGraphic - the piece of 4661 that was reverted.  Peter D. has already run the mustella tests on this version.

Modified Paths:
--------------
/flex/sdk/trunk/frameworks/projects/flex4/src/mx/graphics/TextGraphic.as

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

--- frameworks/projects/spark/src/spark/components/RichText.as
+++ frameworks/projects/spark/src/spark/components/RichText.as
@@ -23,6 +23,7 @@
 import flashx.textLayout.elements.ParagraphElement;
 import flashx.textLayout.elements.SpanElement;
 import flashx.textLayout.elements.TextFlow;
+import flashx.textLayout.events.DamageEvent;
 import flashx.textLayout.formats.CharacterFormat;
 import flashx.textLayout.formats.ContainerFormat;
 import flashx.textLayout.formats.ICharacterFormat;
@@ -196,6 +197,17 @@
      */
     private var textInvalid:Boolean = false;

+    /**
+     *  @private
+     *  This flag is set to true if the text must be clipped.
+     */
+    private var isOverset:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var stylesChanged:Boolean = false;
+
     //--------------------------------------------------------------------------
     //
     //  Overridden properties
@@ -361,11 +373,13 @@
         if (!mx_internal::styleChainInitialized)
             return;

-        compose(explicitWidth, explicitHeight);
+        isOverset = compose(explicitWidth, explicitHeight);

         var bounds:Rectangle = textFlowComposer.bounds;
         measuredWidth = Math.ceil(bounds.width);
         measuredHeight = Math.ceil(bounds.height);
+
+        //trace("measure", explicitWidth, explicitHeight, measuredWidth, measuredHeight);
     }

     /**
@@ -374,6 +388,8 @@
     override protected function updateDisplayList(unscaledWidth:Number,
                                                   unscaledHeight:Number):void
     {
+        //trace("updateDisplayList", unscaledWidth, unscaledHeight);
+
         super.updateDisplayList(unscaledWidth, unscaledHeight);

         // The updateDisplayList() method of a GraphicElement can get called
@@ -382,12 +398,20 @@
         if (!mx_internal::styleChainInitialized)
             return;

-        var overset:Boolean = compose(unscaledWidth, unscaledHeight);
-
+        // If both width and height are specified, then measure isn't called
+        // and measuredWidth/Height will remain 0.  In this case the compose
+        // will always be done here.  Otherwise measure will compose and set
+        // measuredWidth/Height/isOverset.  If the unscaledWidth/Height is the
+        // same as measuredWidth/Height there is no need to redo the compose.
+        if (stylesChanged ||
+                unscaledWidth != measuredWidth ||
+                    unscaledHeight != measuredHeight)
+            isOverset = compose(unscaledWidth, unscaledHeight);
+
         // Use scrollRect to clip overset lines.
         // But don't read or write scrollRect if you can avoid it,
         // because this causes Player 10.0 to allocate memory.
-        if (overset)
+        if (isOverset)
         {
             displayObject.scrollRect =
                 new Rectangle(0, 0, unscaledWidth, unscaledHeight);
@@ -397,7 +421,7 @@
         {
             displayObject.scrollRect = null;
             mx_internal::hasScrollRect = false;
-        }
+        }
     }

     /**
@@ -428,6 +452,8 @@
             hostFormatsInvalid = true;
         else
             setHostFormat(styleProp);
+
+        stylesChanged = true;
     }

     //--------------------------------------------------------------------------
@@ -627,6 +653,9 @@
      */
     private function compose(width:Number = NaN, height:Number = NaN):Boolean
     {
+        // Don't want this handler firing when we're re-composing the text lines.
+        textFlow.removeEventListener(DamageEvent.DAMAGE, textFlow_damageHandler);
+
         textFlow = createTextFlow();
         _content = textFlow;

@@ -642,8 +671,43 @@

         textFlowComposer.addTextLines(DisplayObjectContainer(displayObject));

+        // Just recomposed so reset.
+        stylesChanged = false;
+
+        // Listen for "damage" events in case the textFlow is
+        // modified programatically.
+        textFlow.addEventListener(DamageEvent.DAMAGE, textFlow_damageHandler);
+
         return textFlowComposer.isOverset;
     }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Event handlers
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *  Called when the TextFlow dispatches a 'damage' event
+     *  to indicate it has been modified.
+     */
+    private function textFlow_damageHandler(
+                            event:DamageEvent):void
+    {
+        //trace("damageHandler", "damageStart", event.damageStart, "damageLength", event.damageLength);
+
+        // The text flow changed.  It could have been either/or content or
+        // styles within the flow.
+        contentChanged = true;
+        stylesChanged = true;
+
+        // Unless both width/height were specified, need to recalc size.
+        if (isNaN(explicitWidth) || isNaN(explicitHeight))
+            invalidateSize();
+
+        invalidateDisplayList();
+    }
 }

 }


Transferred from the Adobe Open Source Subversion Repository

Revision: 20211
Author:   eday@adobe.com
Date:     2011-02-08T22:10:34.648451Z

Log Message:
-----------
Small change to prevent throw velocity precision loss.

The runtime globalToLocal and localToGlobal coordinate-space conversion functions round all results to the nearest 0.05.  So now we scale our throw velocity values up and back to preserve more precision.

QE notes:
Doc notes:
Bugs: SDK-29456
Reviewer: Ryan
Tests run: Cyclone with Steve
Is noteworthy for integration: no

Modified Paths:
--------------
/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/Scroller.as

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

--- frameworks/projects/spark/src/spark/components/Scroller.as
+++ frameworks/projects/spark/src/spark/components/Scroller.as
@@ -3270,14 +3270,28 @@
         // In order to use them to change the scroll position we must convert
         // them to the scroller's local coordinate space first.
         // This code converts the deltas from global to local.
+        //
+        // Note that we scale the velocity values up and then back down around the
+        // calls to globalToLocal.  This is because the runtime only returns values
+        // rounded to the nearest 0.05.  The velocities are small number (<4.0) with
+        // lots of precision that we don't want to lose.  The scaling preserves
+        // a sufficient level of precision for our purposes.
+        throwVelocity.x *= 100000;
+        throwVelocity.y *= 100000;
+
+        // Because we subtract out the difference between the two coordinate systems' origins,
+        // This is essentially just multiplying by a scaling factor.
         throwVelocity =
             scroller.globalToLocal(throwVelocity).subtract(scroller.globalToLocal(new Point(0,0)));
+
+        throwVelocity.x /= 100000;
+        throwVelocity.y /= 100000;

         // Note that we always call performThrow - even when the velocity is zero.
         // This is needed because we may be past the end of the list and need an
         // animation to get us back.
         scroller.performThrow(throwVelocity.x, throwVelocity.y);
-    }
+        }

     /**
      *  @private