You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@royale.apache.org by GitBox <gi...@apache.org> on 2018/10/09 20:17:57 UTC

[GitHub] aharui closed pull request #313: emulation components add and/or modified

aharui closed pull request #313: emulation components add and/or modified
URL: https://github.com/apache/royale-asjs/pull/313
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
index e5acdb11b..b94371dfd 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
@@ -148,14 +148,21 @@ internal class MXRoyaleClasses
 	import mx.events.ProgressEvent; ProgressEvent;
 	import mx.controls.advancedDataGridClasses.MXAdvancedDataGridItemRenderer; MXAdvancedDataGridItemRenderer;
 	import mx.formatters.Formatter; Formatter;
-        import mx.formatters.IFormatter; IFormatter;
+	import mx.formatters.IFormatter; IFormatter;
 	import mx.events.CalendarLayoutChangeEvent; CalendarLayoutChangeEvent;
 	import mx.net.SharedObject; SharedObject;
 	import mx.modules.ModuleManager; ModuleManager;
 	import mx.events.DragEvent; DragEvent;
+	import mx.formatters.DateBase; DateBase;
+	import mx.core.Keyboard; Keyboard;
+	import mx.core.UIComponentGlobals; UIComponentGlobals;
+	import mx.managers.ILayoutManagerClient; ILayoutManagerClient;
+	import mx.core.LayoutDirection; LayoutDirection;
+	import mx.styles.IAdvancedStyleClient; IAdvancedStyleClient;
+	import mx.collections.IComplexSortField; IComplexSortField;
 
 	COMPILE::JS
-    	{
+    {
 		import mx.utils.TextEncoderLiteWrapper; TextEncoderLiteWrapper;
 		import mx.utils.Base64JSWrapper; Base64JSWrapper;
 	}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/collections/IComplexSortField.as b/frameworks/projects/MXRoyale/src/main/royale/mx/collections/IComplexSortField.as
new file mode 100644
index 000000000..dffb21604
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/collections/IComplexSortField.as
@@ -0,0 +1,24 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.collections {
+    public interface IComplexSortField {
+        function get nameParts():Array;
+    }
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Alert.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Alert.as
index 73fd6e449..b8f845eb4 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Alert.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Alert.as
@@ -295,7 +295,7 @@ public class Alert extends Panel
      *  @private
      *  Storage for the cancelLabel property.
      */
-    //private static var _cancelLabel:String;
+    private static var _cancelLabel:String;
     
     /**
      *  @private
@@ -304,6 +304,26 @@ public class Alert extends Panel
 
     //[Inspectable(category="General")]
 
+	public static function get cancelLabel():String
+	{
+		// initialize();
+		
+		return _cancelLabel;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public static function set cancelLabel(value:String):void
+	{
+		/*cancelLabelOverride = value;
+		
+		_cancelLabel = value != null ?
+			value :
+			resourceManager.getString(
+				"controls", "cancelLabel");
+		*/
+	}
     //----------------------------------
     //  noLabel
     //----------------------------------
@@ -325,7 +345,7 @@ public class Alert extends Panel
      *  @private
      *  Storage for the okLabel property.
      */
-    //private static var _okLabel:String;
+    private static var _okLabel:String;
     
     /**
      *  @private
@@ -333,7 +353,29 @@ public class Alert extends Panel
     //private static var okLabelOverride:String;
 
     //[Inspectable(category="General")]
-
+	
+	public static function get okLabel():String
+	{
+		// initialize();
+		
+		return _okLabel;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public static function set okLabel(value:String):void
+	{
+		/*
+		okLabelOverride = value;
+		
+		_okLabel = value != null ?
+			value :
+			resourceManager.getString(
+				"controls", "okLabel");
+		*/
+	}
+	
     /**
      *  @private
      *  Storage for the yesLabel property.
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/core/Keyboard.as b/frameworks/projects/MXRoyale/src/main/royale/mx/core/Keyboard.as
new file mode 100644
index 000000000..014a65270
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/core/Keyboard.as
@@ -0,0 +1,1705 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package mx.core
+{
+	/**
+	 *  This class holds constants for special keys
+	 *  See: 
+	 *  See: 
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.8
+	 */
+	public class Keyboard
+	{
+		
+		/***
+		 * [static] Constant associated with the key code value for the A key (65).
+		 */
+		
+		public static const A : uint = 65;
+		
+		/**
+		 * [static] Constant associated with the key code value for the Alternate (Option) key (18).
+		 */
+		public static const ALTERNATE : uint = 18;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for selecting the audio mode.
+		 */
+		public static const AUDIO : uint = 0x01000017;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the B key (66).
+		 */
+		public static const B : uint = 66;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for returning to the previous page in the application.
+		 */
+		public static const BACK : uint = 0x01000016;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the ` key (192).
+		 */
+		public static const BACKQUOTE : uint = 192;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the \ key (220).
+		 */
+		public static const BACKSLASH : uint = 220;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Backspace key (8).
+		 */
+		public static const BACKSPACE : uint = 8;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the blue function key button.
+		 */
+		public static const BLUE : uint = 0x01000003;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the C key (67). 
+		 */
+		public static const C : uint = 67;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Caps Lock key (20).
+		 */
+		public static const CAPS_LOCK : uint = 20;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the channel down button.
+		 */
+		public static const CHANNEL_DOWN : uint = 0x01000005;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the channel up button.
+		 */
+		public static const CHANNEL_UP : uint = 0x01000004;
+		
+		
+		/**
+		 * [static] An array containing all the defined key name constants. 
+		 */
+		public static const CharCodeStrings : Array = null;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the , key (188).
+		 */
+		public static const COMMA : uint = 188;
+		
+		
+		/**
+		 * [static] Constant associated with the Mac command key (15).
+		 */
+		public static const COMMAND : uint = 15;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Control key (17).
+		 */
+		public static const CONTROL : uint = 17;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the D key (68).
+		 */
+		public static const D : uint = 68;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Delete key (46).
+		 */
+		public static const DELETE : uint = 46;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Down Arrow key (40).
+		 */
+		public static const DOWN : uint = 40;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging DVR application mode.
+		 */
+		public static const DVR : uint = 0x01000019;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the E key (69).
+		 */
+		public static const E : uint = 69;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the End key (35).
+		 */
+		public static const END : uint = 35;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Enter key (13).
+		 */
+		public static const ENTER : uint = 13;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the = key (187).
+		 */
+		public static const EQUAL : uint = 187;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Escape key (27).
+		 */
+		public static const ESCAPE : uint = 27;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for exiting the current application mode.
+		 */
+		public static const EXIT : uint = 0x01000015;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F key (70).
+		 */
+		public static const F : uint = 70;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F1 key (112).
+		 */
+		public static const F1 : uint = 112;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F10 key (121).
+		 */
+		public static const F10 : uint = 121;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F11 key (122).
+		 */
+		public static const F11 : uint = 122;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F12 key (123).
+		 */
+		public static const F12 : uint = 123;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F13 key (124).
+		 */
+		public static const F13 : uint = 124;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F14 key (125).
+		 */
+		public static const F14 : uint = 125;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F15 key (126).
+		 */
+		public static const F15 : uint = 126;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F2 key (113).
+		 */
+		public static const F2 : uint = 113;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F3 key (114).
+		 */
+		public static const F3 : uint = 114;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F4 key (115).
+		 */
+		public static const F4 : uint = 115;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F5 key (116).
+		 */
+		public static const F5 : uint = 116;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F6 key (117).
+		 */
+		public static const F6 : uint = 117;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F7 key (118).
+		 */
+		public static const F7 : uint = 118;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F8 key (119).
+		 */
+		public static const F8 : uint = 119;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the F9 key (120).
+		 */
+		public static const F9 : uint = 120;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging fast-forward transport mode.
+		 */
+		public static const FAST_FORWARD : uint = 0x0100000A;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the G key (71).
+		 */
+		public static const G : uint = 71;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the green function key button.
+		 */
+		public static const GREEN : uint = 0x01000001;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging the program guide. 
+		 */
+		public static const GUIDE : uint = 0x01000014;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the H key (72).
+		 */
+		public static const H : uint = 72;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging the help application or context-sensitive help.
+		 */
+		public static const HELP : uint = 0x0100001D;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Home key (36).
+		 */
+		public static const HOME : uint = 36;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the I key (73).
+		 */
+		public static const I : uint = 73;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the info button.
+		 */
+		public static const INFO : uint = 0x01000013;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for cycling inputs.
+		 */
+		public static const INPUT : uint = 0x0100001B;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Insert key (45).
+		 */
+		public static const INSERT : uint = 45;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the J key (74).
+		 */
+		public static const J : uint = 74;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the K key (75).
+		 */
+		public static const K : uint = 75;
+		
+		
+		/**
+		 * [static] The Begin key
+		 */
+		public static const KEYNAME_BEGIN : String = "Begin";
+		
+		
+		/**
+		 * [static] The Break key
+		 */
+		public static const KEYNAME_BREAK : String = "Break";
+		
+		
+		/**
+		 * [static] The Clear Display key
+		 */
+		public static const KEYNAME_CLEARDISPLAY : String = "ClrDsp";
+		
+		
+		/**
+		 * [static] The Clear Line key
+		 */
+		public static const KEYNAME_CLEARLINE : String = "ClrLn";
+		
+		
+		/**
+		 * [static] The Delete key
+		 */
+		public static const KEYNAME_DELETE : String = "Delete";
+		
+		
+		/**
+		 * [static] The Delete Character key
+		 */
+		public static const KEYNAME_DELETECHAR : String = "DelChr";
+		
+		
+		/**
+		 * [static] The Delete Line key
+		 */
+		public static const KEYNAME_DELETELINE : String = "DelLn";
+		
+		
+		/**
+		 * [static] The down arrow
+		 */
+		public static const KEYNAME_DOWNARROW : String = "Down";
+		
+		
+		/**
+		 * [static] The End key
+		 */
+		public static const KEYNAME_END : String = "End";
+		
+		
+		/**
+		 * [static] The Execute key
+		 */
+		public static const KEYNAME_EXECUTE : String = "Exec";
+		
+		
+		/**
+		 * [static] The F1 key
+		 */
+		public static const KEYNAME_F1 : String = "F1";
+		
+		
+		/**
+		 * [static] The F10 key
+		 */
+		public static const KEYNAME_F10 : String = "F10";
+		
+		
+		/**
+		 * [static] The F11 key
+		 */
+		public static const KEYNAME_F11 : String = "F11";
+		
+		
+		/**
+		 * [static] The F12 key
+		 */
+		public static const KEYNAME_F12 : String = "F12";
+		
+		
+		/**
+		 * [static] The F13 key
+		 */
+		public static const KEYNAME_F13 : String = "F13";
+		
+		
+		/**
+		 * [static] The F14 key
+		 */
+		public static const KEYNAME_F14 : String = "F14";
+		
+		
+		/**
+		 * [static] The F15 key
+		 */
+		public static const KEYNAME_F15 : String = "F15";
+		
+		
+		/**
+		 * [static] The F16 key
+		 */
+		public static const KEYNAME_F16 : String = "F16";
+		
+		
+		/**
+		 * [static] The F17 key
+		 */
+		public static const KEYNAME_F17 : String = "F17";
+		
+		
+		/**
+		 * [static] The F18 key
+		 */
+		public static const KEYNAME_F18 : String = "F18";
+		
+		
+		/**
+		 * [static] The F19 key
+		 */
+		public static const KEYNAME_F19 : String = "F19";
+		
+		
+		/**
+		 * [static] The F2 key
+		 */
+		public static const KEYNAME_F2 : String = "F2";
+		
+		
+		/**
+		 * [static] The F20 key
+		 */
+		public static const KEYNAME_F20 : String = "F20";
+		
+		
+		/**
+		 * [static] The F21 key
+		 */
+		public static const KEYNAME_F21 : String = "F21";
+		
+		
+		/**
+		 * [static] The F22 key
+		 */
+		public static const KEYNAME_F22 : String = "F22";
+		
+		
+		/**
+		 * [static] The F23 key
+		 */
+		public static const KEYNAME_F23 : String = "F23";
+		
+		
+		/**
+		 * [static] The F24 key
+		 */
+		public static const KEYNAME_F24 : String = "F24";
+		
+		
+		/**
+		 * [static] The F25 key
+		 */
+		public static const KEYNAME_F25 : String = "F25";
+		
+		
+		/**
+		 * [static] The F26 key
+		 */
+		public static const KEYNAME_F26 : String = "F26";
+		
+		
+		/**
+		 * [static] The F27 key
+		 */
+		public static const KEYNAME_F27 : String = "F27";
+		
+		
+		/**
+		 * [static] The F28 key
+		 */
+		public static const KEYNAME_F28 : String = "F28";
+		
+		
+		/**
+		 * [static] The F29 key
+		 */
+		public static const KEYNAME_F29 : String = "F29";
+		
+		
+		/**
+		 * [static] The F3 key
+		 */
+		public static const KEYNAME_F3 : String = "F3";
+		
+		
+		/**
+		 * [static] The F30 key
+		 */
+		public static const KEYNAME_F30 : String = "F30";
+		
+		
+		/**
+		 * [static] The F31 key
+		 */
+		public static const KEYNAME_F31 : String = "F31";
+		
+		
+		/**
+		 * [static] The F32 key
+		 */
+		public static const KEYNAME_F32 : String = "F32";
+		
+		
+		/**
+		 * [static] The F33 key
+		 */
+		public static const KEYNAME_F33 : String = "F33";
+		
+		
+		/**
+		 * [static] The F34 key
+		 */
+		public static const KEYNAME_F34 : String = "F34";
+		
+		
+		/**
+		 * [static] The F35 key
+		 */
+		public static const KEYNAME_F35 : String = "F35";
+		
+		
+		/**
+		 * [static] The F4 key
+		 */
+		public static const KEYNAME_F4 : String = "F4";
+		
+		
+		/**
+		 * [static] The F5 key
+		 */
+		public static const KEYNAME_F5 : String = "F5";
+		
+		
+		/**
+		 * [static] The F6 key
+		 */
+		public static const KEYNAME_F6 : String = "F6";
+		
+		
+		/**
+		 * [static] The F7 key
+		 */
+		public static const KEYNAME_F7 : String = "F7";
+		
+		
+		/**
+		 * [static] The F8 key
+		 */
+		public static const KEYNAME_F8 : String = "F8";
+		
+		
+		/**
+		 * [static] The F9 key
+		 */
+		public static const KEYNAME_F9 : String = "F9";
+		
+		
+		/**
+		 * [static] The Find key
+		 */
+		public static const KEYNAME_FIND : String = "Find";
+		
+		
+		/**
+		 * [static] The Help key
+		 */
+		public static const KEYNAME_HELP : String = "Help";
+		
+		
+		/**
+		 * [static] The Home key
+		 */
+		public static const KEYNAME_HOME : String = "Home";
+		
+		
+		/**
+		 * [static] The Insert key
+		 */
+		public static const KEYNAME_INSERT : String = "Insert";
+		
+		
+		/**
+		 * [static] The Insert Character key
+		 */
+		public static const KEYNAME_INSERTCHAR : String = "InsChr";
+		
+		
+		/**
+		 * [static] The Insert Line key
+		 */
+		public static const KEYNAME_INSERTLINE : String = "InsLn";
+		
+		
+		/**
+		 * [static] The left arrow
+		 */
+		public static const KEYNAME_LEFTARROW : String = "Left";
+		
+		
+		/**
+		 * [static] The Menu key
+		 */
+		public static const KEYNAME_MENU : String = "Menu";
+		
+		
+		/**
+		 * [static] The Mode Switch key
+		 */
+		public static const KEYNAME_MODESWITCH : String = "ModeSw";
+		
+		
+		/**
+		 * [static] The Next key
+		 */
+		public static const KEYNAME_NEXT : String = "Next";
+		
+		
+		/**
+		 * [static] The Page Down key
+		 */
+		public static const KEYNAME_PAGEDOWN : String = "PgDn";
+		
+		
+		/**
+		 * [static] The Page Up key
+		 */
+		public static const KEYNAME_PAGEUP : String = "PgUp";
+		
+		
+		/**
+		 * [static] The Pause key
+		 */
+		public static const KEYNAME_PAUSE : String = "Pause";
+		
+		
+		/**
+		 * [static] The Play_Pause key
+		 */
+		public static const KEYNAME_PLAYPAUSE : String = "PlayPause";
+		
+		
+		/**
+		 * [static] The Previous key
+		 */
+		public static const KEYNAME_PREV : String = "Prev";
+		
+		
+		/**
+		 * [static] The Print key
+		 */
+		public static const KEYNAME_PRINT : String = "Print";
+		
+		
+		/**
+		 * [static] The Print Screen
+		 */
+		public static const KEYNAME_PRINTSCREEN : String = "PrntScrn";
+		
+		
+		/**
+		 * [static] The Redo key
+		 */
+		public static const KEYNAME_REDO : String = "Redo";
+		
+		
+		/**
+		 * [static] The Reset key
+		 */
+		public static const KEYNAME_RESET : String = "Reset";
+		
+		
+		/**
+		 * [static] The right arrow
+		 */
+		public static const KEYNAME_RIGHTARROW : String = "Right";
+		
+		
+		/**
+		 * [static] The Scroll Lock key
+		 */
+		public static const KEYNAME_SCROLLLOCK : String = "ScrlLck";
+		
+		
+		/**
+		 * [static] The Select key
+		 */
+		public static const KEYNAME_SELECT : String = "Select";
+		
+		
+		/**
+		 * [static] The Stop key
+		 */
+		public static const KEYNAME_STOP : String = "Stop";
+		
+		
+		/**
+		 * [static] The System Request key
+		 */
+		public static const KEYNAME_SYSREQ : String = "SysReq";
+		
+		
+		/**
+		 * [static] The System key
+		 */
+		public static const KEYNAME_SYSTEM : String = "Sys";
+		
+		
+		/**
+		 * [static] The Undo key
+		 */
+		public static const KEYNAME_UNDO : String = "Undo";
+		
+		
+		/**
+		 * [static] The up arrow
+		 */
+		public static const KEYNAME_UPARROW : String = "Up";
+		
+		
+		/**
+		 * [static] The User key
+		 */
+		public static const KEYNAME_USER : String = "User";
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the L key (76).
+		 */
+		public static const L : uint = 76;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for watching the last channel or show watched.
+		 */
+		public static const LAST : uint = 0x01000011;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Left Arrow key (37).
+		 */
+		public static const LEFT : uint = 37;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the [ key (219).
+		 */
+		public static const LEFTBRACKET : uint = 219;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for returning to live [position in broadcast].
+		 */
+		public static const LIVE : uint = 0x01000010;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the M key (77).
+		 */
+		public static const M : uint = 77;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging the "Master Shell" (e.g. TiVo or other vendor button).
+		 */
+		public static const MASTER_SHELL : uint = 0x0100001E;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging the menu.
+		 */
+		public static const MENU : uint = 0x01000012;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the - key (189).
+		 */
+		public static const MINUS : uint = 189;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the N key (78).
+		 */
+		public static const N : uint = 78;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for skipping to next track or chapter.
+		 */
+		public static const NEXT : uint = 0x0100000E;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 0 key (48).
+		 */
+		public static const NUMBER_0 : uint = 48;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 1 key (49).
+		 */
+		public static const NUMBER_1 : uint = 49;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 2 key (50).
+		 */
+		public static const NUMBER_2 : uint = 50;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 3 key (51).
+		 */
+		public static const NUMBER_3 : uint = 51;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 4 key (52).
+		 */
+		public static const NUMBER_4 : uint = 52;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 5 key (53).
+		 */
+		public static const NUMBER_5 : uint = 53;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 6 key (54).
+		 */
+		public static const NUMBER_6 : uint = 54;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 7 key (55).
+		 */
+		public static const NUMBER_7 : uint = 55;
+		
+		/**
+		 * [static] Constant associated with the key code value for the 8 key (56).
+		 */
+		public static const NUMBER_8 : uint = 56;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the 9 key (57).
+		 */
+		public static const NUMBER_9 : uint = 57;
+		
+		
+		/**
+		 * [static] Constant associated with the pseudo-key code for the the number pad (21).
+		 */
+		public static const NUMPAD : uint = 21;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 0 key on the number pad (96).
+		 */
+		public static const NUMPAD_0 : uint = 96;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 1 key on the number pad (97).
+		 */
+		public static const NUMPAD_1 : uint = 97;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 2 key on the number pad (98).
+		 */
+		public static const NUMPAD_2 : uint = 98;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 3 key on the number pad (99).
+		 */
+		public static const NUMPAD_3 : uint = 99;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 4 key on the number pad (100).
+		 */
+		public static const NUMPAD_4 : uint = 100;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 5 key on the number pad (101).
+		 */
+		public static const NUMPAD_5 : uint = 101;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 6 key on the number pad (102).
+		 */
+		public static const NUMPAD_6 : uint = 102;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 7 key on the number pad (103).
+		 */
+		public static const NUMPAD_7 : uint = 103;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 8 key on the number pad (104).
+		 */
+		public static const NUMPAD_8 : uint = 104;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the number 9 key on the number pad (105).
+		 */
+		public static const NUMPAD_9 : uint = 105;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the addition key on the number pad (107).
+		 */
+		public static const NUMPAD_ADD : uint = 107;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the decimal key on the number pad (110).
+		 */
+		public static const NUMPAD_DECIMAL : uint = 110;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the division key on the number pad (111).
+		 */
+		public static const NUMPAD_DIVIDE : uint = 111;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Enter key on the number pad (108).
+		 */
+		public static const NUMPAD_ENTER : uint = 108;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the multiplication key on the number pad (106).
+		 */
+		public static const NUMPAD_MULTIPLY : uint = 106;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the subtraction key on the number pad (109).
+		 */
+		public static const NUMPAD_SUBTRACT : uint = 109;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the O key (79).
+		 */
+		public static const O : uint = 79;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the P key (80).
+		 */
+		public static const P : uint = 80;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Page Down key (34).
+		 */
+		public static const PAGE_DOWN : uint = 34;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Page Up key (33).
+		 */
+		public static const PAGE_UP : uint = 33;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for pausing transport mode.
+		 */
+		public static const PAUSE : uint = 0x01000008;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the .
+		 */
+		public static const PERIOD : uint = 190;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging play transport mode.
+		 */
+		public static const PLAY : uint = 0x01000007;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging play/pause transport mode.
+		 */
+		public static const PLAY_PAUSE : uint = 0x01000020;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for skipping to previous track or chapter.
+		 */
+		public static const PREVIOUS : uint = 0x0100000F;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Q key (81).
+		 */
+		public static const Q : uint = 81;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the ' key (222).
+		 */
+		public static const QUOTE : uint = 222;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the R key (82).
+		 */
+		public static const R : uint = 82;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for recording or engaging record transport mode.
+		 */
+		public static const RECORD : uint = 0x01000006;
+		
+		
+		/**
+		 * [static] Red function key button.
+		 */
+		public static const RED : uint = 0x01000000;
+		
+			
+			/**
+			 * [static] Constant associated with the key code value for the button for engaging rewind transport mode.
+			 */
+			public static const REWIND : uint = 0x0100000B;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Right Arrow key (39).
+		 */
+		public static const RIGHT : uint = 39;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the ] key (221).
+		 */
+		public static const RIGHTBRACKET : uint = 221;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the S key (83).
+		 */
+		public static const S : uint = 83;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for the search button.
+		 */
+		public static const SEARCH : uint = 0x0100001F;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the ; key (186).
+		 */
+		public static const SEMICOLON : uint = 186;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging the setup application or menu.
+		 */
+		public static const SETUP : uint = 0x0100001C;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Shift key (16).
+		 */
+		public static const SHIFT : uint = 16;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging quick skip backward (usually 7-10 seconds).
+		 */
+		public static const SKIP_BACKWARD : uint = 0x0100000D;
+		
+			
+			/**
+			 * [static] Constant associated with the key code value for the button for engaging quick skip ahead (usually 30 seconds).
+			 */
+			public static const SKIP_FORWARD : uint = 0x0100000C;
+		
+			
+			/**
+			 * [static] Constant associated with the key code value for the / key (191).
+			 */
+			public static const SLASH : uint = 191;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Spacebar (32).
+		 */
+		public static const SPACE : uint = 32;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for stopping transport mode.
+		 */
+		public static const STOP : uint = 0x01000009;
+		
+		
+		/**
+		 * [static] The OS X Unicode Begin constant
+		 */
+		public static const STRING_BEGIN : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Break constant
+		 */
+		public static const STRING_BREAK : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Clear Display constant
+		 */
+		public static const STRING_CLEARDISPLAY : String = "";
+		
+		/**
+		 * 
+		 */
+		
+		/**
+		 * [static] The OS X Unicode Clear Line constant
+		 */
+		public static const STRING_CLEARLINE : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Delete constant
+		 */
+		public static const STRING_DELETE : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Delete Character constant
+		 */
+		public static const STRING_DELETECHAR : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Delete Line constant
+		 */
+		public static const STRING_DELETELINE : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode down arrow constant
+		 */
+		public static const STRING_DOWNARROW : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode End constant
+		 */
+		public static const STRING_END : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Execute constant
+		 */
+		public static const STRING_EXECUTE : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F1 constant
+		 */
+		public static const STRING_F1 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F10 constant
+		 */
+		public static const STRING_F10 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F11 constant
+		 */
+		public static const STRING_F11 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F12 constant
+		 */
+		public static const STRING_F12 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F13 constant
+		 */
+		public static const STRING_F13 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F14 constant
+		 */
+		public static const STRING_F14 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F15 constant
+		 */
+		public static const STRING_F15 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F16 constant
+		 */
+		public static const STRING_F16 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F17 constant
+		 */
+		public static const STRING_F17 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F18 constant
+		 */
+		public static const STRING_F18 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F19 constant
+		 */
+		public static const STRING_F19 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F2 constant
+		 */
+		public static const STRING_F2 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F20 constant
+		 */
+		public static const STRING_F20 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F21 constant
+		 */
+		public static const STRING_F21 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F22 constant
+		 */
+		public static const STRING_F22 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F23 constant
+		 */
+		public static const STRING_F23 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F24 constant
+		 */
+		public static const STRING_F24 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F25 constant
+		 */
+		public static const STRING_F25 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F26 constant
+		 */
+		public static const STRING_F26 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F27 constant
+		 */
+		public static const STRING_F27 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F28 constant
+		 */
+		public static const STRING_F28 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F29 constant
+		 */
+		public static const STRING_F29 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F3 constant
+		 */
+		public static const STRING_F3 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F30 constant
+		 */
+		public static const STRING_F30 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F31 constant
+		 */
+		public static const STRING_F31 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F32 constant
+		 */
+		public static const STRING_F32 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F33 constant
+		 */
+		public static const STRING_F33 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F34 constant
+		 */
+		public static const STRING_F34 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F35 constant
+		 */
+		public static const STRING_F35 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F4 constant
+		 */
+		public static const STRING_F4 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F5 constant
+		 */
+		public static const STRING_F5 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F6 constant
+		 */
+		public static const STRING_F6 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F7 constant
+		 */
+		public static const STRING_F7 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F8 constant
+		 */
+		public static const STRING_F8 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode F9 constant
+		 */
+		public static const STRING_F9 : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Find constant
+		 */
+		public static const STRING_FIND : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Help constant
+		 */
+		public static const STRING_HELP : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Home constant
+		 */
+		public static const STRING_HOME : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Insert constant
+		 */
+		public static const STRING_INSERT : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Insert Character constant
+		 */
+		public static const STRING_INSERTCHAR : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Insert Line constant
+		 */
+		public static const STRING_INSERTLINE : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode left arrow constant
+		 */
+		public static const STRING_LEFTARROW : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Menu constant
+		 */
+		public static const STRING_MENU : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Mode Switch constant
+		 */
+		public static const STRING_MODESWITCH : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Next constant
+		 */
+		public static const STRING_NEXT : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Page Down constant
+		 */
+		public static const STRING_PAGEDOWN : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Page Up constant
+		 */
+		public static const STRING_PAGEUP : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Pause constant
+		 */
+		public static const STRING_PAUSE : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Previous constant
+		 */
+		public static const STRING_PREV : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Print constant
+		 */
+		public static const STRING_PRINT : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Print Screen constant
+		 */
+		public static const STRING_PRINTSCREEN : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Redo constant
+		 */
+		public static const STRING_REDO : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Reset constant
+		 */
+		public static const STRING_RESET : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode right arrow constant
+		 */
+		public static const STRING_RIGHTARROW : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Scroll Lock constant
+		 */
+		public static const STRING_SCROLLLOCK : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Select constant
+		 */
+		public static const STRING_SELECT : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Stop constant
+		 */
+		public static const STRING_STOP : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode System Request constant
+		 */
+		public static const STRING_SYSREQ : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode System constant
+		 */
+		public static const STRING_SYSTEM : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode Undo constant
+		 */
+		public static const STRING_UNDO : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode up arrow constant
+		 */
+		public static const STRING_UPARROW : String = "";
+		
+		
+		/**
+		 * [static] The OS X Unicode User constant
+		 */
+		public static const STRING_USER : String = "";
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for toggling subtitles.
+		 */
+		public static const SUBTITLE : uint = 0x01000018;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the T key (84).
+		 */
+		public static const T : uint = 84;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Tab key (9).
+		 */
+		public static const TAB : uint = 9;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the U key (85).
+		 */
+		public static const U : uint = 85;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Up Arrow key (38).
+		 */
+		public static const UP : uint = 38;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the V key (86).
+		 */
+		public static const V : uint = 86;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the button for engaging video-on-demand.
+		 */
+		public static const VOD : uint = 0x0100001A;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the W key (87).
+		 */
+		public static const W : uint = 87;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the X key (88).
+		 */
+		public static const X : uint = 88;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Y key (89).
+		 */
+		public static const Y : uint = 89;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the yellow function key button.
+		 */
+		public static const YELLOW : uint = 0x01000002;
+		
+		
+		/**
+		 * [static] Constant associated with the key code value for the Z key (90).
+		 */
+		public static const Z : uint = 90;
+		
+		
+	}
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/core/LayoutDirection.as b/frameworks/projects/MXRoyale/src/main/royale/mx/core/LayoutDirection.as
new file mode 100644
index 000000000..fa9cd7a18
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/core/LayoutDirection.as
@@ -0,0 +1,77 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.core
+{    
+    /**
+     *  The LayoutDirection class defines the constant values
+     *  for the <code>layoutDirection</code> style of an IStyleClient and the 
+     *  <code>layoutDirection</code> property of an ILayoutDirectionElement.
+     *  
+     *  Left-to-right layoutDirection is typically used with Latin-style 
+     *  scripts. Right-to-left layoutDirection is used with scripts such as 
+     *  Arabic or Hebrew.
+     * 
+     *  If an IStyleClient, set the layoutDirection style to undefined to
+     *  inherit the layoutDirection from its ancestor.
+     * 
+     *  If an ILayoutDirectionElement, set the layoutDirection property to null to
+     *  inherit the layoutDirection from its ancestor.
+     * 
+     *  @see mx.styles.IStyleClient
+     *  @see mx.core.ILayoutDirectionElement
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.1
+     */
+    public final class LayoutDirection
+    {
+        // include "Version.as";
+        
+        //--------------------------------------------------------------------------
+        //
+        //  Class constants
+        //
+        //--------------------------------------------------------------------------
+        
+        /**
+         *  Specifies left-to-right layout direction for a style client or a
+         *  visual element.
+         *  
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 2.0
+         *  @productversion Flex 4.1
+         */
+        public static const LTR:String = "ltr";
+        
+        /**
+         *  Specifies right-to-left layout direction for a style client or a
+         *  visual element.
+         * 
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 2.0
+         *  @productversion Flex 4.1
+         */
+        public static const RTL:String = "rtl";
+    }
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/core/UIComponentGlobals.as b/frameworks/projects/MXRoyale/src/main/royale/mx/core/UIComponentGlobals.as
new file mode 100644
index 000000000..9e962cec8
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/core/UIComponentGlobals.as
@@ -0,0 +1,154 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.core
+{
+/*
+import mx.managers.ILayoutManager;
+import flash.display.InteractiveObject;
+import flash.geom.Matrix;
+use namespace mx_internal;
+*/
+
+import mx.core.mx_internal;
+import org.apache.royale.geom.Matrix;
+	
+	
+/**
+*  @private
+*/
+public class UIComponentGlobals
+{
+    /**
+     *  @private
+     *  A reference to the sole instance of the LayoutManager
+     *  used by all components.
+     *
+     *  <p>This property is set in the constructor of the Application class.
+     *  If you need to override or replace LayoutManager,
+     *  set UIComponent.layoutManager in your application's constructor
+     *  after calling super().</p>
+     */
+    // mx_internal static var layoutManager:ILayoutManager;
+
+    /**
+     *  @private
+     *  When this variable is non-zero, no methods queued
+     *  by the <code>callLater()</code> method get invoked.
+     *  This is used to allow short effects to play without interruption.
+     *  This counter is incremented by suspendBackgroundProcessing(),
+     *  decremented by resumeBackgroundProcessing(), and checked by
+     *  callLaterDispatcher().
+     */
+    mx_internal static var callLaterSuspendCount:int = 0;
+
+    /**
+     *  @private
+     *  There is a bug (139390) where setting focus from within callLaterDispatcher
+     *  screws up the ActiveX player.  We defer focus until enterframe.
+     */
+    mx_internal static var callLaterDispatcherCount:int = 0;
+
+    /**
+     *  @private
+     *  There is a bug (139390) where setting focus from within callLaterDispatcher
+     *  screws up the ActiveX player.  We defer focus until enterframe.
+     */
+    // mx_internal static var nextFocusObject:InteractiveObject;
+
+    /**
+     *  @private
+     *  This single Matrix is used to pass information from the
+     *  horizontalGradientMatrix() or verticalGradientMatrix()
+     *  utility methods to the drawRoundRect() method.
+     *  Each call to horizontalGradientMatrix() or verticalGradientMatrix()
+     *  simply calls createGradientBox() to stuff this Matrix with new values.
+     *  We can keep restuffing the same Matrix object because these utility
+     *  methods are only used inside a call to drawRoundRect()
+     *  and the Matrix isn't needed after drawRoundRect() returns.
+     */
+    mx_internal static var tempMatrix:Matrix = new Matrix();
+
+    /**
+     *  @private
+     *  A global flag that can be read by any component to determine
+     *  whether it is currently executing in the context of a design
+     *  tool such as Flash Builder's design view.  Most components will
+     *  never need to check this flag, but if a component needs to
+     *  have different behavior at design time than at runtime, then it
+     *  can check this flag.
+     */
+    mx_internal static var designTime:Boolean = false;
+
+    /**
+     *  A global flag that can be read by any component to determine
+     *  whether it is currently executing in the context of a design
+     *  tool such as Flash Builder's design view.  Most components will
+     *  never need to check this flag, but if a component needs to
+     *  have different behavior at design time than at runtime, then it
+     *  can check this flag.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function get designMode():Boolean
+    {
+        return false; //designTime;
+    }
+
+    /**
+     *  @private
+     */
+    public static function set designMode(value:Boolean):void
+    {
+        //designTime = value;
+    }
+
+    /**
+     *  @private
+     */
+    private static var _catchCallLaterExceptions:Boolean = false;
+
+    /**
+     *  A global flag that can is used to catch unhandled exceptions
+     *  during execution of methods executed via callLater
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function get catchCallLaterExceptions():Boolean
+    {
+        return _catchCallLaterExceptions;
+    }
+
+    /**
+     *  @private
+     */
+    public static function set catchCallLaterExceptions(value:Boolean):void
+    {
+        _catchCallLaterExceptions = value;
+    }
+}
+
+}
+
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/DateBase.as b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/DateBase.as
new file mode 100644
index 000000000..dac2ab1b5
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/DateBase.as
@@ -0,0 +1,703 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.formatters
+{
+
+// import flash.events.Event;
+import org.apache.royale.events.Event;
+
+import mx.core.mx_internal;
+import mx.resources.IResourceManager;
+import mx.resources.ResourceManager;
+
+use namespace mx_internal;
+
+// [ResourceBundle("formatters")]
+// [ResourceBundle("SharedResources")]
+
+/**
+ *  The DateBase class contains the localized string information
+ *  used by the mx.formatters.DateFormatter class and the parsing function
+ *  that renders the pattern.
+ *  This is a helper class for the DateFormatter class that is not usually
+ *  used independently.
+ *
+ *  @see mx.formatters.DateFormatter
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class DateBase
+{
+    // include "../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class variables
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private static var initialized:Boolean = false;
+
+    /**
+     *  @private
+     *  Storage for the resourceManager getter.
+     *  This gets initialized on first access,
+     *  not at static initialization time, in order to ensure
+     *  that the Singleton registry has already been initialized.
+     */
+    private static var _resourceManager:IResourceManager;
+    
+    /**
+     *  @private
+     *  A reference to the object which manages
+     *  all of the application's localized resources.
+     *  This is a singleton instance which implements
+     *  the IResourceManager interface.
+     */
+    private static function get resourceManager():IResourceManager
+    {
+        if (!_resourceManager)
+            _resourceManager = ResourceManager.getInstance();
+
+        return _resourceManager;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Class properties
+    //
+    //--------------------------------------------------------------------------
+        
+    //----------------------------------
+    //  dayNamesLong
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the dayNamesLong property.
+     */
+    private static var _dayNamesLong:Array; /* of String */
+    
+    /**
+     *  @private
+     */
+    private static var dayNamesLongOverride:Array; /* of String */
+
+    /**
+     *  Long format of day names.
+     * 
+     *  @default ["Sunday", "Monday", "Tuesday", "Wednesday",
+     *  "Thursday", "Friday", "Saturday"]
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function get dayNamesLong():Array /* of String */
+    {
+        initialize();
+
+        return _dayNamesLong;
+    }
+
+    /**
+     *  @private
+     */
+    public static function set dayNamesLong(value:Array /* of String*/):void
+    {
+        dayNamesLongOverride = value;
+
+        _dayNamesLong = value != null ?
+                        value :
+                        resourceManager.getStringArray(
+                            "SharedResources", "dayNames");
+    }
+        
+    //----------------------------------
+    //  dayNamesShort
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the dayNamesShort property.
+     */
+    private static var _dayNamesShort:Array; /* of String */
+    
+    /**
+     *  @private
+     */
+    private static var dayNamesShortOverride:Array; /* of String */
+
+    /**
+     *  Short format of day names.
+     * 
+     *  @default ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function get dayNamesShort():Array /* of String */
+    {
+        initialize();
+
+        return _dayNamesShort;
+    }
+
+    /**
+     *  @private
+     */
+    public static function set dayNamesShort(value:Array /* of String*/):void
+    {
+        dayNamesShortOverride = value;
+
+        _dayNamesShort = value != null ?
+                         value :
+                         resourceManager.getStringArray(
+                             "formatters", "dayNamesShort");
+    }
+    
+    //----------------------------------
+    //  defaultStringKey
+    //----------------------------------
+
+    /**
+     *  @private
+     */     
+    mx_internal static function get defaultStringKey():Array /* of String */
+    {
+        initialize();
+
+        return monthNamesLong.concat(timeOfDay);
+    }
+    
+    //----------------------------------
+    //  monthNamesLong
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the monthNamesLong property.
+     */
+    private static var _monthNamesLong:Array; /* of String */
+    
+    /**
+     *  @private
+     */
+    private static var monthNamesLongOverride:Array; /* of String */
+
+    /**
+     *  Long format of month names.
+     *
+     *  @default ["January", "February", "March", "April", "May", "June", 
+     *  "July", "August", "September", "October", "November", "December"].
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function get monthNamesLong():Array /* of String */
+    {
+        initialize();
+
+        return _monthNamesLong;
+    }
+
+    /**
+     *  @private
+     */
+    public static function set monthNamesLong(value:Array /* of String*/):void
+    {
+        monthNamesLongOverride = value;
+
+        _monthNamesLong = value != null ?
+                          value :
+                          resourceManager.getStringArray(
+                              "SharedResources", "monthNames");
+
+        if (value == null)
+        {
+            // Currently there is no way to get a null 
+            // string from resourceBundles using getString
+            // Hence monthSymbol is a space in English, but
+            // we actually want it to be a null string.
+            var monthSymbol:String = resourceManager.getString(
+                "SharedResources", "monthSymbol");
+            if (monthSymbol != " ")
+            {
+                // _monthNamesLong will be null if there are no resources.
+                var n:int = _monthNamesLong ? _monthNamesLong.length : 0;
+                for (var i:int = 0; i < n; i++)
+                {
+                    _monthNamesLong[i] += monthSymbol;
+                }
+            }
+        }
+    }
+                
+    //----------------------------------
+    //  monthNamesShort
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the monthNamesShort property.
+     */
+    private static var _monthNamesShort:Array; /* of String */
+    
+    /**
+     *  @private
+     */
+    private static var monthNamesShortOverride:Array; /* of String */
+
+    /**
+     *  Short format of month names.
+     *
+     *  @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
+     *  "Jul", "Aug", "Sep", "Oct","Nov", "Dec"]
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function get monthNamesShort():Array /* of String */
+    {
+        initialize();
+
+        return _monthNamesShort;
+    }
+
+    /**
+     *  @private
+     */
+    public static function set monthNamesShort(value:Array /* of String*/):void
+    {
+        monthNamesShortOverride = value;
+
+        _monthNamesShort = value != null ?
+                           value :
+                           resourceManager.getStringArray(
+                               "formatters", "monthNamesShort");
+        if (value == null)
+        {
+            // Currently there is no way to get a null 
+            // string from resourceBundles using getString
+            // Hence monthSymbol is a space in English, but
+            // we actually want it to be a null string.
+            var monthSymbol:String = resourceManager.getString(
+                "SharedResources", "monthSymbol");
+            if (monthSymbol != " ")
+            {
+                // _monthNamesShort will be null if there are no resources.
+                var n:int = _monthNamesShort ? _monthNamesShort.length : 0;
+                for (var i:int = 0; i < n; i++)
+                {
+                    _monthNamesShort[i] += monthSymbol;
+                }
+            }
+        }
+    }
+            
+    //----------------------------------
+    //  timeOfDay
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the timeOfDay property.
+     */
+    private static var _timeOfDay:Array; /* of String */
+    
+    /**
+     *  @private
+     */
+    private static var timeOfDayOverride:Array; /* of String */
+
+    /**
+     *  Time of day names.
+     * 
+     *  @default ["AM", "PM"]
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static function get timeOfDay():Array /* of String */ 
+    {
+        initialize();
+
+        return _timeOfDay;
+    }
+
+    /**
+     *  @private
+     */
+    public static function set timeOfDay(value:Array /* of String */):void
+    {
+        timeOfDayOverride = value;
+
+        var am:String = resourceManager.getString("formatters", "am");
+        var pm:String = resourceManager.getString("formatters", "pm");
+
+        _timeOfDay = value != null ? value : [ am, pm ];
+    }
+
+	/**
+	 *  @private
+	 */
+	private static var _timezoneName:String = "GMT";
+	
+	/**
+	 *  Timezone name.
+	 * 
+	 *  @default "GMT"
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion  Apache Flex 4.10
+	 */
+	public static function get timezoneName():String
+	{
+		return _timezoneName;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public static function set timezoneName(value:String):void
+	{
+		_timezoneName = value;
+	}
+	
+	/**
+	 *  @private
+	 */
+	private static var _timezoneHourMinuteSeperator:String = ":";
+	
+	/**
+	 *  Timezone hour/minute seperator.
+	 * 
+	 *  @default ":"
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Apache Flex 4.10
+	 */
+	public static function get timezoneHourMinuteSeperator():String
+	{
+		return _timezoneHourMinuteSeperator;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public static function set timezoneHourMinuteSeperator(value:String):void
+	{
+		_timezoneHourMinuteSeperator = value;
+	}
+	
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private    
+     */
+    private static function initialize():void
+    {
+        if (!initialized)
+        {
+            // Register as a weak listener for "change" events
+            // from ResourceManager.
+            /*resourceManager.addEventListener(
+                Event.CHANGE, static_resourceManager_changeHandler,
+                false, 0, true);*/
+
+            static_resourcesChanged();
+
+            initialized = true;
+        }
+    }
+
+    /**
+     *  @private    
+     */
+    private static function static_resourcesChanged():void
+    {
+        dayNamesLong = dayNamesLongOverride;
+        dayNamesShort = dayNamesShortOverride;
+        monthNamesLong = monthNamesLongOverride;
+        monthNamesShort = monthNamesShortOverride;
+        timeOfDay = timeOfDayOverride;
+    }
+
+    /**
+     *  @private
+     *  Parses token objects and renders the elements of the formatted String.
+     *  For details about token objects, see StringFormatter.
+     *
+     *  @param date Date object.
+     *
+     *  @param tokenInfo Array object that contains token object descriptions.
+     *
+     *  @return Formatted string.
+     */
+    mx_internal static function extractTokenDate(date:Date,
+                                            tokenInfo:Object):String
+    {
+        initialize();
+
+        var result:String = "";
+        
+        var key:int = int(tokenInfo.end) - int(tokenInfo.begin);
+        
+        var day:int;
+        var hours:int;
+        
+        switch (tokenInfo.token)
+        {
+            case "Y":
+            {
+                // year
+                var year:String = date.getFullYear().toString();
+                if (key < 3)
+                    return year.substr(2);
+                else if (key > 4)
+                    return setValue(Number(year), key);
+                else
+                    return year;
+            }
+
+            case "M":
+            {
+                // month in year
+                var month:int = int(date.getMonth());
+                if (key < 3)
+                {
+                    month++; // zero based
+                    result += setValue(month, key);
+                    return result;
+                }
+                else if (key == 3)
+                {
+                    return monthNamesShort[month];
+                }
+                else
+                {
+                    return monthNamesLong[month];
+                }
+            }
+
+            case "D":
+            {
+                // day in month
+                day = int(date.getDate());
+                result += setValue(day, key);
+                return result;
+            }
+
+            case "E":
+            {
+                // day in the week
+                day = int(date.getDay());
+                if (key < 3)
+                {
+                    result += setValue(day, key);
+                    return result;
+                }
+                else if (key == 3)
+                {
+                    return dayNamesShort[day];
+                }
+                else
+                {
+                    return dayNamesLong[day];
+                }
+            }
+
+            case "A":
+            {
+                // am/pm marker
+                hours = int(date.getHours());
+                if (hours < 12)
+                    return timeOfDay[0];
+                else
+                    return timeOfDay[1];
+            }
+
+            case "H":
+            {
+                // hour in day (1-24)
+                hours = int(date.getHours());
+                if (hours == 0)
+                    hours = 24;
+                result += setValue(hours, key);
+                return result;
+            }
+
+            case "J":
+            {
+                // hour in day (0-23)
+                hours = int(date.getHours());
+                result += setValue(hours, key);
+                return result;
+            }
+
+            case "K":
+            {
+                // hour in am/pm (0-11)
+                hours = int(date.getHours());
+                if (hours >= 12)
+                    hours = hours - 12;
+                result += setValue(hours, key);
+                return result;
+            }
+
+            case "L":
+            {
+                // hour in am/pm (1-12)
+                hours = int(date.getHours());
+                if (hours == 0)
+                    hours = 12;
+                else if (hours > 12)
+                    hours = hours - 12;
+                result += setValue(hours, key);
+                return result;
+            }
+
+            case "N":
+            {
+                // minutes in hour
+                var mins:int = int(date.getMinutes());
+                result += setValue(mins, key);
+                return result;
+            }
+
+            case "S":
+            {
+                // seconds in minute
+                var sec:int = int(date.getSeconds());
+                result += setValue(sec, key);
+                return result;
+            }
+            
+			case "Q":
+			{
+				// milliseconds in second
+				var ms:int = int(date.getMilliseconds());
+				result += setValue(ms, key);
+				return result;
+			}
+				
+			case "Z":
+			{
+				// timezone offset
+				result += timezoneName;
+				return result;
+			}
+				
+			case "O":
+			{
+				// timezone offset
+				var offset:int = -1 * int(date.timezoneOffset);
+				hours = offset/60;
+				mins = offset - hours*60;
+				var tzStr:String = "";
+				
+				if (key <= 2 && mins == 0)
+					tzStr += setValue(hours, key);
+				else
+					tzStr += setValue(hours, key-2)
+						+ timezoneHourMinuteSeperator 
+						+ setValue(mins, 2);
+					
+				if (offset >= 0)
+					tzStr = "+" + tzStr;
+				
+				result += tzStr;
+				
+				return result;
+			}
+        }
+
+        return result;
+    }
+
+    /**
+     *  @private
+     *  Makes a given length of digits longer by padding with zeroes.
+     *
+     *  @param value Value to pad.
+     *
+     *  @param key Length of the string to pad.
+     *
+     *  @return Formatted string.
+     */
+    private static function setValue(value:Object, key:int):String
+    {
+        var result:String = "";
+
+        var vLen:int = value.toString().length;
+        if (vLen < key)
+        {
+            var n:int = key - vLen;
+            for (var i:int = 0; i < n; i++)
+            {
+                result += "0"
+            }
+        }
+
+        result += value.toString();
+
+        return result;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class event handlers
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private static function static_resourceManager_changeHandler(event:Event):void
+    {
+        static_resourcesChanged();
+    }
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/managers/ILayoutManagerClient.as b/frameworks/projects/MXRoyale/src/main/royale/mx/managers/ILayoutManagerClient.as
new file mode 100644
index 000000000..ae775fe57
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/managers/ILayoutManagerClient.as
@@ -0,0 +1,212 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.managers
+{
+
+// import flash.events.IEventDispatcher;
+import org.apache.royale.events.IEventDispatcher;
+import mx.core.mx_internal;
+
+use namespace mx_internal;
+
+/**
+ *  The ILayoutManagerClient interface defines the interface 
+ *  that a component must implement to participate in the 
+ *  LayoutManager's commit/measurement/layout sequence.  
+ *
+ *  <p>Objects that implement this interface can be passed to the
+ *  LayoutManager's <code>invalidateProperties()</code> method.
+ *  When the LayoutManager reaches the commit properties phase,
+ *  the LayoutManager invokes this object's <code>validateProperties()</code>
+ *  method.</p>
+ *
+ *  <p>Similarly, if an object is passed to the LayoutManager's
+ *  <code>invalidateSize()</code> method, then the LayoutManager
+ *  calls that object's <code>validateSize()</code> method
+ *  during its measurement phase, and if an object is passed
+ *  to LayoutManager's <code>invalidateDisplayList()</code> method,
+ *  then the LayoutManager  calls its <code>validateDisplayList()</code> method 
+ *  during the layout phase.</p>
+ *
+ *  <p>The ILayoutManagerClient interface is implemented by the UIComponent 
+ *  and ProgrammaticSkin classes.</p>
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public interface ILayoutManagerClient extends IEventDispatcher
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  initialized
+    //----------------------------------
+
+    /**
+     *  A flag that determines if an object has been through all three phases
+     *  of layout validation (provided that any were required)
+     *  This flag should only be modified by the LayoutManager.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    function get initialized():Boolean;
+    
+    /**
+     *  @private
+     */
+    function set initialized(value:Boolean):void;
+
+    //----------------------------------
+    //  nestLevel
+    //----------------------------------
+
+    /**
+     *  The top-level SystemManager has a nestLevel of 1.
+     *  Its immediate children (the top-level Application and any pop-up
+     *  windows) have a <code>nestLevel</code> of 2.
+     *  Their children have a <code>nestLevel</code> of 3, and so on.  
+     *
+     *  The <code>nestLevel</code> is used to sort ILayoutManagerClients
+     *  during the measurement and layout phases.
+     *  During the commit phase, the LayoutManager commits properties on clients
+     *  in order of increasing <code>nestLevel</code>, so that an object's
+     *  children have already had their properties committed before Flex 
+     *  commits properties on the object itself.
+     *  During the measurement phase, the LayoutManager measures clients
+     *  in order of decreasing <code>nestLevel</code>, so that an object's
+     *  children have already been measured before Flex measures
+     *  the object itself.
+     *  During the layout phase, the LayoutManager lays out clients
+     *  in order of increasing <code>nestLevel</code>, so that an object
+     *  has a chance to set the sizes of its children before the child
+     *  objects are asked to position and size their children.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    function get nestLevel():int;
+    
+    /**
+     *  @private
+     */
+    function set nestLevel(value:int):void;
+
+    //----------------------------------
+    //  processedDescriptors
+    //----------------------------------
+
+    /**
+     *  @copy mx.core.UIComponent#processedDescriptors
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    function get processedDescriptors():Boolean;
+    
+    /**
+     *  @private
+     */
+    function set processedDescriptors(value:Boolean):void;
+
+    //----------------------------------
+    //  updateCompletePendingFlag
+    //----------------------------------
+
+    /**
+     *  A flag that determines if an object is waiting to have its
+     *  <code>updateComplete</code> event dispatched.
+     *  This flag should only be modified by the LayoutManager.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    function get updateCompletePendingFlag():Boolean;
+    
+    /**
+     *  @private
+     */
+    function set updateCompletePendingFlag(value:Boolean):void;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Validates the properties of a component.
+     *  If the <code>LayoutManager.invalidateProperties()</code> method is called with
+     *  this ILayoutManagerClient, then the <code>validateProperties()</code> method
+     *  is called when it's time to commit property values.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    function validateProperties():void;
+    
+    /**
+     *  Validates the measured size of the component
+     *  If the <code>LayoutManager.invalidateSize()</code> method is called with
+     *  this ILayoutManagerClient, then the <code>validateSize()</code> method
+     *  is called when it's time to do measurements.
+     *
+     *  @param recursive If <code>true</code>, call this method
+     *  on the objects children.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    function validateSize(recursive:Boolean = false):void;
+    
+    /**
+     *  Validates the position and size of children and draws other
+     *  visuals.
+     *  If the <code>LayoutManager.invalidateDisplayList()</code> method is called with
+     *  this ILayoutManagerClient, then the <code>validateDisplayList()</code> method
+     *  is called when it's time to update the display list.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    function validateDisplayList():void;
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/styles/IAdvancedStyleClient.as b/frameworks/projects/MXRoyale/src/main/royale/mx/styles/IAdvancedStyleClient.as
new file mode 100644
index 000000000..2b4ae8863
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/styles/IAdvancedStyleClient.as
@@ -0,0 +1,161 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.styles
+{
+
+/**
+ *  This interface describes the advanced properties that a component must
+ *  implement to fully participate in the advanced style subsystem.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+public interface IAdvancedStyleClient extends IStyleClient
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  id
+    //----------------------------------
+
+    /**
+     *  The identity of the component.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */ 
+    function get id():String;
+
+    //----------------------------------
+    //  styleParent
+    //----------------------------------
+
+    /**
+     *  The parent of this <code>IAdvancedStyleClient</code>..
+     *
+     *  Typically, you do not assign this property directly.
+     *  It is set by the <code>addChild, addChildAt, removeChild, and
+     *  removeChildAt</code> methods of the
+     *  <code>flash.display.DisplayObjectContainer</code> and  the
+     *  <code>mx.core.UIComponent.addStyleClient()</code>  and
+     *  the <code>mx.core.UIComponent.removeStyleClient()</code> methods.
+     *
+     *  If it is assigned a value directly, without calling one of the
+     *  above mentioned methods the instance of the class that implements this
+     *  interface will not inherit styles from the UIComponent or DisplayObject.
+     *  Also if assigned a value directly without, first removing the
+     *  object from the current parent with the remove methods listed above,
+     *  a memory leak could occur.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */ 
+    function get styleParent():IAdvancedStyleClient;
+    function set styleParent(parent:IAdvancedStyleClient):void;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Flex calls the <code>stylesInitialized()</code> method when
+     *  the styles for a component are first initialized.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    function stylesInitialized():void
+        
+    /**
+     *  Returns <code>true</code> if <code>cssState</code> matches <code>currentCSSState</code>.
+     *  Typically, you do not call this method directly. 
+     *  It is called by the <code>mx.styles.CSSCondition.matchesStyleClient()</code> method.
+     *
+     *  <p>Note Spark components use their skin state as the pseudo state.
+     *  Halo components use the <code>currentState</code> property.</p>
+     *
+     *  @param cssState A possible value of <code>CSSCondition.value</code>.
+     *  It represents the current state of this component used to match CSS pseudo-selectors.
+     *
+     *  @return <code>true</code> if <code>cssState</code> matches <code>currentCSSState</code>. 
+     *  By default, <code>currentCSSState</code> is the same as <code>currentState</code>.
+     *  If no state exists, return null.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    function matchesCSSState(cssState:String):Boolean;
+
+    /**
+     *  Determines whether this instance is the same as, or is a subclass of,
+     *  the given type.
+     *  Typically, you do not call this method directly. 
+     *  It is called by the <code>mx.styles.CSSCondition.matchesStyleClient()</code> method.
+     *
+     *  @param cssType A CSSSelector object.
+     *
+     *  @return <code>true</code> if <code>cssType</code> is in the hierarchy of qualified type selectors.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */ 
+    function matchesCSSType(cssType:String):Boolean;
+
+
+    /**
+     *  Returns <code>true</code> if <code>currentCSSState</code> is not <code>null</code>.
+     *  Typically, you do not call this method directly. 
+     *  It is called by the <code>mx.styles.CSSCondition.matchesStyleClient()</code> method.
+     *
+     *  <p>Note Spark components use their skin state as the pseudo state.
+     *  Halo components use the <code>currentState</code> property.</p>
+     *
+     *  @return <code>true</code> if <code>currentCSSState</code> is not <code>null</code>. 
+     *  By default, <code>currentCSSState</code> is the same as <code>currentState</code>.
+     *  If no state exists, return false.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.6
+     */
+    function hasCSSState():Boolean;
+    
+}
+
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/SparkRoyaleClasses.as b/frameworks/projects/SparkRoyale/src/main/royale/SparkRoyaleClasses.as
index e34eec796..d936785d2 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/SparkRoyaleClasses.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/SparkRoyaleClasses.as
@@ -34,11 +34,39 @@ internal class SparkRoyaleClasses
     import spark.skins.spark.DefaultItemRenderer;DefaultItemRenderer;
     import spark.skins.spark.DropDownListButtonSkin; DropDownListButtonSkin;
     import spark.skins.spark.TitleWindowCloseButtonSkin; TitleWindowCloseButtonSkin; 
-	 import spark.skins.spark.ComboBoxButtonSkin; ComboBoxButtonSkin; 
-	 import spark.skins.spark.ComboBoxTextInputSkin; ComboBoxTextInputSkin; 
-
-     import spark.layouts.supportClasses.SparkLayoutBead; SparkLayoutBead;
-
+	import spark.skins.spark.ComboBoxButtonSkin; ComboBoxButtonSkin; 
+	import spark.skins.spark.ComboBoxTextInputSkin; ComboBoxTextInputSkin; 
+	
+	import spark.layouts.supportClasses.SparkLayoutBead; SparkLayoutBead;
+	
+	import spark.components.supportClasses.RegExPatterns; RegExPatterns;
+	
+	import spark.components.gridClasses.CellRegion; CellRegion;
+	import spark.components.gridClasses.CellPosition; CellPosition;
+	import spark.components.gridClasses.GridSelectionMode; GridSelectionMode;
+	import spark.components.gridClasses.GridDoubleClickMode; GridDoubleClickMode;
+	import spark.components.gridClasses.GridSortFieldComplex; GridSortFieldComplex;
+	import spark.components.gridClasses.ComplexSortField; ComplexSortField;
+	import spark.components.gridClasses.GridSortFieldSimple; GridSortFieldSimple;
+	
+	import spark.components.gridClasses.IDataGridElement; IDataGridElement;
+	import spark.components.gridClasses.GridView; GridView;
+	import spark.components.gridClasses.GridRowNode; GridRowNode;
+	import spark.components.gridClasses.IGridItemRenderer; IGridItemRenderer;
+	import spark.components.gridClasses.GridRowList; GridRowList;
+	import spark.components.gridClasses.GridDimensions; GridDimensions;
+	import spark.components.gridClasses.GridLayout; GridLayout;
+	import spark.components.gridClasses.GridColumn; GridColumn;
+	import spark.components.gridClasses.GridSelection; GridSelection;
+	import spark.events.GridEvent; GridEvent;
+	import spark.events.GridCaretEvent; GridCaretEvent;
+	import spark.events.GridSelectionEvent; GridSelectionEvent;
+	import spark.collections.SubListView; SubListView;
+	import spark.collections.SortField; SortField;
+	import spark.components.supportClasses.GroupBase; GroupBase;
+	import spark.components.supportClasses.IDataProviderEnhance; IDataProviderEnhance;
+	import spark.components.Grid; Grid;
+	
 }
 
 }
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/collections/SortField.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/collections/SortField.as
new file mode 100644
index 000000000..abd9b7a94
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/collections/SortField.as
@@ -0,0 +1,567 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.collections
+{
+	
+	// import flash.events.Event;
+	import org.apache.royale.events.Event;
+	
+	import mx.styles.IAdvancedStyleClient;
+	import mx.collections.ISortField;
+	import mx.core.FlexGlobals;
+	import mx.core.IFlexModule;
+	import mx.core.IMXMLObject;
+	import mx.utils.ObjectUtil;
+	
+	// import spark.globalization.SortingCollator;
+	
+	// [ResourceBundle("collections")]
+	
+	//--------------------------------------
+	//  Styles
+	//--------------------------------------
+	
+	/**
+	 *  The locale identifier that specifies the language, region, script
+	 *  and optionally other related tags and keys.
+	 *  The syntax of this identifier must follow the syntax defined
+	 *  by the Unicode Technical Standard #35 (for example, en-US, de-DE, zh-Hans-CN).
+	 * 
+	 *  <p>For browser based apps, the default locale is based on the language settings from the browser. 
+	 *  (Note that this is not the browser UI language that is available from Javascript, but rather is the list of 
+	 *  preferred locales for web pages that the user has set in the browser preferences.) For AIR applications, 
+	 *  the default UI locale is based on the user's system preferences.</p>
+	 * 
+	 *  @see http://www.unicode.org/reports/tr35/
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.1
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Style(name="locale", type="String", inherit="yes")]
+	
+	/**
+	 *  Provides the sorting information required to establish a sort on a field
+	 *  or property in a collection view.
+	 *
+	 *  The SortField class is meant to be used with the Sort class.
+	 *
+	 *  Typically the sort is defined for collections of complex items, that
+	 *  is items in which the sort is performed on properties of those objects.
+	 *  As in the following example:
+	 *
+	 *  <pre><code>
+	 *     var col:ICollectionView = new ArrayCollection();
+	 *     col.addItem({first:"Anders", last:"Dickerson"});
+	 *     var sort:Sort = new Sort();
+	 *     var sortfield:SortField = new SortField("first", true);
+	 *     sortfield.setStyle("locale", "en-US");
+	 *     sort.fields = [sortfield];
+	 *     col.sort = sort;
+	 *  </code></pre>
+	 *
+	 *  There are situations in which the collection contains simple items, like
+	 *  <code>String</code>, <code>Date</code>, <code>Boolean</code>, etc.
+	 *  In this case, sorting should be applied to the simple type directly.
+	 *  When constructing a sort for this situation only a single sort field is
+	 *  required and should not have a <code>name</code> specified.
+	 *  For example:
+	 *
+	 *  <pre><code>
+	 *     var col:ICollectionView = new ArrayCollection();
+	 *     col.addItem("California");
+	 *     col.addItem("Arizona");
+	 *     var sort:Sort = new Sort();
+	 *     var sortfield:SortField = new SortField(null, true);
+	 *     sortfield.setStyle("locale", "en-US");
+	 *     sort.fields = [sortfield];
+	 *     col.sort = sort;
+	 *  </code></pre>
+	 *
+	 *  <p>The default comparison provided by the <code>SortField</code> class 
+	 *  provides correct language specific
+	 *  sorting for strings. The language is selected by the setting the locale
+	 *  style on an instance of the class in one of the following ways:
+	 *  </p>
+	 *  <ul>
+	 *  <li>
+	 *  By using the class in an MXML declaration and inheriting the
+	 *  locale from the document that contains the declaration.
+	 *  </li>
+	 *  Example:
+	 *  <pre>
+	 *  &lt;fx:Declarations&gt; <br>
+	 *         &lt;s:SortField id="sf" /&gt; <br>
+	 *  &lt;/fx:Declarations&gt;
+	 *  </pre>
+	 *  <li>
+	 *  By using an MXML declaration and specifying the locale value
+	 *  in the list of assignments.
+	 *  </li>
+	 *  Example:
+	 *  <pre>
+	 *  &lt;fx:Declarations&gt; <br>
+	 *      &lt;s:SortField id="sf_SimplifiedChinese" locale="zh-Hans-CN" /&gt; <br>
+	 *  &lt;/fx:Declarations&gt;
+	 *  </pre>
+	 *  <li>
+	 *  Calling the <code>setStyle</code> method,
+	 *  e.g. <code>sf.setStyle("locale", "zh-Hans-CN")</code>
+	 *  </li>
+	 *  <li> 
+	 *  Inheriting the style from a <code>UIComponent</code> by calling the
+	 *  UIComponent's <code>addStyleClient()</code> method.
+	 *  </li>
+	 *  </ul>
+	 *
+	 *  Note: to prevent problems like
+	 *  <a href="https://issues.apache.org/jira/browse/FLEX-34853">FLEX-34853</a>
+	 *  it is recommended to use SortField
+	 *  instances as immutable objects (by not changing their state).
+	 *  
+	 *  @mxml
+	 *
+	 *  <p>The <code>&lt;s:SortField&gt;</code> tag has the following attributes:</p>
+	 *
+	 *  <pre>
+	 *  &lt;s:SortField
+	 *  <b>Properties</b>
+	 *  compareFunction="<em>Internal compare function</em>"
+	 *  descending="false"
+	 *  name="null"
+	 *  numeric="null"
+	 *  /&gt;
+	 *  </pre>
+	 *
+	 *  @includeExample examples/SortExample1.mxml
+	 *  @includeExample examples/SortExample2.mxml
+	 * 
+	 *  @see mx.collections.ICollectionView
+	 *  @see spark.collections.Sort
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.1
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	public class SortField extends mx.collections.SortField implements IAdvancedStyleClient, IFlexModule, IMXMLObject
+	{
+		// include "../core/Version.as";
+		// include "AdvancedStyleClientImplementation.as";
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor.
+		 *
+		 *  @param name The name of the property that this field uses for
+		 *              comparison.
+		 *              If the object is a simple type, pass <code>null</code>.
+		 *  @param descending Tells the comparator whether to arrange items in
+		 *              descending order.
+		 *  @param numeric Tells the comparator whether to compare sort items as
+		 *              numbers, instead of alphabetically.
+		 *  @param sortCompareType Gives an indication to SortField which of the
+		 *              default compare functions to use.
+		 *  @param customCompareFunction Use a custom function to compare the
+		 *              objects based on this SortField.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.1
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function SortField(name:String = null,
+								  descending:Boolean = false,
+								  numeric:Object = null,
+								  sortCompareType:String = null,
+								  customCompareFunction:Function = null)
+		{
+			super(name, false, descending, numeric, sortCompareType, customCompareFunction);
+			
+			//initAdvancedStyleClient();
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 *  Cache for "locale" style.
+		 *
+		 *  The code needs be able to find out if the locale style has been changed
+		 *  from earlier.
+		 */
+		private var localeStyle:* = undefined;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		[Inspectable(category="General")]
+		
+		/**
+		 *  The function that compares two items during a sort of items for the
+		 *  associated collection. If you specify a <code>compareFunction</code>
+		 *  property in an <code>ISort</code> object, Flex ignores any 
+		 *  <code>compareFunction</code> properties of the ISort's 
+		 *  <code>SortField</code> objects.
+		 * 
+		 *  <p>The compare function must have the following signature:</p>
+		 *
+		 *  <p><code>function myCompare(a:Object, b:Object):int</code></p>
+		 *
+		 *  <p>This function must return the following values:</p>
+		 *
+		 *   <ul>
+		 *        <li>-1, if the <code>Object a</code> should appear before the 
+		 *        <code>Object b</code> in the sorted sequence</li>
+		 *        <li>0, if the <code>Object a</code> equals the 
+		 *        <code>Object b</code></li>
+		 *        <li>1, if the <code>Object a</code> should appear after the 
+		 *        <code>Object b</code> in the sorted sequence</li>
+		 *  </ul>
+		 *
+		 *  <p>The default value is an internal compare function that can perform
+		 *  a string, numeric, or date comparison in ascending or descending order.
+		 *  The string comparison is performed using the locale (language,
+		 *  region and script) specific comparison method from the
+		 *  <code>SortingCollator</code> class.
+		 *  This class uses the locale style to determine a locale.
+		 *  Specify your own function only if you need a need a custom comparison
+		 *  algorithm. This is normally only the case if a calculated field is
+		 *  used in a display.</p>
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.1
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		override public function get compareFunction():Function
+		{
+			return super.compareFunction;
+		}
+		
+		/**
+		 *  @deprecated A future release of Apache Flex SDK will remove this function. Please use the constructor
+		 *  argument instead.
+		 */
+		override public function set compareFunction(c:Function):void
+		{
+			super.compareFunction = c;
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 *
+		 *  Called by AdvancedStyleClientImplementation.as
+		 */
+		private function _getStyle(styleProp:String):*
+		{
+			/*if (styleProp != "locale")
+				return _advancedStyleClient.getStyleImpl(styleProp);*/
+			
+			if ((localeStyle !== undefined) && (localeStyle !== null))
+				return localeStyle;
+			
+			if (styleParent)
+				return styleParent.getStyle(styleProp);
+			
+			if (FlexGlobals.topLevelApplication)
+				return FlexGlobals.topLevelApplication.getStyle(styleProp);
+			
+			return undefined;
+		}
+		
+		/**
+		 *  @private
+		 *  Intercept style change for "locale".
+		 *
+		 *  In the case that there is no associated UI component or the
+		 *  module factory of the UIComponent has not yet been initialized
+		 *  style changes are only recorded but the styleChanged method
+		 *  is not called.  Overriding the setStyle method allows
+		 *  the class to be updated immediately when the locale style is
+		 *  set directly on this class instance.
+		 *
+		 *  Called by AdvancedStyleClientImplementation.as
+		 */
+		private function _setStyle(styleProp:String, newValue:*):void
+		{
+			//_advancedStyleClient.setStyleImpl(styleProp, newValue);
+			
+			if (styleProp != "locale")
+				return;
+			
+			localeChanged();
+		}
+		
+		/**
+		 *  @private
+		 *  Detects changes to style properties. When any style property is set,
+		 *  Flex calls the <code>styleChanged()</code> method,
+		 *  passing to it the name of the style being set.
+		 *
+		 *  For the Collator class this method determines whether or not the
+		 *  locale style has changed and if needed updates the instance of
+		 *  the class to reflect this change. If the locale has been
+		 *  updated the <code>change</code> event will be dispatched and
+		 *  uses of the bindable methods or properties will be updated.
+		 *
+		 *  Called by AdvancedStyleClientImplementation.as
+		 *
+		 *  @param styleProp The name of the style property, or null if
+		 *  all styles for this component have changed.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.1
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		private function _styleChanged(styleProp:String):void
+		{
+			localeChanged();
+			
+			//_advancedStyleClient.styleChangedImpl(styleProp);
+		}
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		// Private Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		//---------------------------------
+		//  stringCollator
+		//---------------------------------
+		
+		/**
+		 *  @private
+		 *  Locale-aware string collator.
+		 */
+		// private var internalStringCollator:SortingCollator;
+		
+		/**
+		 *  @private
+		 *  Locale-aware string collator
+		 *
+		 *  @default false
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.1
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		/*private function get stringCollator():SortingCollator
+		{
+			if (!internalStringCollator)
+			{
+				ensureStyleSource();
+				const locale:* = getStyle("locale");
+				
+				internalStringCollator = new SortingCollator();
+				internalStringCollator.setStyle("locale", locale);
+			}
+			
+			return internalStringCollator;
+		}*/
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Private Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 *  Ensure some style source exists for this instance of a globalization
+		 *  object.
+		 *
+		 *  A style source is considered exist if (A) styleParent value is non-null,
+		 *  or (B) localeStyle value has some useable value.
+		 *  If neither is the case, this style client will be added to the
+		 *  FlexGlobals.topLevelApplication as a child if possible.
+		 *
+		 *  As a side effect this will call the styleChanged method and if the
+		 *  locale has changed will cause the createWorkingInstance method
+		 *  to be called.
+		 */
+		private function ensureStyleSource():void
+		{
+			if (!styleParent &&
+				((localeStyle === undefined) || (localeStyle === null)))
+			{
+				if (FlexGlobals.topLevelApplication) 
+				{
+					FlexGlobals.topLevelApplication.addStyleClient(this);
+				}
+			}
+		}
+		
+		
+		
+		
+		
+		/**
+		 *  Pull the strings from the objects and call the implementation.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.1
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		override protected function stringCompare(a:Object, b:Object):int
+		{
+			var fa:String = name == null ? String(a) : String(getSortFieldValue(a));
+			var fb:String = name == null ? String(b) : String(getSortFieldValue(b));
+			
+			return null; //stringCollator.compare(fa, fb);
+		}
+		
+		/**
+		 *  Pull the values out fo the XML object, then compare
+		 *  using the string or numeric comparator depending
+		 *  on the numeric flag.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.1
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		override protected function xmlCompare(a:Object, b:Object):int
+		{
+			var sa:String = name == null ? a.toString() : getSortFieldValue(a).toString();
+			var sb:String = name == null ? b.toString() : getSortFieldValue(b).toString();
+			
+			if (numeric == true)
+			{
+				return ObjectUtil.numericCompare(parseFloat(sa), parseFloat(sb));
+			}
+			else
+			{
+				return null; //stringCollator.compare(sa, sb);
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  This method is called if a style is changed on the instances of
+		 *  this formatter.
+		 *
+		 *  This method determines if the locale style has changed and if
+		 *  so it updates the formatter to reflect this change.
+		 *  If the locale has been updated the <code>change</code> event
+		 *  will be dispatched and uses of the
+		 *  bindable methods or properties will be updated.
+		 */
+		private function localeChanged():void
+		{
+			const newLocaleStyle:* = null; //_advancedStyleClient.getStyleImpl("locale");
+			
+			if (localeStyle === newLocaleStyle)
+				return;
+			
+			localeStyle = newLocaleStyle;
+			
+			/*if (internalStringCollator)
+			{
+				internalStringCollator.setStyle("locale", localeStyle);
+			}*/
+			
+			dispatchEvent(new Event(Event.CHANGE));
+		}
+		
+		public function initialized(document:Object, id:String):void
+		{
+		}
+		
+		public function get className():String
+		{
+			return null;
+		}
+		
+		public function getStyle(styleProp:String):*
+		{
+			return null;
+		}
+		
+		public function get id():String
+		{
+			return "";
+		}
+		
+		public function get styleParent():IAdvancedStyleClient
+		{
+			return null;
+		}
+		
+		public function set styleParent(parent:IAdvancedStyleClient):void
+		{
+		}
+		
+		public function stylesInitialized():void
+		{
+		}
+		
+		public function matchesCSSState(cssState:String):Boolean
+		{
+			return false;
+		}
+		
+		public function matchesCSSType(cssType:String):Boolean
+		{
+			return false;
+		}
+		
+		public function hasCSSState():Boolean
+		{
+			return false;
+		}
+		
+		public function set moduleFactory(factory:mx.core.IFlexModuleFactory):void
+		{
+		}
+		
+		public function get moduleFactory():mx.core.IFlexModuleFactory 
+		{
+			return null;
+		}
+
+	}
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/collections/SubListView.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/collections/SubListView.as
new file mode 100644
index 000000000..b90e588a1
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/collections/SubListView.as
@@ -0,0 +1,415 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.collections
+{
+/*
+import flash.events.Event;
+import flash.events.EventDispatcher;
+*/
+	
+import org.apache.royale.events.Event;
+import org.apache.royale.events.EventDispatcher;
+
+import mx.collections.IList;
+import mx.events.CollectionEvent;
+import mx.events.CollectionEventKind;
+
+[ExcludeClass]
+
+/**
+ *  A "view" of a contiguous IList interval that begins at startIndex and extends for count items.
+ * 
+ *  The list item index parameter for IList methods like getItemAt(index) are defined relative to 
+ *  this SubListView.   For example the SubListView definition of getItemAt(0) is defined as 
+ *  list.getItemAt(startIndex).  Similarly returned index values and the location CollectionEvent 
+ *  property are defined relative to the SubListView.   In all other respects paraters, return values,
+ *  and events, have the same semantics as defined for IList.
+ *  
+ *  This class is internal to the Grid implementation.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 11
+ *  @playerversion AIR 3
+ *  @productversion Flex 5.0* 
+ */
+public class SubListView extends EventDispatcher implements IList
+{
+    /**
+     *  Construct a SubListView and optionally specify the target list and the item interval
+     *  this SubListView spans.
+     */
+    public function SubListView(list:IList = null, startIndex:int = 0, count:int = -1)
+    {
+        super();
+        this.list = list;
+        this.startIndex = startIndex;
+        this.count = count;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     */
+    private function dispatchChangeEvent(type:String):void
+    {
+        if (hasEventListener(type))
+            dispatchEvent(new Event(type));
+    }
+    
+    /**
+     *  @private
+     */
+    private function dispatchCollectionResetEvent():void
+    {
+        if (hasEventListener(CollectionEvent.COLLECTION_CHANGE))
+            dispatchEvent(new CollectionEvent(CollectionEvent.COLLECTION_CHANGE, false, false, CollectionEventKind.RESET));            
+    }      
+    
+    //----------------------------------
+    //  list
+    //----------------------------------
+    
+    private var _list:IList;
+    
+    [Inspectable(category="General")]
+    [Bindable("listChanged")]
+    
+    /**
+     *  The IList to which all of IList methods are delegated.
+     * 
+     *  <p>If this property is null, the IList mutation methods, such as <code>setItemAt()</code>,
+     *  are no-ops. The IList query methods, such <code>getItemAt()</code>, return null
+     *  or zero (-1 for <code>getItemIndex()</code>), as appropriate.</p>
+     * 
+     *  @default null  
+     */
+    public function get list():IList
+    {
+        return _list;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set list(value:IList):void
+    {
+        if (_list == value)
+            return;
+        
+        if (_list)
+            _list.removeEventListener(CollectionEvent.COLLECTION_CHANGE, handleCollectionChangeEvent);
+        _list = value;
+        if (_list)
+            _list.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleCollectionChangeEvent, false, 0); //, true);
+        
+        dispatchChangeEvent("listChanged");
+        dispatchCollectionResetEvent();
+    }
+	
+    //----------------------------------
+    //  startIndex
+    //----------------------------------
+    
+    private var _startIndex:int = 0;  // Typically this value is >= 0
+    
+    [Inspectable(category="General")]
+    [Bindable("startIndexChanged")]
+    
+    /**
+     *  The index of the first list item included by this SubListView.
+     * 
+     *  @default 0
+     */
+    public function get startIndex():int
+    {
+        return _startIndex;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set startIndex(value:int):void
+    {
+        if (_startIndex == value)
+            return;
+        
+        _startIndex = value;
+        
+        dispatchChangeEvent("startIndexChanged");
+        dispatchCollectionResetEvent();
+    }
+    
+    //----------------------------------
+    //  count
+    //----------------------------------
+    
+    private var _count:int = -1;  
+    
+    [Inspectable(category="General")]
+    [Bindable("countChanged")]
+    
+    /**
+     *  The number of items to be included in this SubListView or -1, which means
+     *  that all items, beginning with the one at startIndex, are to be included.
+     * 
+     *  @default -1
+     */
+    public function get count():int
+    {
+        return _count;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set count(value:int):void
+    {
+        if (_count == value)
+            return;
+        
+        _count = value;
+        
+        dispatchChangeEvent("countChanged");
+        dispatchCollectionResetEvent();
+    }
+    
+    
+    //--------------------------------------------------------------------------
+    //
+    //  CollectionEvent.COLLECTION_CHANGE Handlers
+    //
+    //-------------------------------------------------------------------------- 
+    
+    /**
+     *  @private
+     *  All "collectionChange" events are redispatched to the SubListView listeners.
+     */
+    private function handleCollectionChangeEvent(event:CollectionEvent):void
+    {
+        var viewEvent:CollectionEvent = null;
+        var location:int = event.location;
+        
+        switch (event.kind)
+        {
+            case CollectionEventKind.ADD:
+            case CollectionEventKind.REMOVE: 
+            {
+                viewEvent = handleModifyCollectionChangeEvent(event);
+                break;
+            }
+                
+            case CollectionEventKind.REPLACE:
+            case CollectionEventKind.UPDATE:
+            {
+                viewEvent = handleUpdateCollectionChangeEvent(event);
+                break;
+            }                
+                
+            case CollectionEventKind.MOVE:
+            {
+                // TBD: may require synthesizing add and/or remove events
+                break;
+            }
+                
+            default:  // refresh, reset, null
+            {
+                viewEvent = event;
+                break;
+            }
+        }		
+        
+        if (viewEvent)
+            dispatchEvent(viewEvent);
+    }
+    
+    /**
+     *  @private
+     */    
+    private function createCollectionEvent(kind:String):CollectionEvent
+    {
+        return new CollectionEvent(CollectionEvent.COLLECTION_CHANGE, false, false, kind);
+    }  
+    
+    /**
+     *  @private
+     *  This method is called after (the underlying) list has been modified via add/remove.
+     * 
+     *  The incoming event.location is the list modification start point, event.items is the 
+     *  array of items that were inserted/removed/replaced.
+     * 
+     *  Returned event (if any) is a refresh if the insert was "to the left of" this SubListView,
+     *  or a potentially truncated version of the insert was within the SubListView.
+     */
+    private function handleModifyCollectionChangeEvent(event:CollectionEvent):CollectionEvent
+    {
+        const viewEnd:int = startIndex + length;
+        
+        //  is "to the right of" the SubListView
+        
+        if (event.location >= viewEnd) 
+            return null;
+        
+        // Insert is "to the left of" the SubListView; entire SubListView shifts 
+        
+        if (event.location <= startIndex) 
+            return createCollectionEvent(CollectionEventKind.REFRESH);
+        
+        // Insert is within the SubListView
+        
+        const viewEvent:CollectionEvent = createCollectionEvent(event.kind);
+        viewEvent.location = event.location - startIndex;
+        
+        const items:Array = [];
+        viewEvent.items = items;
+        
+        var location:int = event.location;
+        for each (var item:Object in event.items)
+        {
+            items.push(item);
+            if (location++ >= viewEnd)
+                break;
+        }        
+
+        return viewEvent;
+    } 
+    
+    /**
+     *  @private
+     *  This method is called after (the underlying) list has been modified via update/replace.
+     *  This case is different than add/remove because the item locations do not change.
+     * 
+     *  The incoming event.location is the list modification start point, event.items is the 
+     *  array of PropertyChangeEvents that characterize the old and new item values.
+     * 
+     */
+    private function handleUpdateCollectionChangeEvent(event:CollectionEvent):CollectionEvent
+    {
+        const viewEnd:int = startIndex + length;
+        
+        // Update/replace doesn't overlap this SubListView
+        
+        if (((event.location + event.items.length) < startIndex) || (event.location >= viewEnd))
+            return null;
+        
+        const viewEvent:CollectionEvent = createCollectionEvent(event.kind);
+        var viewLocation:int = Math.max(startIndex, event.location);
+        viewEvent.location = viewLocation - startIndex;
+        
+        const items:Array = [];
+        viewEvent.items = items;
+        
+        for each (var item:Object in event.items)
+        {
+            items.push(item);
+            if (viewLocation++ >= viewEnd)
+                break;
+        }        
+        
+        return viewEvent;
+    } 
+        
+    //--------------------------------------------------------------------------
+    //
+    //  IList Implementation
+    //
+    //--------------------------------------------------------------------------
+    
+    [Bindable("collectionChange")]
+    
+    public function get length():int
+    {
+        if (count == -1)
+            return (list) ? list.length - startIndex : 0; 
+        
+        return count;
+    }
+    
+    public function addItem(item:Object):void
+    {
+        if (list)
+            list.addItem(item);
+    }
+    
+    public function addItemAt(item:Object, index:int):void
+    {
+        if (list)
+            list.addItemAt(item, index + startIndex);
+    }
+    
+    public function getItemAt(index:int, prefetch:int=0):Object
+    {
+        return (list) ? list.getItemAt(index + startIndex, prefetch) : null;
+    }
+    
+    public function getItemIndex(item:Object):int
+    {
+        if (!list || (count == 0))
+            return -1;
+        
+        const index:int = list.getItemIndex(item);
+        return ((index < startIndex) || (index >= (startIndex + length))) ? -1 : index - startIndex;
+    }
+    
+    public function itemUpdated(item:Object, property:Object=null, oldValue:Object=null, newValue:Object=null):void
+    {
+        if (list)
+            list.itemUpdated(item, property, oldValue, newValue);        
+    }
+    
+    public function removeAll():void
+    {
+        if (list)
+            list.removeAll();
+    }
+    
+	public function removeItem(item:Object):Boolean
+	{
+		return (list && "removeItem" in list) ? list["removeItem"]( item ) : false;
+	}
+	
+    public function removeItemAt(index:int):Object
+    {
+        return (list) ? list.removeItemAt(startIndex + index) : null;
+    }
+    
+    public function setItemAt(item:Object, index:int):Object
+    {
+        return (list) ? list.setItemAt(item, startIndex + index) : null;
+    }
+    
+    public function toArray():Array
+    {
+        if (!list)
+            return [];
+        
+        const a:Array = new Array(length);
+		const aCount:int = Math.min(a.length, list.length - startIndex);
+        for(var i:int = 0; i < aCount; i++)
+            a[i] = list.getItemAt(i + startIndex);
+        return a;
+    }
+    
+}
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/Grid.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/Grid.as
new file mode 100644
index 000000000..7ada3a356
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/Grid.as
@@ -0,0 +1,6053 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components
+{
+	/*	
+	import flash.display.InteractiveObject;
+	import flash.events.Event;
+	import flash.events.MouseEvent;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.utils.getTimer;
+	*/
+	import mx.events.MouseEvent;
+	import org.apache.royale.geom.Point;
+	import org.apache.royale.geom.Rectangle;
+	
+	import mx.controls.DataGrid;
+	
+	import mx.collections.ArrayList;
+	import mx.collections.IList;
+	import mx.core.IFactory;
+	import mx.core.IVisualElement;
+	import mx.core.UIComponent;
+	import mx.core.UIComponentGlobals;
+	import mx.core.mx_internal;
+	import mx.events.CollectionEvent;
+	import mx.events.CollectionEventKind;
+	import mx.events.FlexEvent;
+	import mx.events.PropertyChangeEvent;
+	import mx.graphics.SolidColorStroke;
+	import mx.utils.ObjectUtil;
+	
+	// import spark.collections.SubListView;
+	import spark.components.gridClasses.CellPosition;
+	import spark.components.gridClasses.GridDoubleClickMode;
+	import spark.components.gridClasses.GridColumn;
+	import spark.components.gridClasses.GridDimensions;
+	// import spark.components.gridClasses.GridDimensionsView;
+	import spark.components.gridClasses.GridLayout;
+	import spark.components.gridClasses.GridSelection;
+	import spark.components.gridClasses.GridSelectionMode;
+	import spark.components.gridClasses.GridView;
+	// import spark.components.gridClasses.GridViewLayout;
+	import spark.components.gridClasses.IDataGridElement;
+	import spark.components.gridClasses.IGridItemRenderer;
+	import spark.components.supportClasses.GroupBase;
+	import spark.components.supportClasses.IDataProviderEnhance;
+	import spark.components.supportClasses.RegExPatterns;
+	import spark.events.GridCaretEvent;
+	import spark.events.GridEvent;
+	import spark.layouts.VerticalLayout;
+	import spark.layouts.supportClasses.LayoutBase;
+	import spark.primitives.Line;
+	import spark.primitives.Rect;
+	// import spark.utils.MouseEventUtil;
+	
+	use namespace mx_internal;
+	
+	//--------------------------------------
+	//  Events
+	//--------------------------------------
+	
+	/**
+	 *  Dispatched when the mouse button is pressed over a Grid cell.
+	 *
+	 *  @eventType spark.events.GridEvent.GRID_MOUSE_DOWN
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Event(name="gridMouseDown", type="spark.events.GridEvent")]
+	
+	/**
+	 *  Dispatched after a <code>gridMouseDown</code> event 
+	 *  if the mouse moves before the button is released.
+	 *
+	 *  @eventType spark.events.GridEvent.GRID_MOUSE_DRAG
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Event(name="gridMouseDrag", type="spark.events.GridEvent")]
+	
+	/**
+	 *  Dispatched when the mouse button is released over a Grid cell.
+	 *  During a drag operation, it is also dispatched after a 
+	 *  <code>gridMouseDown</code> event 
+	 *  when the mouse button is released, even if the mouse is no longer 
+	 *  in the Grid.
+	 *
+	 *  @eventType spark.events.GridEvent.GRID_MOUSE_UP
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Event(name="gridMouseUp", type="spark.events.GridEvent")]
+	
+	/**
+	 *  Dispatched when the mouse enters a grid cell.
+	 *
+	 *  @eventType spark.events.GridEvent.GRID_ROLL_OVER
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Event(name="gridRollOver", type="spark.events.GridEvent")]
+	
+	/**
+	 *  Dispatched when the mouse leaves a grid cell.
+	 *
+	 *  @eventType spark.events.GridEvent.GRID_ROLL_OUT
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Event(name="gridRollOut", type="spark.events.GridEvent")]
+	
+	/**
+	 *  Dispatched when the mouse is clicked over a cell
+	 *
+	 *  @eventType spark.events.GridEvent.GRID_CLICK
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Event(name="gridClick", type="spark.events.GridEvent")]
+	
+	/**
+	 *  Dispatched when the mouse is double-clicked over a cell
+	 *
+	 *  @eventType spark.events.GridEvent.GRID_DOUBLE_CLICK
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Event(name="gridDoubleClick", type="spark.events.GridEvent")]
+	
+	/**
+	 *  Dispatched after the caret changes.  
+	 *
+	 *  @eventType spark.events.GridCaretEvent.CARET_CHANGE
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	[Event(name="caretChange", type="spark.events.GridCaretEvent")]
+	
+	/**
+	 *  The Grid control displays a list of data items called
+	 *  its <i>data provider</i> in a scrollable table or "grid", one item per row.
+	 *  Each of the grid's columns, defined by a GridColumn object,
+	 *  displays a value based on the item for the corresponding row.
+	 *  The grid's data provider is mutable, meaning its items can be added or
+	 *  removed, or changed.  
+	 *  Similarly, the list of columns is mutable.
+	 * 
+	 *  <p>The Grid component is intended to be used as a DataGrid skin part, or
+	 *  as an element of other custom composite components.  
+	 *  Therefore, it is not skinnable, it does not include a scroller or scrollbars, 
+	 *  and it does not provide default mouse or keyboard event handling.</p>
+	 * 
+	 *  <p>Each visible Grid <i>cell</i> is displayed by a GridItemRenderer
+	 *  instance created by using the <code>itemRenderer</code> property.  
+	 *  specify an item renderer for each column.
+	 *  Before it is displayed, each item renderer instance is configured 
+	 *  with the value of the data provider item for that row.
+	 *  Item renderers are created as needed and then, to keep creation
+	 *  overhead to a minimum, pooled and recycled.</p>
+	 *
+	 *  <p>The Grid control supports a doubleClick event, according the <code>doubleClickMode</code>
+	 *  property.</p>
+	 * 
+	 *  <p>The Grid control supports selection, according the <code>selectionMode</code>
+	 *  property.  The set of selected row or cell indices can be modified or
+	 *  queried programatically using the selection methods, such as 
+	 *  <code>setSelectedIndex</code> or <code>selectionContainsIndex()</code>.</p>
+	 * 
+	 *  <p>The Grid control displays hover, caret, and selection indicators based  
+	 *  on the <code>selectionMode</code> property and the corresponding 
+	 *  row index and column index properties, such as 
+	 *  <code>hoverRowIndex</code> and <code>columnRowIndex</code>.   
+	 *  An indicator can be any visual element.  
+	 *  Indicators that implement IGridVisualElement can configure themselves 
+	 *  according to the row and column in which they are used.</p>
+	 * 
+	 *  <p>The Grid control supports smooth scrolling.  
+	 *  Their vertical and horizontal scroll positions define the pixel origin 
+	 *  of the visible part of the grid and the grid's layout only displays 
+	 *  as many cell item renderers as are needed to fill the available space.</p>
+	 *
+	 *  <p>The Grid control supports variable height rows that automatically compute 
+	 *  their height based on the item renderers' contents.  
+	 *  This support is called grid <i>virtualization</i>
+	 *  because the mapping from (pixel) scroll positions to row and column indices
+	 *  is typically based on incomplete information about the preferred sizes 
+	 *  for grid cells.  
+	 *  The Grid caches the computed heights of rows that have been
+	 *  scrolled into view and estimates the rest based on a single 
+	 *  <code>typicalItem</code>.</p>
+	 * 
+	 *  <p>Transitions in DataGrid item renderers aren't supported. The GridItemRenderer class 
+	 *  has disabled its <code>transitions</code> property so setting it will have no effect.</p>
+	 *
+	 *  @mxml <p>The <code>&lt;s:Grid&gt;</code> tag inherits all of the tag 
+	 *  attributes of its superclass and adds the following tag attributes:</p>
+	 *
+	 *  <pre>
+	 *  &lt;s:Grid 
+	 *    <strong>Properties</strong>
+	 *  /&gt;
+	 *  </pre>
+	 *
+	 *  @see DataGrid
+	 *  @see spark.components.gridClasses.GridColumn
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 4.5
+	 */
+	public class Grid extends Group implements IDataGridElement, IDataProviderEnhance
+	{
+		// include "../core/Version.as";
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 *  A list of functions to be called at commitProperties() time, after the dataProvider
+		 *  has been set.  This list is used to defer making grid selection updates per the 
+		 *  set methods for the selectedIndex, selectedIndices, selectedItem, selectedItems, 
+		 *  selectedCell and selectedCells properties.
+		 */
+		private const deferredOperations:Vector.<Function> = new Vector.<Function>();
+		
+		/**
+		 *  @private
+		 *  Cache the dataItem that goes with the caretRowIndex so we can find the
+		 *  rowIndex of the caret after a collection refresh event.
+		 */    
+		private var caretSelectedItem:Object = null;
+		private var updateCaretForDataProviderChanged:Boolean = false;
+		private var updateCaretForDataProviderChangeLastEvent:CollectionEvent;
+		
+		/**
+		 *  @private
+		 *  True while updateDisplayList is running.  Use to disable invalidateSize(),
+		 *  invalidateDisplayList() here and in the GridLayer class.
+		 */
+		mx_internal var inUpdateDisplayList:Boolean = false;  
+		
+		/**
+		 *  @private
+		 *  True while doing a drag operation with the mouse.
+		 */
+		private var dragInProgress:Boolean = false;
+		
+		/**
+		 *  @private
+		 *  True if the columns were generated rather than explicitly set.
+		 */
+		private var generatedColumns:Boolean = false;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor. 
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function Grid()
+		{
+			super();
+			/*
+			layout = new GridLayout();
+			
+			MouseEventUtil.addDownDragUpListeners(this, 
+				grid_mouseDownDragUpHandler, 
+				grid_mouseDownDragUpHandler, 
+				grid_mouseDownDragUpHandler);
+			
+			addEventListener(MouseEvent.MOUSE_UP, grid_mouseUpHandler);
+			addEventListener(MouseEvent.MOUSE_MOVE, grid_mouseMoveHandler);
+			addEventListener(MouseEvent.ROLL_OUT, grid_mouseRollOutHandler);   
+			*/
+		}
+		
+		/**
+		 *  @private
+		 *  Return the GridView which contains the specified cell.   If rowIndex == -1,
+		 *  then return the topmost GridView that contains the specified column and 
+		 *  if columnIndex == -1 then return the leftmost GridView that contains the specified row. 
+		 */
+		private function getGridViewAt(rowIndex:int, columnIndex:int):GridView
+		{
+			if ((rowIndex < 0) && (columnIndex < 0))
+				return null;
+			
+			const gridLayout:GridLayout = layout as GridLayout;
+			
+			if ((rowIndex >= lockedRowCount) || (rowIndex == -1))
+			{
+				if ((columnIndex >= lockedColumnCount) || (columnIndex == -1))
+					return gridLayout.centerGridView;
+				
+				return gridLayout.leftGridView;
+			}
+			
+			return (columnIndex < lockedColumnCount) ? gridLayout.topLeftGridView : gridLayout.topGridView;
+		}
+		
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		private function dispatchChangeEvent(type:String):void
+		{
+			if (hasEventListener(type))
+			/*dispatchEvent(new Event(type))*/;
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function dispatchFlexEvent(type:String):void
+		{
+			if (hasEventListener(type))
+				dispatchEvent(new FlexEvent(type));
+		}
+		
+		//----------------------------------
+		//  anchorColumnIndex
+		//----------------------------------
+		
+		private var _anchorColumnIndex:int = 0;
+		
+		/**
+		 *  @private
+		 *  True if either anchorColumnIndex or anchorRowIndex changes.
+		 */
+		private var anchorChanged:Boolean = false;
+		
+		[Bindable("anchorColumnIndexChanged")]
+		
+		/**
+		 *  The column index of the <i>anchor</i> for the next shift selection.
+		 *  The anchor is the item most recently selected. 
+		 *  It defines the anchor item when selecting multiple items in the grid. 
+		 *  When you select multiple items, the set of items extends from 
+		 *  the anchor to the caret item.
+		 *
+		 *  <p>Grid event handlers should use this property to record the
+		 *  location of the most recent unshifted mouse down or keyboard
+		 *  event that defines one end of the next potential shift
+		 *  selection.  
+		 *  The caret index defines the other end.</p>
+		 * 
+		 *  @default 0
+		 * 
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#caretColumnIndex
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get anchorColumnIndex():int
+		{
+			return _anchorColumnIndex;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set anchorColumnIndex(value:int):void
+		{
+			if (_anchorColumnIndex == value || 
+				selectionMode == GridSelectionMode.SINGLE_ROW || 
+				selectionMode == GridSelectionMode.MULTIPLE_ROWS)
+			{
+				return;
+			}
+			
+			_anchorColumnIndex = value;
+			
+			anchorChanged = true;
+			invalidateProperties();
+			
+			dispatchChangeEvent("anchorColumnIndexChanged");
+		}
+		
+		//----------------------------------
+		//  anchorRowIndex
+		//----------------------------------
+		
+		private var _anchorRowIndex:int = 0; 
+		
+		[Bindable("anchorRowIndexChanged")]
+		
+		/**
+		 *  The row index of the <i>anchor</i> for the next shift selection.
+		 *  The anchor is the item most recently selected. 
+		 *  It defines the anchor item when selecting multiple items in the grid. 
+		 *  When you select multiple items, the set of items extends from 
+		 *  the anchor to the caret item.
+		 *
+		 *  <p>Grid event handlers should use this property to record the
+		 *  location of the most recent unshifted mouse down or keyboard
+		 *  event that defines one end of the next potential shift
+		 *  selection.  
+		 *  The caret index defines the other end.</p>
+		 * 
+		 *  @default 0
+		 *
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#caretColumnIndex
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get anchorRowIndex():int
+		{
+			return _anchorRowIndex;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set anchorRowIndex(value:int):void
+		{
+			if (_anchorRowIndex == value)
+				return;
+			
+			_anchorRowIndex = value;
+			
+			anchorChanged = true;
+			invalidateProperties();
+			
+			dispatchChangeEvent("anchorRowIndexChanged");
+		}
+		
+		//----------------------------------
+		//  caretIndicator
+		//----------------------------------
+		
+		private var _caretIndicator:IFactory = null;
+		
+		[Bindable("caretIndicatorChanged")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
+		 *  a single visual element displayed for the caret row, 
+		 *  If <code>selectionMode</code> is
+		 *  <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, the
+		 *  visual element displayed for the caret cell.
+		 *  
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get caretIndicator():IFactory
+		{
+			return _caretIndicator;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set caretIndicator(value:IFactory):void
+		{
+			if (_caretIndicator == value)
+				return;
+			
+			_caretIndicator = value;
+			invalidateDisplayListFor("caretIndicator");
+			dispatchChangeEvent("caretIndicatorChanged");
+		}    
+		
+		//----------------------------------
+		//  caretColumnIndex
+		//----------------------------------
+		
+		private var _caretColumnIndex:int = -1;
+		private var _oldCaretColumnIndex:int = -1;
+		private var caretChanged:Boolean = false;
+		
+		[Bindable("caretColumnIndexChanged")]
+		
+		/**
+		 *  If <code>showCaretIndicator</code> is <code>true</code>,
+		 *  the column index of the <code>caretIndicator</code>.
+		 
+		 *  <p>If <code>selectionMode</code> is
+		 *  <code>GridSelectionMode.SINGLE_ROW</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code> then the indicator
+		 *  occupies the entire row and <code>caretColumnIndex</code> is ignored.  
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, then the 
+		 *  <code>caretIndicator</code> occupies the specified cell.</p>
+		 * 
+		 *  <p>Setting <code>caretColumnIndex</code> to -1 means that the column 
+		 *  index is undefined and a cell caret is not shown.</p>
+		 *  
+		 *  @default -1
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get caretColumnIndex():int
+		{
+			return _caretColumnIndex;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set caretColumnIndex(value:int):void
+		{
+			if (_caretColumnIndex == value || value < -1)
+				return;
+			
+			_caretColumnIndex = value;
+			
+			caretChanged = true;
+			invalidateProperties();
+			
+			// Unconditionally invalidate because renderers may depend on
+			// caretColumnIndex even when the caretIndicator doesn't exist.
+			invalidateDisplayListFor("caretIndicator");         
+			dispatchChangeEvent("caretColumnIndexChanged");
+		}
+		
+		//----------------------------------
+		//  caretRowIndex
+		//----------------------------------
+		
+		private var _caretRowIndex:int = -1;
+		private var _oldCaretRowIndex:int = -1;
+		
+		[Bindable("caretRowIndexChanged")]
+		
+		/**
+		 *  If <code>showCaretIndicator</code> is <code>true</code>,   
+		 *  the row index of the <code>caretIndicator</code>.
+		 *  If <code>selectionMode</code> is
+		 *  <code>GridSelectionMode.SINGLE_ROW</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code> then the indicator
+		 *  occupies the entire row and the <code>caretColumnIndex</code> 
+		 *  property is ignored.  
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, then the <code>caretIndicator</code>
+		 *  occupies the specified cell.
+		 * 
+		 *  <p>Setting <code>caretRowIndex</code> to -1 means that the row index 
+		 *  is undefined and the caret will not be shown.</p>
+		 * 
+		 *  @default -1
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get caretRowIndex():int
+		{
+			return _caretRowIndex;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set caretRowIndex(value:int):void
+		{
+			if (_caretRowIndex == value || value < -1)
+				return;
+			
+			_caretRowIndex = value;
+			
+			caretChanged = true;
+			invalidateProperties();
+			
+			// Unconditionally invalidate because renderers may depend on
+			// caretRowIndex even when the caretIndicator doesn't exist.
+			invalidateDisplayListFor("caretIndicator");         
+			dispatchChangeEvent("caretRowIndexChanged");
+		}
+		
+		//----------------------------------
+		//  clipAndEnableScrolling (private override)
+		//----------------------------------
+		
+		private var _clipAndEnableScrolling:Boolean = false;
+		
+		/**
+		 *  @private
+		 */
+		override public function get clipAndEnableScrolling():Boolean 
+		{
+			return _clipAndEnableScrolling;
+		}
+		
+		/**
+		 *  @private
+		 */
+		override public function set clipAndEnableScrolling(value:Boolean):void 
+		{
+			if (value == _clipAndEnableScrolling)
+				return;
+			
+			_clipAndEnableScrolling = value;
+			/*
+			const gridLayout:GridLayout = layout as GridLayout;
+			const topGridView:GridView = gridLayout.topGridView;        
+			const leftGridView:GridView = gridLayout.leftGridView;
+			const centerGridView:GridView = gridLayout.centerGridView;		
+			
+			if (topGridView) topGridView.clipAndEnableScrolling = value;
+			if (leftGridView) leftGridView.clipAndEnableScrolling = value;
+			if (centerGridView) centerGridView.clipAndEnableScrolling = value;
+			*/
+		}
+		
+		
+		//----------------------------------
+		//  contentHeight (private get override)
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 */
+		override public function get contentHeight():Number 
+		{
+			return Math.ceil(gridDimensions.getContentHeight());
+		}
+		
+		//----------------------------------
+		//  contentWidth (private get override)
+		//---------------------------------- 
+		
+		/**
+		 *  @private
+		 */    
+		override public function get contentWidth():Number 
+		{
+			return Math.ceil(gridDimensions.getContentWidth());
+		}
+		
+		//----------------------------------
+		//  horizontalScrollPosition (private override)
+		//----------------------------------
+		
+		private var _horizontalScrollPosition:Number = 0;
+		
+		[Bindable]
+		[Inspectable(minValue="0.0")] 
+		
+		/**
+		 *  @copy spark.core.IViewport#horizontalScrollPosition
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		override public function get horizontalScrollPosition():Number 
+		{
+			return _horizontalScrollPosition;
+		}
+		
+		/**
+		 *  @private
+		 */
+		/*override*/ 
+		public function set horizontalScrollPosition(value:Number):void 
+		{
+			if (_horizontalScrollPosition == value)
+				return;
+			/*
+			const gridLayout:GridLayout = layout as GridLayout;
+			const topGridView:GridView = gridLayout.topGridView;        
+			const centerGridView:GridView = gridLayout.centerGridView;	
+			
+			if (centerGridView)
+			{
+				const gridViewLayout:GridViewLayout = centerGridView.gridViewLayout;
+				const gridMaxHSP:Number = contentWidth - width;
+				const centerContentWidth:Number = Math.ceil(gridViewLayout.gridDimensionsView.getContentWidth());
+				const centerMaxHSP:Number = centerContentWidth - centerGridView.width;
+				const hsp:Number = (gridMaxHSP > 0) ? (centerMaxHSP / gridMaxHSP) * value : 0;
+				
+				centerGridView.horizontalScrollPosition = hsp;
+				
+				if (topGridView)
+					topGridView.horizontalScrollPosition = hsp;
+			}
+			*/
+			_horizontalScrollPosition = value;
+			
+		}
+		
+		
+		//----------------------------------
+		//  isFirstRow
+		//----------------------------------
+		
+		/**
+		 *  Returns if the selectedIndex is equal to the first row.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function get isFirstRow():Boolean
+		{
+			if (dataProvider && dataProvider.length > 0)
+			{
+				if (selectedIndex == 0)
+				{
+					return true;
+				}
+				else
+				{
+					return false;
+				}
+			}
+			else
+			{
+				return false;
+			}
+		}
+		
+		
+		//----------------------------------
+		//  isLastRow
+		//----------------------------------
+		
+		/**
+		 *  Returns if the selectedIndex is equal to the last row.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function get isLastRow():Boolean
+		{
+			if (dataProvider && dataProvider.length > 0)
+			{
+				if (selectedIndex == dataProvider.length - 1)
+				{
+					return true;
+				}
+				else
+				{
+					return false;
+				}
+			}
+			else
+			{
+				return false;
+			}
+		}
+		
+		
+		//----------------------------------
+		//  verticalScrollPosition (private override)
+		//----------------------------------
+		
+		private var _verticalScrollPosition:Number = 0;
+		
+		[Bindable]
+		[Inspectable(minValue="0.0")] 
+		
+		/**
+		 *  @copy spark.core.IViewport#verticalScrollPosition
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		override public function get verticalScrollPosition():Number 
+		{
+			return _verticalScrollPosition;
+		}
+		
+		/**
+		 *  @private
+		 */
+		/* override */ 
+		public function set verticalScrollPosition(value:Number):void 
+		{
+			if (_verticalScrollPosition == value)
+				return;
+			/*
+			const gridLayout:GridLayout = layout as GridLayout;
+			const leftGridView:GridView = gridLayout.leftGridView;
+			const centerGridView:GridView = gridLayout.centerGridView;	
+			
+			if (centerGridView)
+			{
+				const gridViewLayout:GridViewLayout = centerGridView.gridViewLayout;
+				const gridMaxVSP:Number = contentHeight - height;
+				const centerContentHeight:Number = Math.ceil(gridViewLayout.gridDimensionsView.getContentHeight());
+				const centerMaxVSP:Number = centerContentHeight - centerGridView.height;
+				const vsp:Number = (gridMaxVSP > 0) ? (centerMaxVSP / gridMaxVSP) * value : 0;
+				
+				centerGridView.verticalScrollPosition = vsp;
+				
+				if (leftGridView)
+					leftGridView.verticalScrollPosition = vsp;
+			}
+			*/
+			_verticalScrollPosition = value;
+			
+		}
+		
+		//----------------------------------
+		//  hoverIndicator
+		//----------------------------------
+		
+		private var _hoverIndicator:IFactory = null;
+		
+		[Bindable("hoverIndicatorChanged")]
+		
+		/**
+		 *  If <code>selectionMode</code> is
+		 *  <code>GridSelectionMode.SINGLE_ROW</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>. 
+		 *  a single visual element displayed for the row under the mouse.
+		 *  If <code>selectionMode</code> is
+		 *  <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>,
+		 *  the visual element for the cell.
+		 * 
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get hoverIndicator():IFactory
+		{
+			return _hoverIndicator;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set hoverIndicator(value:IFactory):void
+		{
+			if (_hoverIndicator == value)
+				return;
+			
+			_hoverIndicator = value;
+			invalidateDisplayListFor("hoverIndicator");
+			dispatchChangeEvent("hoverIndicatorChanged");
+		}    
+		
+		//----------------------------------
+		//  hoverColumnIndex 
+		//----------------------------------
+		
+		private var _hoverColumnIndex:int = -1;
+		
+		[Bindable("hoverColumnIndexChanged")]
+		
+		/**
+		 *  If <code>showHoverIndicator</code> is <code>true</code>,  
+		 *  Specifies column index of the <code>hoverIndicator</code>.
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, then the indicator
+		 *  occupies the entire row and <code>hoverColumnIndex</code> is ignored. 
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code> then the <code>hoverIndicator</code>
+		 *  occupies the specified cell.
+		 *  
+		 *  <p>Setting <code>hoverColumnIndex</code> to -1 (the default) means 
+		 *  that the column index is undefined and a cell hover indicator is not displayed.</p>
+		 * 
+		 *  @default -1
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get hoverColumnIndex():int
+		{
+			return _hoverColumnIndex;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set hoverColumnIndex(value:int):void
+		{
+			if (_hoverColumnIndex == value)
+				return;
+			
+			_hoverColumnIndex = value;
+			
+			// Unconditionally invalidate because renderers may depend on
+			// hoverColumnIndex even when the hoverIndicator doesn't exist.
+			invalidateDisplayListFor("hoverIndicator");
+			dispatchChangeEvent("hoverColumnIndexChanged");
+		}
+		
+		//----------------------------------
+		//  hoverRowIndex
+		//----------------------------------
+		
+		private var _hoverRowIndex:int = -1;
+		
+		[Bindable("hoverRowIndexChanged")]
+		
+		/**
+		 *  If <code>showHoverIndicator</code> is <code>true</code>,  
+		 *  specifies the column index of the <code>hoverIndicator</code>.
+		 *  If <code>selectionMode</code> is
+		 *  <code>GridSelectionMode.SINGLE_ROW</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, then the indicator
+		 *  occupies the entire row and <code>hoverColumnIndex</code> is ignored.   
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code> then the <code>hoverIndicator</code>
+		 *  occupies the specified cell.
+		 * 
+		 *  <p>Setting <code>hoverRowIndex</code> to -1,the default, means that 
+		 *  the row index is undefined and a hover indicator is not displayed.</p>
+		 * 
+		 *  @default -1
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get hoverRowIndex():int
+		{
+			return _hoverRowIndex;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set hoverRowIndex(value:int):void
+		{
+			if (_hoverRowIndex == value)
+				return;
+			
+			_hoverRowIndex = value;
+			
+			// Unconditionally invalidate because renderers may depend on
+			// hoverRowIndex even when the hoverIndicator doesn't exist.
+			invalidateDisplayListFor("hoverIndicator");           
+			dispatchChangeEvent("hoverRowIndexChanged");
+		}
+		
+		//----------------------------------
+		//  columns
+		//----------------------------------    
+		
+		private var _columns:IList = null;
+		private var columnsChanged:Boolean = false;
+		
+		[Bindable("columnsChanged")]
+		[Inspectable(category="General")]
+		
+		/**
+		 *  The list of GridColumn objectss displayed by this grid.  
+		 *  Each column selects different data provider item properties 
+		 *  to display.
+		 *  
+		 *  <p>GridColumn objects can only appear in the <code>columns</code> 
+		 *  for a single Grid control.</p> 
+		 *  
+		 *  @default null
+		 * 
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get columns():IList
+		{
+			return _columns;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set columns(value:IList):void
+		{
+			if (_columns == value)
+				return;
+			
+			// Remove the old column listener, and set each column's grid=null, columnIndex=-1.
+			
+			const oldColumns:IList = _columns;
+			if (oldColumns)
+			{
+				oldColumns.removeEventListener(CollectionEvent.COLLECTION_CHANGE, columns_collectionChangeHandler);
+				for (var index:int = 0; index < oldColumns.length; index++)
+				{
+					
+					var oldColumn:GridColumn = GridColumn(oldColumns.getItemAt(index));
+					oldColumn.setGrid(null);
+					oldColumn.setColumnIndex(-1);
+					
+				}
+			}
+			
+			_columns = value; 
+			
+			// Add the new columns listener, and set their grid,columnIndex properties.
+			// The listener is a local method, so creating a weak reference to it (last 
+			// addEventListener parameter) is safe, since the listener's lifetime is the 
+			// same as this object.        
+			
+			const newColumns:IList = _columns;
+			if (newColumns)
+			{
+				newColumns.addEventListener(CollectionEvent.COLLECTION_CHANGE, columns_collectionChangeHandler, false, 0); //, true);
+				for (index = 0; index < newColumns.length; index++)
+				{
+					
+					var newColumn:GridColumn = GridColumn(newColumns.getItemAt(index));
+					newColumn.setGrid(this);
+					newColumn.setColumnIndex(index);
+					
+				}
+			}
+			
+			columnsChanged = true;
+			generatedColumns = false;        
+			invalidateProperties();
+			invalidateSize();
+			invalidateDisplayList();
+			
+			dispatchChangeEvent("columnsChanged");             
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function getColumnsLength():uint
+		{
+			const columns:IList = columns;
+			return (columns) ? columns.length : 0;
+		}
+		
+		/**
+		 *  @private
+		 *  This method is similar to mx.controls.DataGrid/ls().
+		 */
+		private function generateColumns():IList
+		{
+			var item:Object = typicalItem;
+			if (!item && dataProvider && (dataProvider.length > 0))
+				item = dataProvider.getItemAt(0);
+			
+			var itemColumns:IList = null;
+			if (item)
+			{
+				itemColumns = new ArrayList();
+				const classInfo:Object = ObjectUtil.getClassInfo(item, ["uid", "mx_internal_uid"]);
+				if (classInfo)
+				{
+					for each (var property:QName in classInfo.properties)
+					{
+						
+						var column:GridColumn = new GridColumn();
+						column.dataField = property.localName;
+						itemColumns.addItem(column);
+						
+					}
+				}
+			}
+			
+			return itemColumns;
+		}
+		
+		//----------------------------------
+		//  dataProvider
+		//----------------------------------
+		
+		private var _dataProvider:IList = null;
+		private var dataProviderChanged:Boolean;
+		
+		[Bindable("dataProviderChanged")]
+		[Inspectable(category="Data")]
+		
+		/**
+		 *  A list of data items that correspond to the rows in the grid.   
+		 *  Each grid column is associated with a property of the 
+		 *  data items to display that property in the grid <i>cells</i>.
+		 * 
+		 *  @default null
+		 * 
+		 *  @see spark.components.Grid#columns
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get dataProvider():IList
+		{
+			return _dataProvider;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set dataProvider(value:IList):void
+		{
+			if (_dataProvider == value)
+				return;
+			
+			const oldDataProvider:IList = dataProvider;
+			if (oldDataProvider)
+				oldDataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, dataProvider_collectionChangeHandler);
+			
+			_dataProvider = value;
+			
+			// The listener is a local method, so creating a weak reference to it (last addEventListener 
+			// parameter) is safe, since the listener's lifetime is the same as this object.
+			
+			const newDataProvider:IList = dataProvider;
+			if (newDataProvider)
+				newDataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, dataProvider_collectionChangeHandler, false, 0); //, true);        
+			
+			dataProviderChanged = true;
+			invalidateProperties();
+			invalidateSize();
+			invalidateDisplayList();
+			
+			dispatchChangeEvent("dataProviderChanged");
+		}
+		
+		//----------------------------------
+		//  dataTipField
+		//----------------------------------
+		
+		private var _dataTipField:String = null;
+		
+		[Bindable("dataTipFieldChanged")]
+		[Inspectable(category="Data", defaultValue="null")]
+		
+		/**
+		 *  @copy spark.components.gridClasses.GridColumn#dataTipField
+		 * 
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get dataTipField():String
+		{
+			return _dataTipField;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set dataTipField(value:String):void
+		{
+			if (_dataTipField == value)
+				return;
+			
+			_dataTipField = value;
+			invalidateDisplayList();
+			dispatchChangeEvent("dataTipFieldChanged");
+		}
+		
+		//----------------------------------
+		//  dataTipFunction
+		//----------------------------------
+		
+		private var _dataTipFunction:Function = null;
+		
+		[Bindable("dataTipFunctionChanged")]
+		[Inspectable(category="Data")]
+		
+		/**
+		 *  @copy spark.components.gridClasses.GridColumn#dataTipFunction
+		 *
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get dataTipFunction():Function
+		{
+			return _dataTipFunction;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set dataTipFunction(value:Function):void
+		{
+			if (_dataTipFunction == value)
+				return;
+			
+			_dataTipFunction = value;
+			invalidateDisplayList();        
+			dispatchChangeEvent("dataTipFunctionChanged");
+		}    
+		
+		
+		//----------------------------------
+		//  doubleClickMode
+		//----------------------------------
+		private var _doubleClickMode:String = GridDoubleClickMode.ROW;
+		
+		[Bindable("doubleClickModeChanged")]
+		[Inspectable(category="General", enumeration="cell,grid,row", defaultValue="row")]
+		
+		/**
+		 *  The doubleClick mode of the control.  Possible values are:
+		 *  <code>GridDoubleClickMode.CELL</code>, 
+		 *  <code>GridDoubleClickMode.GRID</code>, 
+		 *  <code>GridDoubleClickMode.ROW</code>, 
+		 * 
+		 *  <p>Changing the doubleClickMode changes the double click
+		 *  criteria for firing the doubleClick event</p>
+		 *
+		 *  @default GridDoubleClickMode.ROW
+		 * 
+		 *  @see spark.components.gridClasses.GridDoubleClickMode
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function get doubleClickMode():String
+		{
+			return _doubleClickMode;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set doubleClickMode(newValue:String):void
+		{
+			if (newValue == _doubleClickMode)
+			{
+				return;
+			}
+			
+			switch(newValue)
+			{
+				case GridDoubleClickMode.CELL:
+				case GridDoubleClickMode.GRID:
+				case GridDoubleClickMode.ROW:
+				{
+					_doubleClickMode = newValue;
+					
+					dispatchChangeEvent("doubleClickModeChanged");
+					
+					break;
+				}
+			}
+		}
+		
+		
+		//----------------------------------
+		//  gridDimensions (mx_internal)
+		//----------------------------------
+		
+		private var _gridDimensions:GridDimensions = null;
+		
+		mx_internal function get gridDimensions():GridDimensions
+		{
+			if (!_gridDimensions)
+				_gridDimensions = new GridDimensions();
+			
+			return _gridDimensions;
+		}
+		
+		//----------------------------------
+		//  itemRenderer
+		//----------------------------------
+		
+		private var _itemRenderer:IFactory = null;
+		private var itemRendererChanged:Boolean = false;
+		
+		[Bindable("itemRendererChanged")]
+		[Inspectable(category="Data")]
+		
+		/**
+		 *  The item renderer that's used for columns that do not specify one.
+		 * 
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function get itemRenderer():IFactory
+		{
+			return _itemRenderer;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set itemRenderer(value:IFactory):void
+		{
+			if (_itemRenderer == value)
+				return;
+			
+			_itemRenderer = value;
+			
+			itemRendererChanged = true;
+			invalidateProperties();
+			invalidateSize();
+			invalidateDisplayList();
+			
+			dispatchChangeEvent("itemRendererChanged");
+		}    
+		
+		//----------------------------------
+		//  columnSeparator
+		//----------------------------------
+		
+		private var _columnSeparator:IFactory = null;
+		
+		[Bindable("columnSeparatorChanged")]
+		
+		/**
+		 *  A visual element displayed between each column.
+		 * 
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get columnSeparator():IFactory
+		{
+			return _columnSeparator;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set columnSeparator(value:IFactory):void
+		{
+			if (_columnSeparator == value)
+				return;
+			
+			_columnSeparator = value;
+			invalidateDisplayList();
+			dispatchChangeEvent("columnSeparatorChanged");
+		}    
+		
+		//----------------------------------
+		//  gridSelection (mx_internal)
+		//----------------------------------
+		
+		/**
+		 *  @private
+		 */
+		
+		private var _gridSelection:GridSelection;
+		mx_internal function get gridSelection():GridSelection
+		{
+			if (!_gridSelection)
+				_gridSelection = createGridSelection();
+			
+			return _gridSelection;
+		}
+		
+		/**
+		 *  @private
+		 *  If this Grid is serving as a DataGrid skin part, then this property is created 
+		 *  by DataGrid/partAdded() and then set here.   It is only set once, unless that 
+		 *  "grid" part is removed, at which point it's set to null.
+		 */
+		
+		mx_internal function set gridSelection(value:GridSelection):void
+		{
+			_gridSelection = value;
+		}
+		
+		//----------------------------------
+		//  dataGrid
+		//----------------------------------
+		
+		private var _dataGrid:DataGrid = null;
+		
+		[Bindable("dataGridChanged")]
+		
+		/**
+		 *  The DataGrid control for which this Grid is used as the grid skin part.
+		 * 
+		 *  @default null
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get dataGrid():DataGrid
+		{
+			return _dataGrid;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set dataGrid(value:DataGrid):void
+		{
+			if (_dataGrid == value)
+				return;
+			
+			_dataGrid = value;
+			dispatchChangeEvent("dataGridChanged");
+		}
+		
+		//----------------------------------
+		//  lockedColumnCount
+		//----------------------------------
+		
+		private var _lockedColumnCount:int = 0;
+		
+		[Bindable("lockedColumnCountChanged")]
+		[Inspectable(category="General", defaultValue="0", minValue="0")]	
+		
+		/**
+		 *  The first lockedColumnCount columns are "locked", i.e. they do not scroll horizontally. 
+		 *  If lockedColumnCount is zero (the default) then changes to the horizontalScrollPosition
+		 *  affect all columns.
+		 * 
+		 *  <p>The locked columns are displayed in the topGridView and, if lockedRowCount is also
+		 *  greater than zero, the topLeftGridView.  The locked columns are separated from the remaining 
+		 *  columns by a lockedColumnSeparator.</p>
+		 * 
+		 *  @default 0
+		 * 
+		 *  @see spark.components.gridClasses.GridColumn#topGridView 
+		 *  @see spark.components.gridClasses.GridColumn#topLeftGridView
+		 * 	@see spark.components.gridClasses.GridColumn#lockedColumnSeparator
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 5.0
+		 */
+		public function get lockedColumnCount():int
+		{
+			return _lockedColumnCount;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set lockedColumnCount(value:int):void
+		{
+			if (_lockedColumnCount == value)
+				return;
+			
+			invalidateProperties();
+			invalidateSize();
+			invalidateDisplayList();
+			
+			_lockedColumnCount = value;
+			dispatchChangeEvent("lockedColumnCountChanged");
+		}
+		
+		//----------------------------------
+		//  lockedColumnsSeparator
+		//----------------------------------
+		
+		private var _lockedColumnsSeparator:IFactory = null;
+		
+		[Bindable("lockedColumnsSeparatorChanged")]
+		
+		/**
+		 *  A visual element displayed between the locked and unlocked columns.  The factory value of this
+		 *  property is used to create the lockedColumnsSeparatorElement.
+		 * 
+		 *  @see spark.components.Grid#lockedRowsSeparatorElement	
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 5.0
+		 * 
+		 *  @default null
+		 */
+		public function get lockedColumnsSeparator():IFactory
+		{
+			return _lockedColumnsSeparator;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set lockedColumnsSeparator(value:IFactory):void
+		{
+			if (_lockedColumnsSeparator == value)
+				return;
+			
+			_lockedColumnsSeparator = value;
+			invalidateDisplayList();
+			dispatchChangeEvent("lockedColumnsSeparatorChanged");
+		} 
+		
+		//----------------------------------
+		//  lockedRowCount
+		//----------------------------------
+		
+		private var _lockedRowCount:int = 0;
+		
+		[Bindable("lockedRowCountChanged")]
+		[Inspectable(category="General", defaultValue="0", minValue="0")]	
+		
+		/**
+		 *  The first lockedRowCount rows are "locked", i.e. they do not scroll vertically. 
+		 *  If lockedRowCount is zero (the default) then changes to the verticalScrollPosition
+		 *  affect all rows.
+		 * 
+		 *  <p>The locked rows are displayed in the leftGridView and, if lockedColumnCount is also
+		 *  greater than zero, the topLeftGridView.  The locked rows are separated from the remaining 
+		 *  rows by a lockedRowSeparator.</p>
+		 * 
+		 *  @default 0
+		 * 
+		 *  @see spark.components.gridClasses.GridColumn#leftGridView 
+		 *  @see spark.components.gridClasses.GridColumn#topLeftGridView
+		 * 	@see spark.components.gridClasses.GridColumn#lockedRowSeparator
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 5.0
+		 */
+		public function get lockedRowCount():int
+		{
+			return _lockedRowCount;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set lockedRowCount(value:int):void
+		{
+			if (_lockedRowCount == value)
+				return;
+			
+			invalidateProperties();
+			invalidateSize();
+			invalidateDisplayList();
+			
+			_lockedRowCount = value;
+			dispatchChangeEvent("lockedRowCountChanged");
+		}
+		
+		//----------------------------------
+		//  lockedRowsSeparator
+		//----------------------------------
+		
+		private var _lockedRowsSeparator:IFactory = null;
+		
+		[Bindable("lockedRowsSeparatorChanged")]
+		
+		/**
+		 *  A visual element displayed between the locked and unlocked rows.   The factory value of this
+		 *  property is used to create the lockedRowsSeparatorElement.
+		 * 
+		 *  @default null
+		 * 
+		 *  @see spark.components.Grid#lockedRowsSeparatorElement
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 5.0
+		 */
+		public function get lockedRowsSeparator():IFactory
+		{
+			return _lockedRowsSeparator;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set lockedRowsSeparator(value:IFactory):void
+		{
+			if (_lockedRowsSeparator == value)
+				return;
+			
+			_lockedRowsSeparator = value;
+			invalidateDisplayList();
+			dispatchChangeEvent("lockedRowsSeparatorChanged");
+		}	
+		
+		//----------------------------------
+		//  preserveSelection (delegates to gridSelection.preserveSelection)
+		//----------------------------------
+		
+		[Inspectable(category="General", defaultValue="true")]
+		
+		/**
+		 *  If <code>true</code>, the selection is preserved when the data provider 
+		 *  refreshes its collection. 
+		 *  Because this refresh requires each item in the selection to be saved, 
+		 *  this action is not desirable if the selection is large.
+		 *
+		 *  @default true
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get preserveSelection():Boolean
+		{
+			return gridSelection.preserveSelection;
+		}
+		
+		/**
+		 *  @private
+		 */    
+		public function set preserveSelection(value:Boolean):void
+		{
+			gridSelection.preserveSelection = value;
+		}
+		
+		//----------------------------------
+		//  requestedMaxRowCount
+		//----------------------------------
+		
+		private var _requestedMaxRowCount:int = 10;
+		
+		[Inspectable(category="General", defaultValue="10", minValue="-1")]
+		
+		/**
+		 *  The measured height of the grid is large enough to display 
+		 *  no more than <code>requestedMaxRowCount</code> rows.
+		 * 
+		 *  <p>This property has no effect if any of the following are true;
+		 *  <ul>
+		 *      <li><code>requestedRowCount</code> is set.</li>
+		 *      <li>The actual size of the grid has been explicitly set.</li>
+		 *  </ul>
+		 *  </p>
+		 * 
+		 *  @default 10
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get requestedMaxRowCount():int
+		{
+			return _requestedMaxRowCount;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set requestedMaxRowCount(value:int):void
+		{
+			if (_requestedMaxRowCount == value)
+				return;
+			
+			_requestedMaxRowCount = value;
+			invalidateSize();
+		}      
+		
+		//----------------------------------
+		//  requestedMinRowCount
+		//----------------------------------
+		
+		private var _requestedMinRowCount:int = -1;
+		
+		[Inspectable(category="General", minValue="-1")]
+		
+		/**
+		 *  The measured height of this grid is large enough to display 
+		 *  at least <code>requestedMinRowCount</code> rows.
+		 * 
+		 *  <p>This property has no effect if any of the following are true;
+		 *  <ul>
+		 *      <li><code>requestedRowCount</code> is set.</li>
+		 *      <li>The actual size of the grid has been explicitly set.</li>
+		 *  </ul>
+		 *  </p>
+		 * 
+		 *  @default -1
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get requestedMinRowCount():int
+		{
+			return _requestedMinRowCount;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set requestedMinRowCount(value:int):void
+		{
+			if (_requestedMinRowCount == value)
+				return;
+			
+			_requestedMinRowCount = value;
+			invalidateSize();
+		}    
+		
+		//----------------------------------
+		//  requestedRowCount
+		//----------------------------------
+		
+		private var _requestedRowCount:int = -1;
+		
+		[Inspectable(category="General", minValue="-1")]
+		
+		/**
+		 *  The measured height of this grid is large enough to display 
+		 *  the first <code>requestedRowCount</code> rows. 
+		 * 
+		 *  <p>If <code>requestedRowCount</code> is -1, then the measured
+		 *  size will be big enough for all of the layout elements.</p>
+		 * 
+		 *  <p>If the actual size of the grid has been explicitly set,
+		 *  then this property has no effect.</p>
+		 * 
+		 *  @default -1
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4
+		 */
+		public function get requestedRowCount():int
+		{
+			return _requestedRowCount;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set requestedRowCount(value:int):void
+		{
+			if (_requestedRowCount == value)
+				return;
+			
+			_requestedRowCount = value;
+			invalidateSize();
+		}
+		
+		//----------------------------------
+		//  requestedMinColumnCount
+		//----------------------------------
+		
+		private var _requestedMinColumnCount:int = -1;
+		
+		[Inspectable(category="General", minValue="-1")]
+		
+		/**
+		 *  The measured width of this grid is large enough to display 
+		 *  at least <code>requestedMinColumnCount</code> columns.
+		 * 
+		 *  <p>This property has no effect if any of the following are true;
+		 *  <ul>
+		 *      <li><code>requestedColumnCount</code> is set.</li>
+		 *      <li>The actual size of the grid has been explicitly set.</li>
+		 *      <li>The grid is inside a Scroller component.</li>
+		 *  </ul>
+		 *  </p>
+		 *  
+		 *  @default -1
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get requestedMinColumnCount():int
+		{
+			return _requestedMinColumnCount;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set requestedMinColumnCount(value:int):void
+		{
+			if (_requestedMinColumnCount == value)
+				return;
+			
+			_requestedMinColumnCount = value;
+			invalidateSize();
+		}   
+		
+		//----------------------------------
+		//  requestedColumnCount
+		//----------------------------------
+		
+		private var _requestedColumnCount:int = -1;
+		
+		[Inspectable(category="General", minValue="-1")]
+		
+		/**
+		 *  The measured width of this grid is large enough to display 
+		 *  the first <code>requestedColumnCount</code> columns. 
+		 *  If <code>requestedColumnCount</code> is -1, then the measured
+		 *  width is big enough for all of the columns.
+		 * 
+		 *  <p>If the actual size of the grid has been explicitly set,
+		 *  then this property has no effect.</p>
+		 * 
+		 *  @default -1
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get requestedColumnCount():int
+		{
+			return _requestedColumnCount;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set requestedColumnCount(value:int):void
+		{
+			if (_requestedColumnCount == value)
+				return;
+			
+			_requestedColumnCount = value;
+			invalidateSize();
+		}    
+		
+		//----------------------------------
+		//  requireSelection
+		//----------------------------------
+		
+		[Inspectable(category="General", defaultValue="false")]
+		
+		/**
+		 *  If <code>true</code> and the <code>selectionMode</code> property is not 
+		 *  <code>GridSelectionMode.NONE</code>, an item must always be selected 
+		 *  in the grid.
+		 *
+		 *  @default false
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get requireSelection():Boolean
+		{
+			return gridSelection.requireSelection;
+		}
+		
+		/**
+		 *  @private
+		 */    
+		public function set requireSelection(value:Boolean):void
+		{
+			gridSelection.requireSelection = value;
+			
+			if (value)
+				invalidateDisplayListFor("selectionIndicator");
+		}
+		
+		//----------------------------------
+		//  resizableColumns
+		//----------------------------------
+		
+		private var _resizableColumns:Boolean = true;
+		
+		[Bindable("resizableColumnsChanged")]
+		[Inspectable(category="General", defaultValue="true")]
+		
+		/**
+		 *  Indicates whether the user can change the size of the columns.
+		 *  If <code>true</code>, the user can stretch or shrink the columns of 
+		 *  the DataGrid control by dragging the grid lines between the header cells.
+		 *  If <code>true</code>, individual columns must also have their 
+		 *  <code>resizable</code> properties set to <code>false</code> to 
+		 *  prevent the user from resizing a particular column.  
+		 *
+		 *  @default true
+		 *    
+		 *  @see spark.components.gridClasses.GridColumn
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get resizableColumns():Boolean
+		{
+			return _resizableColumns;
+		}
+		
+		/**
+		 *  @private
+		 */        
+		public function set resizableColumns(value:Boolean):void
+		{
+			if (value == resizableColumns)
+				return;
+			
+			_resizableColumns = value;        
+			dispatchChangeEvent("resizableColumnsChanged");            
+		}
+		
+		//----------------------------------
+		//  rowBackground
+		//----------------------------------
+		
+		private var _rowBackground:IFactory = null;
+		
+		[Bindable("rowBackgroundChanged")]
+		
+		/**
+		 *  A visual element that's displays the background for each row.  
+		 * 
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get rowBackground():IFactory
+		{
+			return _rowBackground;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set rowBackground(value:IFactory):void
+		{
+			if (_rowBackground == value)
+				return;
+			
+			_rowBackground = value;
+			invalidateDisplayList();
+			dispatchChangeEvent("rowBackgroundChanged");
+		}
+		
+		//----------------------------------
+		//  rowHeight
+		//----------------------------------
+		
+		private var _rowHeight:Number = NaN;
+		private var rowHeightChanged:Boolean;
+		
+		[Bindable("rowHeightChanged")]
+		[Inspectable(category="General", minValue="0.0")]
+		
+		/**
+		 *  If <code>variableRowHeight</code> is <code>false</code>, then 
+		 *  this property specifies the actual height of each row, in pixels.
+		 * 
+		 *  <p>If <code>variableRowHeight</code> is <code>true</code>, 
+		 *  the value of this property is used as the estimated
+		 *  height for rows that haven't been scrolled into view yet, rather
+		 *  than the preferred height of renderers configured with the <code>typicalItem</code>.
+		 *  Similarly, when the Grid pads its display with empty rows, this property
+		 *  specifies the empty rows' height.</p>
+		 * 
+		 *  <p>If <code>variableRowHeight</code> is <code>false</code>, 
+		 *  the default value of this property is the maximum preferred height
+		 *  of the per-column renderers created for the <code>typicalItem</code>.</p>
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get rowHeight():Number
+		{
+			return _rowHeight;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set rowHeight(value:Number):void
+		{
+			if (_rowHeight == value)
+				return;
+			
+			_rowHeight = value;
+			rowHeightChanged = true;        
+			invalidateProperties();
+			
+			dispatchChangeEvent("rowHeightChanged");            
+		}
+		
+		/**
+		 *  @private
+		 */	
+		private function setFixedRowHeight(value:Number):void
+		{
+			if (_rowHeight == value)
+				return;
+			
+			_rowHeight = value;
+			dispatchChangeEvent("rowHeightChanged");		
+		}
+		
+		//----------------------------------
+		//  rowSeparator
+		//----------------------------------
+		
+		private var _rowSeparator:IFactory = null;
+		
+		[Bindable("rowSeparatorChanged")]
+		
+		/**
+		 *  A visual element that's displayed in between each row.
+		 * 
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get rowSeparator():IFactory
+		{
+			return _rowSeparator;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set rowSeparator(value:IFactory):void
+		{
+			if (_rowSeparator == value)
+				return;
+			
+			_rowSeparator = value;
+			invalidateDisplayList();
+			dispatchChangeEvent("rowSeparatorChanged");
+		}    
+		
+		//----------------------------------
+		//  selectedCell
+		//----------------------------------
+		
+		[Bindable("selectionChange")]
+		[Bindable("valueCommit")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> 
+		 *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns the first
+		 *  selected cell starting at row 0 column 0 and progressing through each
+		 *  column in a row before moving to the next row.
+		 * 
+		 *  <p>When the user changes the selection by interacting with the 
+		 *  control, the control dispatches the <code>selectionChange</code> 
+		 *  event. When the user changes the selection programmatically, the 
+		 *  control dispatches the <code>valueCommit</code> event.</p>
+		 * 
+		 *  <p> This property is intended to be used to initialize or bind to the
+		 *  selection in MXML markup.  The <code>setSelectedCell()</code> method 
+		 *  should be used for programatic selection updates, for example 
+		 *  when writing a keyboard or mouse event handler. </p> 
+		 *
+		 *  @default null
+		 * 
+		 *  @return CellPosition of the first selected cell or null if there is
+		 *  no cell selection.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectedCell():CellPosition
+		{
+			var selectedCells:Vector.<CellPosition> = gridSelection.allCells();
+			return selectedCells.length ? selectedCells[0] : null;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set selectedCell(value:CellPosition):void
+		{
+			const rowIndex:int = (value) ? value.rowIndex : -1;
+			const columnIndex:int = (value) ? value.columnIndex : -1;
+			
+			// Defer the selection change if we haven't been initialized
+			
+			if (!initialized)
+			{
+				// Append a deferred operation function that selects the specified cell
+				
+				var f:Function = function():void
+				{
+					if ((rowIndex != -1) && (columnIndex != -1))
+						setSelectedCell(rowIndex, columnIndex);
+					else
+						clearSelection();
+				}
+				
+				deferredOperations.push(f);  // function f() to be called by commitProperties()
+				invalidateProperties();
+			}
+			else
+			{
+				if ((rowIndex != -1) && (columnIndex != -1))
+					setSelectedCell(rowIndex, columnIndex);
+				else
+					clearSelection();            
+			}
+		}        
+		
+		//----------------------------------
+		//  selectedCells
+		//----------------------------------
+		
+		[Bindable("selectionChange")]
+		[Bindable("valueCommit")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> 
+		 *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns a Vector
+		 *  of CellPosition objects representing the positions of the selected
+		 *  cells in the grid.
+		 * 
+		 *  <p>When the user changes the selection by interacting with the 
+		 *  control, the control dispatches the <code>selectionChange</code> 
+		 *  event. When the user changes the selection programmatically, the 
+		 *  control dispatches the <code>valueCommit</code> event.</p>
+		 * 
+		 *  <p> This property is intended to be used to initialize or bind to the
+		 *  selection in MXML markup.  The <code>setSelectedCell()</code> method 
+		 *  should be used for programatic selection updates, for example when 
+		 *  writing a keyboard or mouse event handler. </p> 
+		 * 
+		 *  <p>The default value is an empty <code>Vector.&lt;CellPosition&gt;</code></p>
+		 * 
+		 *  @return Vector of CellPosition objects where each element represents
+		 *  a selected cell.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectedCells():Vector.<CellPosition>
+		{
+			return gridSelection.allCells();
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set selectedCells(value:Vector.<CellPosition>):void
+		{
+			// Defensively deep-copy the incoming value; tolerate value=null
+			
+			var valueCopy:Vector.<CellPosition> = new Vector.<CellPosition>(0);
+			if (value)
+			{
+				for each (var cell:CellPosition in value)
+				valueCopy.push(new CellPosition(cell.rowIndex, cell.columnIndex));
+			}
+			
+			// Defer the selection change if we haven't been initialized
+			
+			if (!initialized)
+			{        
+				// Append a deferred operation function that selects the specified cells
+				
+				var f:Function = function():void
+				{
+					doSetSelectedCells(valueCopy);
+				}
+				deferredOperations.push(f);  // function f() to be called by commitProperties()
+				invalidateProperties();
+			}
+			else
+			{
+				doSetSelectedCells(valueCopy);
+			}
+		}          
+		
+		//----------------------------------
+		//  selectedIndex
+		//----------------------------------
+		
+		[Bindable("selectionChange")]
+		[Bindable("valueCommit")]
+		[Inspectable(category="General", defaultValue="-1")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
+		 *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns the
+		 *  rowIndex of the first selected row. 
+		 * 
+		 *  <p>When the user changes the selection by interacting with the 
+		 *  control, the control dispatches the <code>selectionChange</code> 
+		 *  event. When the user changes the selection programmatically, the 
+		 *  control dispatches the <code>valueCommit</code> event.</p>
+		 * 
+		 *  <p> This property is intended to be used to initialize or bind to the
+		 *  selection in MXML markup.  The <code>setSelectedCell()</code> method should be used
+		 *  for programatic selection updates, for example when writing a keyboard
+		 *  or mouse event handler. </p> 
+		 *
+		 *  @default -1
+		 * 
+		 *  @return rowIndex of first selected row or -1 if there are no
+		 *  selected rows.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectedIndex():int
+		{
+			var selectedRows:Vector.<int> = gridSelection.allRows();
+			return (selectedRows.length > 0) ? selectedRows[0] : -1;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set selectedIndex(value:int):void
+		{
+			// Defer the selection change if we haven't been initialized
+			
+			if (!initialized)
+			{        
+				// Append a deferred operation function that selects the specified index
+				
+				var f:Function = function():void
+				{
+					if (value != -1)
+						setSelectedIndex(value);
+					else
+						clearSelection();
+				}
+				deferredOperations.push(f);  // function f() to be called by commitProperties()
+				invalidateProperties();
+			}
+			else
+			{
+				if (value != -1)
+					setSelectedIndex(value);
+				else
+					clearSelection();
+			}
+		}
+		
+		//----------------------------------
+		//  selectedIndices
+		//----------------------------------
+		
+		[Bindable("selectionChange")]
+		[Bindable("valueCommit")]
+		[Inspectable(category="General")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
+		 *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns a Vector of 
+		 *  the selected rows indices.  For all other selection modes, this 
+		 *  method has no effect.
+		 * 
+		 *  <p>When the user changes the selection by interacting with the 
+		 *  control, the control dispatches the <code>selectionChange</code> 
+		 *  event. When the user changes the selection programmatically, the 
+		 *  control dispatches the <code>valueCommit</code> event.</p>
+		 * 
+		 *  <p> This property is intended to be used to initialize or bind to the
+		 *  selection in MXML markup.  The setSelectedCell() method should be used
+		 *  for programatic selection updates, for example when writing a keyboard
+		 *  or mouse event handler. </p> > 
+		 *
+		 *  <p>The default value is an empty <code>Vector.&lt;int&gt;</code></p>
+		 * 
+		 *  @return Vector of ints where each element is the index in 
+		 *  data provider of the selected row.
+		 *  
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectedIndices():Vector.<int>
+		{
+			return gridSelection.allRows();
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set selectedIndices(value:Vector.<int>):void
+		{
+			// Defensively copy the incoming value; tolerate value=null
+			
+			const valueCopy:Vector.<int> = (value) ? value.concat() : new Vector.<int>(0);
+			
+			// Defer the selection change if we haven't been initialized
+			
+			if (!initialized)
+			{        
+				// Append a deferred operation function that selects the specified indices
+				
+				var f:Function = function():void
+				{
+					doSetSelectedIndices(valueCopy);
+				};
+				deferredOperations.push(f);  // function f() to be called by commitProperties()
+				invalidateProperties();
+			}
+			else
+			{
+				doSetSelectedIndices(valueCopy);
+			}
+		}        
+		
+		//----------------------------------
+		//  selectedItem
+		//----------------------------------
+		
+		[Bindable("selectionChange")]
+		[Bindable("valueCommit")]
+		[Inspectable(category="General", defaultValue="null")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
+		 *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns the 
+		 *  item in the the data provider that is currently selected or
+		 *  <code>undefined</code> if no rows are selected.  
+		 * 
+		 *  <p>When the user changes the selection by interacting with the 
+		 *  control, the control dispatches the <code>selectionChange</code> 
+		 *  event. When the user changes the selection programmatically, the 
+		 *  control dispatches the <code>valueCommit</code> event.</p>
+		 * 
+		 *  <p> This property is intended to be used to initialize or bind to the
+		 *  selection in MXML markup.  The <code>setSelectedCell()</code> method should be used
+		 *  for programatic selection updates, for example when writing a keyboard
+		 *  or mouse event handler. </p> 
+		 *  
+		 *  @default null
+		 * 
+		 *  @return Vector of data provider items.
+		 *  
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectedItem():Object
+		{
+			var rowIndex:int = selectedIndex;
+			if (rowIndex == -1)
+				return undefined;
+			
+			return getDataProviderItem(rowIndex);           
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set selectedItem(value:Object):void
+		{
+			// Defer the selection change if we haven't been initialized
+			
+			if (!initialized)
+			{        
+				// Append a deferred operation function that selects the specified item
+				
+				var f:Function = function():void
+				{
+					if (!dataProvider)
+						return;
+					
+					const rowIndex:int = dataProvider.getItemIndex(value);
+					if (rowIndex == -1)
+						clearSelection();
+					else
+						setSelectedIndex(rowIndex);
+				}
+				deferredOperations.push(f);  // function f() to be called by commitProperties()
+				invalidateProperties();
+			}
+			else
+			{
+				if (!dataProvider)
+					return;
+				
+				const rowIndex:int = dataProvider.getItemIndex(value);
+				if (rowIndex == -1)
+					clearSelection();
+				else
+					setSelectedIndex(rowIndex);            
+			}
+		}        
+		
+		//----------------------------------
+		//  selectedItems
+		//----------------------------------
+		
+		[Bindable("selectionChange")]
+		[Bindable("valueCommit")]
+		[Inspectable(category="General")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
+		 *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns a Vector of 
+		 *  the dataProvider items that are currently selected.
+		 * 
+		 *  <p>When the user changes the selection by interacting with the 
+		 *  control, the control dispatches the <code>selectionChange</code> 
+		 *  event. When the user changes the selection programmatically, the 
+		 *  control dispatches the <code>valueCommit</code> event.</p>
+		 * 
+		 *  <p> This property is intended to be used to initialize or bind to the
+		 *  selection in MXML markup.  The setSelectedCell() method should be used
+		 *  for programatic selection updates, for example when writing a keyboard
+		 *  or mouse event handler. </p> 
+		 *  
+		 *  <p>The default value is an empty <code>Vector.&lt;Object&gt;</code></p>
+		 * 
+		 *  @return Vector of data provider items.
+		 *  
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectedItems():Vector.<Object>
+		{
+			var rowIndices:Vector.<int> = selectedIndices;
+			if (rowIndices.length == 0)
+				return undefined;
+			
+			var items:Vector.<Object> = new Vector.<Object>();
+			
+			for each (var rowIndex:int in rowIndices)        
+			items.push(dataProvider.getItemAt(rowIndex));
+			
+			return items;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set selectedItems(value:Vector.<Object>):void
+		{
+			// Defensively copy the incoming value; tolerate value=null
+			
+			const valueCopy:Vector.<Object> = (value) ? value.concat() : new Vector.<Object>(0);
+			
+			// Defer the selection change if we haven't been initialized
+			
+			if (!initialized)
+			{        
+				// Append a deferred operation function that selects the specified items        
+				
+				var f:Function = function():void
+				{
+					doSetSelectedItems(valueCopy);
+				}
+				deferredOperations.push(f);  // function f() to be called by commitProperties()
+				invalidateProperties();
+			}
+			else
+			{
+				doSetSelectedItems(valueCopy);
+			}
+		}        
+		
+		//----------------------------------
+		//  selectionIndicator
+		//----------------------------------
+		
+		private var _selectionIndicator:IFactory = null;
+		
+		[Bindable("selectionIndicatorChanged")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
+		 *  a visual element that's displayed for each selected row, 
+		 *  If <code>selectionMode</code> is
+		 *  <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>,
+		 *  a visual element displayed for each selected cell.
+		 *  
+		 *  @default null
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectionIndicator():IFactory
+		{
+			return _selectionIndicator;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set selectionIndicator(value:IFactory):void
+		{
+			if (_selectionIndicator == value)
+				return;
+			
+			_selectionIndicator = value;
+			invalidateDisplayListFor("selectionIndicator");
+			dispatchChangeEvent("selectionIndicatorChanged");
+		}    
+		
+		//----------------------------------
+		//  selectionLength (delegates to gridSelection.selectionLength)
+		//----------------------------------
+		
+		[Bindable("selectionChange")]
+		[Bindable("valueCommit")]
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
+		 *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
+		 *  returns the number of selected rows. 
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELLS</code> 
+		 *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, 
+		 *  returns the number of selected cells.
+		 * 
+		 *  @default 0
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectionLength():int
+		{
+			return gridSelection.selectionLength;   
+		}
+		
+		//----------------------------------
+		//  selectionMode (delegates to gridSelection.selectionMode)
+		//----------------------------------
+		
+		[Bindable("selectionModeChanged")]
+		[Inspectable(category="General", enumeration="none,singleRow,multipleRows,singleCell,multipleCells", defaultValue="singleRow")]
+		
+		/**
+		 *  The selection mode of the control.  Possible values are:
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, 
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
+		 *  <code>GridSelectionMode.NONE</code>, 
+		 *  <code>GridSelectionMode.SINGLE_CELL</code>, and 
+		 *  <code>GridSelectionMode.SINGLE_ROW</code>.
+		 * 
+		 *  <p>Changing the selectionMode causes the current selection to be 
+		 *  cleared and the caretRowIndex and caretColumnIndex to be set to -1.</p>
+		 *
+		 *  @default GridSelectionMode.SINGLE_ROW
+		 * 
+		 *  @see spark.components.gridClasses.GridSelectionMode
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get selectionMode():String
+		{
+			return gridSelection.selectionMode;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set selectionMode(value:String):void
+		{
+			if (selectionMode == value)
+				return;
+			
+			gridSelection.selectionMode = value;
+			if (selectionMode != value) // value wasn't a valid GridSelectionMode constant
+				return;
+			
+			initializeAnchorPosition();
+			if (!requireSelection)
+				initializeCaretPosition();
+			
+			invalidateDisplayListFor("selectionIndicator");
+			
+			dispatchChangeEvent("selectionModeChanged");
+		}
+		
+		//----------------------------------
+		//  showCaret
+		//----------------------------------
+		
+		/**
+		 *  @private
+		 */
+		private var _showCaret:Boolean = false;
+		
+		[Bindable("showCaretChanged")]    
+		
+		/**
+		 *  Determines if the caret is visible.
+		 *  TBD: when is this property automatically set?
+		 */
+		public function get showCaret():Boolean
+		{
+			return _showCaret;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set showCaret(value:Boolean):void
+		{
+			if (_showCaret == value)
+				return;
+			
+			_showCaret = value;
+			invalidateDisplayListFor("caretIndicator");        
+			dispatchChangeEvent("showCaretChanged");       
+		}    
+		
+		//----------------------------------
+		//  showDataTips
+		//----------------------------------
+		
+		private var _showDataTips:Boolean = false;
+		
+		[Bindable("showDataTipsChanged")]
+		[Inspectable(category="Data", defaultValue="false")]
+		
+		/**
+		 *  If <code>true</code> then a dataTip is displayed for all visible cells.  
+		 *  If <code>false</code>, the default,
+		 *  then a dataTip is only displayed if the column's 
+		 *  <code>showDataTips</code> property is <code>true</code>.
+		 * 
+		 *  @default false
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get showDataTips():Boolean
+		{
+			return _showDataTips;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set showDataTips(value:Boolean):void
+		{
+			if (_showDataTips == value)
+				return;
+			
+			_showDataTips = value;
+			invalidateDisplayList();
+			dispatchChangeEvent("showDataTipsChanged");
+		}
+		
+		//----------------------------------
+		//  typicalItem
+		//----------------------------------
+		
+		private var _typicalItem:Object = null;
+		private var typicalItemChanged:Boolean = false;
+		
+		[Bindable("typicalItemChanged")]
+		[Inspectable(category="Data")]
+		
+		/**
+		 *  The grid's layout ensures that columns whose width is not specified are wide
+		 *  enough to display an item renderer for this default data provider item.  
+		 *  If a typical item is not specified, then the first data provider item is used.
+		 * 
+		 *  <p>Restriction: if the <code>typicalItem</code> is an IVisualItem, it must not 
+		 *  also be a member of the data provider.</p>
+		 * 
+		 *  @default null
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get typicalItem():Object
+		{
+			return _typicalItem;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set typicalItem(value:Object):void
+		{
+			if (_typicalItem == value)
+				return;
+			
+			_typicalItem = value;
+			invalidateTypicalItemRenderer();
+			dispatchChangeEvent("typicalItemChanged");
+		}
+		
+		/**
+		 *  Clears cached column width data that had been based on the 
+		 *  <code>typicalItem</code> property, and requests a new layout pass.   
+		 *  Call this method if some aspect of the <code>typicalItem</code> 
+		 *  has changed that should be reflected by the Grid's layout.  
+		 * 
+		 *  <p>This method is called automatically if the <code>typicalItem</code> 
+		 *  is changed directly. That means if the property is set to a new value 
+		 *  that is not "==" to current value.</p>
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.5 
+		 */
+		public function invalidateTypicalItemRenderer():void
+		{
+			typicalItemChanged = true;       
+			invalidateProperties();
+			invalidateSize();
+			invalidateDisplayList();
+		}
+		
+		//----------------------------------
+		//  variableRowHeight
+		//----------------------------------
+		
+		private var _variableRowHeight:Boolean = false;
+		private var variableRowHeightChanged:Boolean = false;
+		
+		[Bindable("variableRowHeightChanged")]
+		[Inspectable(category="General", defaultValue="false")]
+		
+		/**
+		 *  If <code>true</code>, each row's height is the maximum of 
+		 *  preferred heights of the cells displayed so far.
+		 * 
+		 *  <p>If <code>false</code>, the height of each row is just 
+		 *  the value of the <code>rowHeight</code> property.
+		 *  If <code>rowHeight</code> isn't specified, then the height of 
+		 *  each row is defined by the <code>typicalItem</code> property.</p>
+		 * 
+		 *  @default false
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function get variableRowHeight():Boolean
+		{
+			return _variableRowHeight;
+		}
+		
+		/**
+		 *  @private
+		 */        
+		public function set variableRowHeight(value:Boolean):void
+		{
+			if (value == variableRowHeight)
+				return;
+			
+			_variableRowHeight = value;        
+			variableRowHeightChanged = true;        
+			invalidateProperties();
+			
+			dispatchChangeEvent("variableRowHeightChanged");            
+		}
+		
+		//----------------------------------
+		//  gridView
+		//----------------------------------
+		
+		private var _gridView:IFactory = null;
+		
+		[Bindable("gridViewChanged")]
+		
+		/**
+		 *  Used to initialize this grid's gridViews: centerGridView, leftGridView, topGridView, topLeftGridView. 
+		 *  GridViews are created as needed, depending on the values of lockedRowCount and lockedColumnCount.
+		 * 
+		 *  @default null.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 5.0
+		 */
+		public function get gridView():IFactory
+		{
+			return _gridView;
+		}
+		
+		/**
+		 *  @private
+		 */        
+		public function set gridView(value:IFactory):void
+		{
+			if (value == _gridView)
+				return;
+			
+			_gridView = value;
+			invalidateProperties();
+			
+			// TBD clear everything
+			
+			dispatchChangeEvent("gridViewChanged");            
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  GridSelection Cover Methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  If <code>selectionMode</code> is 
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, selects all rows and
+		 *  removes the caret or if <code>selectionMode</code> is 
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code> selects all cells  
+		 *  and removes the caret.  For all other selection modes, this method 
+		 *  has no effect.
+		 *
+		 *  <p>If items are added to the <code>dataProvider</code> or 
+		 *  <code>columns</code> are added after this method is called, the
+		 *  new rows or cells in the new column will be selected.</p>
+		 * 
+		 *  <p>This implicit "selectAll" mode ends when any of the following occur:
+		 *  <ul>
+		 *    <li>selection is cleared using <code>clearSelection</code></li>
+		 *    <li>selection reset using one of <code>setSelectedCell</code>, 
+		 *    <code>setSelectedCells</code>, <code>setSelectedIndex</code>, 
+		 *    <code>selectIndices</code></li>
+		 *    <li><code>dataProvider</code> is refreshed and <code>preserveSelection</code> is false</li>
+		 *    <li><code>dataProvider</code> is reset</li>
+		 *    <li><code>columns</code> is refreshed, 
+		 *    <code>preserveSelection</code> is <code>false</code> and 
+		 *    <code>selectionMode</code> is 
+		 *    <code>GridSelectionMode.MULTIPLE_CELLS</code></li>
+		 *    <li><code>columns</code> is reset and <code>selectionMode</code> is 
+		 *    <code>GridSelectionMode.MULTIPLE_CELLS</code></li> 
+		 *  </ul></p>
+		 * 
+		 *  @return <code>true</code> if the selection changed.
+		 *    
+		 *  @see spark.components.Grid#clearSelection
+		 *  @see spark.components.Grid#selectIndices
+		 *  @see spark.components.Grid#setSelectedCell
+		 *  @see spark.components.Grid#setSelectedCells
+		 *  @see spark.components.Grid#setSelectedIndex
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function selectAll():Boolean
+		{           
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.selectAll();
+			if (selectionChanged)
+			{               
+				initializeCaretPosition();               
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		/**
+		 *  Removes all of the selected rows and cells, if <code>selectionMode</code>  
+		 *  is not <code>GridSelectionMode.NONE</code>.  Removes the caret and
+		 *  sets the anchor to the initial item.
+		 *
+		 *  @return <code>true</code> if the selection changed.
+		 *  <code>false</code> if there was nothing previously selected.
+		 *    
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function clearSelection():Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.removeAll();
+			if (selectionChanged)
+			{
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			// Remove caret and reset the anchor.
+			initializeCaretPosition();
+			initializeAnchorPosition();
+			
+			return selectionChanged;
+		}
+		
+		//----------------------------------
+		//  selection for rows
+		//----------------------------------    
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code>
+		 *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns <code>true</code> 
+		 *  if the row at <code>index</code> is in the current selection.
+		 * 
+		 *  <p>The <code>rowIndex</code> is the index in the data provider
+		 *  of the item containing the selected cell.</p>
+		 *
+		 *  @param rowIndex The 0-based row index of the row.
+		 * 
+		 *  @return <code>true</code> if the selection contains the row.
+		 *    
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function selectionContainsIndex(rowIndex:int):Boolean 
+		{
+			return gridSelection.containsRow(rowIndex);
+		}
+		
+		/**
+		 *  If <code>selectionMode</code> is 
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns <code>true</code> 
+		 *  if the rows in <code>indices</code> are in the current selection.
+		 * 
+		 *  @param rowIndices Vector of 0-based row indices to include in selection. 
+		 * 
+		 *  @return <code>true</code> if the current selection contains these rows.
+		 *    
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function selectionContainsIndices(rowIndices:Vector.<int>):Boolean 
+		{
+			return gridSelection.containsRows(rowIndices);
+		}
+		
+		/**
+		 *  If <code>selectionMode</code>
+		 *  is <code>GridSelectionMode.SINGLE_ROW</code> or 
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, sets the selection and 
+		 *  the caret position to this row.
+		 *  For all other selection modes, this method has no effect.
+		 * 
+		 *  <p>The <code>rowIndex</code> is the index in the data provider
+		 *  of the item containing the selected cell.</p>
+		 *
+		 *  @param rowIndex The 0-based row index of the cell.
+		 *
+		 *  @return <code>true</code> if if no errors.
+		 *  <code>false</code> if <code>index</code> is invalid, or
+		 *  the <code>selectionMode</code> is invalid. 
+		 *    
+		 *  @see spark.components.Grid#caretColumnIndex
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function setSelectedIndex(rowIndex:int):Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.setRow(rowIndex);
+			if (selectionChanged)
+			{
+				caretRowIndex = rowIndex;
+				caretColumnIndex = -1;
+				
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		/**
+		 *  If <code>selectionMode</code>
+		 *  is <code>GridSelectionMode.MULTIPLE_ROWS</code>, adds this row to
+		 *  the selection and sets the caret position to this row.
+		 *  For all other selection modes, this method has no effect.
+		 * 
+		 *  <p>The <code>rowIndex</code> is the index in the data provider 
+		 *  of the item containing the selected cell.</p>
+		 *
+		 *  @param rowIndex The 0-based row index of the cell.
+		 *
+		 *  @return <code>true</code> if no errors.
+		 *  <code>false</code> if <code>index</code> is invalid or
+		 *  the <code>selectionMode</code> is invalid. 
+		 *    
+		 *  @see spark.components.Grid#caretColumnIndex
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function addSelectedIndex(rowIndex:int):Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.addRow(rowIndex);
+			if (selectionChanged)
+			{
+				caretRowIndex = rowIndex;
+				caretColumnIndex = -1;                
+				
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		/**
+		 *  If <code>selectionMode</code>
+		 *  is <code>GridSelectionMode.SINGLE_ROW</code> or 
+		 *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, removes this row
+		 *  from the selection and sets the caret position to this row.
+		 *  For all other selection modes, this method has no effect.
+		 * 
+		 *  <p>The <code>rowIndex</code> is the index in the data provider 
+		 *  of the item containing the selected cell.</p>
+		 *
+		 *  @param rowIndex The 0-based row index of the cell.
+		 *
+		 *  @return <code>true</code> if no errors.
+		 *  <code>false</code> if <code>index</code> is invalid or
+		 *  the <code>selectionMode</code> is invalid. 
+		 *       
+		 *  @see spark.components.Grid#caretColumnIndex
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function removeSelectedIndex(rowIndex:int):Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.removeRow(rowIndex);
+			if (selectionChanged)
+			{
+				caretRowIndex = rowIndex;
+				caretColumnIndex = -1;
+				
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_ROWS</code>,
+		 *  sets the selection to the specfied rows and the caret position to
+		 *  <code>endRowIndex</code>.
+		 *  For all other selection modes, this method has no effect.
+		 * 
+		 *  <p>Each index represents an item in the data provider  
+		 *  to include in the selection.</p>
+		 *
+		 *  @param rowIndex 0-based row index of the first row in the selection.
+		 * 
+		 *  @param rowCount Number of rows in the selection.
+		 * 
+		 *  @return <code>true</code> if no errors.
+		 *  <code>false</code> if any of the indices are invalid, 
+		 *  if <code>startRowIndex</code> is not less than or equal to 
+		 *  <code>endRowIndex</code>, or the <code>selectionMode</code> is invalid. 
+		 *    
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function selectIndices(rowIndex:int, rowCount:int):Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.setRows(rowIndex, rowCount);
+			if (selectionChanged)
+			{
+				caretRowIndex = rowIndex + rowCount - 1;
+				caretColumnIndex = -1;
+				
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		//----------------------------------
+		//  selection for cells
+		//----------------------------------    
+		
+		/**
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code>
+		 *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns <code>true</code> 
+		 *  if the cell is in the current selection.
+		 * 
+		 *  <p>The <code>rowIndex</code> must be between 0 and the
+		 *  length of the data provider.  The <code>columnIndex</code>
+		 *  must be between 0 and the length of <code>columns</code>. </p>
+		 *
+		 *  @param rowIndex The 0-based row index of the cell.
+		 *
+		 *  @param columnIndex The 0-based column index of the cell.
+		 *  
+		 *  @return <code>true</code> if the current selection contains the cell.
+		 * 
+		 *  @see spark.components.Grid#columns
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function selectionContainsCell(rowIndex:int, columnIndex:int):Boolean
+		{
+			return gridSelection.containsCell(rowIndex, columnIndex);
+		}
+		
+		/**
+		 *  If <code>selectionMode</code> is 
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns <code>true</code> 
+		 *  if the cells in the cell region are in the current selection.
+		 * 
+		 *  <p>The <code>rowIndex</code> must be between 0 and the
+		 *  length of the data provider.  The <code>columnIndex</code>
+		 *  must be between 0 and the length of <code>columns</code>. </p>
+		 *
+		 *  @param rowIndex The 0-based row index of the cell.
+		 *
+		 *  @param columnIndex The 0-based column index of the cell.
+		 *  
+		 *  @param rowCount Number of rows, starting at <code>rowIndex</code> to 
+		 *  include in the cell region.
+		 *
+		 *  @param columnCount Number of columns, starting at 
+		 *  <code>columnIndex</code> to include in the cell region.
+		 * 
+		 *  @return <code>true</code> if the current selection contains all 
+		 *  the cells in the cell region.
+		 * 
+		 *  @see spark.components.Grid#columns
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function selectionContainsCellRegion(rowIndex:int, columnIndex:int, 
+													rowCount:int, columnCount:int):Boolean
+		{
+			return gridSelection.containsCellRegion(rowIndex, columnIndex, 
+				rowCount, columnCount);
+		}
+		
+		/**
+		 *  If <code>selectionMode</code>
+		 *  is <code>GridSelectionMode.SINGLE_CELL</code> or 
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, sets the selection
+		 *  and the caret position to this cell.
+		 *  For all other selection modes, this method has no effect.
+		 * 
+		 *  <p>The <code>rowIndex</code> is the index in the data provider 
+		 *  of the item containing the selected cell.  The <code>columnIndex</code>
+		 *  is the index in <code>columns</code> of the column containing the
+		 *  selected cell.</p>
+		 *
+		 *  @param rowIndex The 0-based row index of the cell.
+		 *
+		 *  @param columnIndex The 0-based column index of the cell.
+		 * 
+		 *  @return <code>true</code> if no errors.
+		 *  <code>false</code> if <code>rowIndex</code> 
+		 *  or <code>columnIndex</code> is invalid or the <code>selectionMode</code> 
+		 *  is invalid.     
+		 *  
+		 *  @see spark.components.Grid#caretColumnIndex
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#columns
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function setSelectedCell(rowIndex:int, columnIndex:int):Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.setCell(rowIndex, columnIndex);
+			if (selectionChanged)
+			{
+				caretRowIndex = rowIndex;
+				caretColumnIndex = columnIndex;
+				
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		/**
+		 *  If <code>selectionMode</code>
+		 *  is <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, adds the cell to
+		 *  the selection and sets the caret position to the cell.
+		 *  For all other selection modes, this method has no effect.
+		 * 
+		 *  <p>The <code>rowIndex</code> is the index in the data provider 
+		 *  of the item containing the selected cell.  The <code>columnIndex</code>
+		 *  is the index in <code>columns</code> of the column containing the
+		 *  selected cell.</p>
+		 *
+		 *  @param rowIndex The 0-based row index of the cell.
+		 *
+		 *  @param columnIndex The 0-based column index of the cell.
+		 * 
+		 *  @return <code>true</code> if no errors.
+		 *  <code>false</code> if <code>rowIndex</code> 
+		 *  or <code>columnIndex</code> is invalid, or the <code>selectionMode</code> 
+		 *  is invalid.     
+		 *  
+		 *  @see spark.components.Grid#caretColumnIndex
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#columns
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function addSelectedCell(rowIndex:int, columnIndex:int):Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.addCell(rowIndex, columnIndex);
+			if (selectionChanged)
+			{
+				caretRowIndex = rowIndex;
+				caretColumnIndex = columnIndex;
+				
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		/**
+		 *  If <code>selectionMode</code>
+		 *  is <code>GridSelectionMode.SINGLE_CELL</code> or
+		 *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, removes the cell
+		 *  from the selection and sets the caret position to the cell.
+		 *  For all other selection modes, this method has no effect.
+		 * 
+		 *  <p>The <code>rowIndex</code> is the index in the data provider 
+		 *  of the item containing the selected cell.  The <code>columnIndex</code>
+		 *  is the index in <code>columns</code> of the column containing the
+		 *  selected cell.</p>
+		 *
+		 *  @param rowIndex The 0-based row index of the cell.
+		 *
+		 *  @param columnIndex The 0-based column index of the cell.
+		 * 
+		 *  @return <code>true</code> if no errors.
+		 *  <code>false</code> if <code>rowIndex</code> 
+		 *  or <code>columnIndex</code> is invalid or the <code>selectionMode</code> 
+		 *  is invalid.     
+		 *  
+		 *  @see spark.components.Grid#caretColumnIndex
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#columns
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function removeSelectedCell(rowIndex:int, columnIndex:int):Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.removeCell(rowIndex, columnIndex);
+			if (selectionChanged)
+			{
+				caretRowIndex = rowIndex;
+				caretColumnIndex = columnIndex;
+				
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		/** 
+		 *  If <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_CELLS</code>,
+		 *  sets the selection to all the cells in the cell region and the
+		 *  caret position to the last cell in the cell region.
+		 *  For all other selection modes, this method has no effect.
+		 * 
+		 *  <p>The <code>rowIndex</code> is the index in the data provider 
+		 *  of the item containing the origin of the cell region.  
+		 *  The <code>columnIndex</code>
+		 *  is the index in <code>columns</code> of the column containing the
+		 *  origin of the cell region.</p>
+		 *
+		 *  <p>This method has no effect if the cell region is not wholly
+		 *  contained within the grid.</p>
+		 * 
+		 *  @param rowIndex The 0-based row index of the origin of the cell region.
+		 *
+		 *  @param columnIndex The 0-based column index of the origin of the cell 
+		 *  region.
+		 *  
+		 *  @param rowCount Number of rows, starting at <code>rowIndex</code> to 
+		 *  include in the cell region.
+		 *
+		 *  @param columnCount Number of columns, starting at 
+		 *  <code>columnIndex</code> to include in the cell region.
+		 * 
+		 *  @return <code>true</code> if no errors.
+		 *  <code>false</code> if the cell region is invalid or 
+		 *  the <code>selectionMode</code> is invalid.     
+		 *  
+		 *  @see spark.components.Grid#caretColumnIndex
+		 *  @see spark.components.Grid#caretRowIndex
+		 *  @see spark.components.Grid#columns
+		 *  @see spark.components.Grid#dataProvider
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function selectCellRegion(rowIndex:int, columnIndex:int, 
+										 rowCount:uint, columnCount:uint):Boolean
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			const selectionChanged:Boolean = gridSelection.setCellRegion(
+				rowIndex, columnIndex, 
+				rowCount, columnCount);
+			if (selectionChanged)
+			{
+				caretRowIndex = rowIndex + rowCount - 1;
+				caretColumnIndex = columnIndex + columnCount - 1;
+				
+				invalidateDisplayListFor("selectionIndicator");
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			}
+			
+			return selectionChanged;
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Selection API Helper Methods
+		//
+		//-------------------------------------------------------------------------- 
+		
+		/**
+		 * For performance reasons, make sure validateClient, anchor and caret updates,
+		 * and selectionIndicator and VALUE_COMMIT updates are only done once.
+		 */
+		private function doSetSelectedCells(valueCopy:Vector.<CellPosition>):void
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			gridSelection.removeAll();
+			for each (var cell:CellPosition in valueCopy)
+			{
+				gridSelection.addCell(cell.rowIndex, cell.columnIndex);
+			}
+			
+			doFinalizeSetSelection(cell ? cell.rowIndex : -1, 
+				cell ? cell.columnIndex : -1);
+		}
+		
+		/**
+		 * For performance reasons, make sure validateClient, anchor and caret updates,
+		 * and selectionIndicator and VALUE_COMMIT updates are only done once.
+		 */
+		private function doSetSelectedIndices(valueCopy:Vector.<int>):void
+		{
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			var newRowIndex:int = -1;
+			gridSelection.removeAll();
+			for each (newRowIndex in valueCopy)
+			{
+				gridSelection.addRow(newRowIndex);
+			}
+			
+			doFinalizeSetSelection(newRowIndex, -1);
+		}
+		
+		/**
+		 * For performance reasons, make sure validateClient, anchor and caret updates,
+		 * and selectionIndicator and VALUE_COMMIT updates are only done once.
+		 */
+		private function doSetSelectedItems(valueCopy:Vector.<Object>):void
+		{
+			if (!dataProvider)
+				return;
+			
+			// Need to apply pending dataProvider and column changes so selection
+			// isn't reset after it is set here.
+			/*if (invalidatePropertiesFlag)
+				UIComponentGlobals.layoutManager.validateClient(this, false);*/
+			
+			var newRowIndex:int = -1;        
+			gridSelection.removeAll();
+			for each (var item:Object in valueCopy)
+			{
+				newRowIndex = dataProvider.getItemIndex(item);
+				gridSelection.addRow(newRowIndex);
+			}
+			
+			doFinalizeSetSelection(newRowIndex, -1);
+		}
+		
+		/**
+		 * Finished selection operations so update the anchor, caret, selection indicators and
+		 * trigger the selection bindings.
+		 */
+		private function doFinalizeSetSelection(rowIndex:int, columnIndex:int):void
+		{
+			initializeAnchorPosition();       
+			caretRowIndex = rowIndex
+			caretColumnIndex = columnIndex
+			
+			invalidateDisplayListFor("selectionIndicator");
+			dispatchFlexEvent(FlexEvent.VALUE_COMMIT);      
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  GridViewLayout Cover Methods, Properties
+		//
+		//-------------------------------------------------------------------------- 
+		
+		/** 
+		 *  @private
+		 *  Update the scroll position so that the virtual Grid element at the specified
+		 *  index is visible.   Note that getScrollPositionDeltaToElement() is only 
+		 *  approximate when variableRowHeight=true, so calling this method once will
+		 *  not necessarily scroll far enough to expose the specified element.
+		 * 
+		 *  @returns True if either the horizontalScrollPosition or verticalScrollPosition changed.
+		 */
+		
+		private function scrollToIndex(view:GridView, elementIndex:int, scrollHorizontally:Boolean, scrollVertically:Boolean):Boolean
+		{
+		/*	var spDelta:Point = view.gridViewLayout.getScrollPositionDeltaToElement(elementIndex);
+			
+			// The cell is completely visible or the specified index is no longer valid so punt.
+			
+			if (!spDelta)
+				return false; 
+			
+			// If the required scroll is locked then punt
+			
+			if ((spDelta.y != 0) && view.gridViewLayout.verticalScrollingLocked)
+				return false;
+			
+			if ((spDelta.x != 0) && view.gridViewLayout.horizontalScrollingLocked)
+				return false;
+			
+			// Update the scroll positions
+			
+			var scrollChanged:Boolean = false;
+			
+			if (scrollHorizontally)
+			{
+				horizontalScrollPosition += spDelta.x;
+				scrollChanged = spDelta.x != 0;
+			}
+			
+			if (scrollVertically)
+			{
+				verticalScrollPosition += spDelta.y;
+				scrollChanged = scrollChanged || spDelta.y != 0;
+			}
+			
+			return scrollChanged;*/ return false;
+		}
+		
+		
+		/**
+		 *  If necessary, set the <code>verticalScrollPosition</code> and 
+		 *  <code>horizontalScrollPosition</code> properties so that the 
+		 *  specified cell is completely visible. 
+		 *  If <code>rowIndex</code> is -1 and <code>columnIndex</code> is specified, 
+		 *  then just adjust the <code>horizontalScrollPosition</code>
+		 *  so that the specified column is visible. 
+		 *  If <code>columnIndex</code> is -1 and <code>rowIndex</code>
+		 *  is specified, then just adjust the <code>verticalScrollPosition</code> 
+		 *  so that the specified row is visible.
+		 * 
+		 *  @param rowIndex The 0-based row index of the item renderer's cell, or -1 to specify a column.
+		 *  
+		 *  @param columnIndex The 0-based column index of the item renderer's cell, or -1 to specify a row.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function ensureCellIsVisible(rowIndex:int = -1, columnIndex:int = -1):void
+		{
+			
+			const columns:IList = this.columns;
+			
+			// Check that each index is within range.
+			if (!columns || columnIndex < -1 || columnIndex >= columns.length || 
+				!dataProvider || rowIndex < -1 || rowIndex >= dataProvider.length || 
+				(columnIndex == -1 && rowIndex == -1))
+				return;
+			
+			// Check to see if any columns are visible or specified column is visible.
+			
+			if ((columnIndex == -1 && getNextVisibleColumnIndex(-1) == -1) || 
+				(columnIndex != -1 && !(GridColumn(columns.getItemAt(columnIndex)).visible)))
+				return;
+			
+			const scrollHorizontally:Boolean = columnIndex != -1;
+			const scrollVertically:Boolean = rowIndex != -1;
+			
+			// If the row, column, or cell is locked, then there's nothing to do.
+			
+			if ((columnIndex < lockedColumnCount) && (rowIndex < lockedRowCount))
+				return;
+			
+			if (!scrollVertically && (columnIndex < lockedColumnCount)) 
+				return;
+			
+			if (!scrollHorizontally && (rowIndex < lockedRowCount))
+				return;        
+			
+			// If called after the layout cache is cleared, need to rebuild the cache
+			// before accessing visible rows/columns and attempting to scroll.
+			//if (getVisibleRowIndices().length == 0 || getVisibleColumnIndices().length == 0)
+			//	validateNow();
+			
+			// When not scrolling horizontally, columnIndex can just be 0.
+			if (!scrollHorizontally)
+				columnIndex = 0;
+			
+			// Find the GridView the specified cell is contained by and punt if it's not visible
+			
+			const cellGridView:GridView = getGridViewAt(rowIndex, columnIndex);	
+			if (!cellGridView || 
+				(cellGridView.getLayoutBoundsX() >= getLayoutBoundsWidth()) || 
+				(cellGridView.getLayoutBoundsY() >= getLayoutBoundsHeight()))
+				return;
+			
+			// If the row index isn't specified, use the first one that's visible.
+			if (!scrollVertically)
+			{
+				// const visibleRowIndices:Vector.<int> = cellGridView.gridViewLayout.getVisibleRowIndices();
+				// rowIndex = (visibleRowIndices.length > 0) ?  visibleRowIndices[0] : 0;
+			}
+			
+			// A cell's index as defined by LayoutBase it's just its position
+			// in the row-major linear ordering of the grid's cells.
+			/*
+			const gridViewLayout:GridViewLayout = cellGridView.gridViewLayout;
+			const cellViewRowIndex:int = rowIndex - gridViewLayout.viewRowIndex;
+			const cellViewColumnIndex:int  = columnIndex - gridViewLayout.viewColumnIndex;
+			const cellElementIndex:int = (cellViewRowIndex * gridViewLayout.columnsView.length) + cellViewColumnIndex;
+			
+			var scrollChanged:Boolean = false;
+			var firstScroll:Boolean = true;
+			
+			// Iterate until we've scrolled elementIndex at least partially into view.
+			do
+			{
+				scrollChanged = scrollToIndex(cellGridView, cellElementIndex, scrollHorizontally, scrollVertically);
+				
+				// Fixed row heights, and we're only scrolling vertically.
+				if (!variableRowHeight && !scrollHorizontally)
+					return;
+				
+				// Bail. This could indicate there is a bug but it avoids an infinite loop.
+				// scrollToIndex() then validateNow() then scrollToIndex() again and
+				// no changes in scroll position.
+				if (!firstScroll && !scrollChanged)
+					return;
+				
+				validateNow();
+				
+				firstScroll = false;
+			}
+			while (!isCellVisible(scrollVertically ? rowIndex : -1, scrollHorizontally ? columnIndex : -1));
+			
+			// At this point we've only ensured that the requested cell is at least 
+			// partially visible.  Ensure that it's completely visible.
+			
+			scrollToIndex(cellGridView, cellElementIndex, scrollHorizontally, scrollVertically);
+			*/
+		}        
+		
+		/**
+		 *  Return the data provider indices and padding indices of the 
+		 *  currently visible rows.  
+		 *  Indices which are greater than or equal to the 
+		 *  <code>dataProvider</code> length represent padding rows.
+		 *  Note that the item renderers for the first and last rows 
+		 *  may only be partially visible. 
+		 *  The returned vector's contents are in the order they're displayed.
+		 * 
+		 *  @return A vector of the visible row indices.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */ 
+		/*
+		public function getVisibleRowIndices():Vector.<int>
+		{
+			const gridLayout:GridLayout = layout as GridLayout;
+			const topGridView:GridView = gridLayout.topGridView;        
+			const centerGridView:GridView = gridLayout.centerGridView;
+			
+			if (!centerGridView)
+				return new Vector.<int>(0);
+			
+			// const centerRowIndices:Vector.<int> = centerGridView.gridViewLayout.getVisibleRowIndices();
+			// if (!topGridView)
+			//	return centerRowIndices;
+			
+			const topRowIndices:Vector.<int> = topGridView.gridViewLayout.getVisibleRowIndices();
+			return topRowIndices.concat(centerRowIndices);
+		}
+		*/
+		/**
+		 *  Return the indices of the currently visible columns.  Note that the 
+		 *  item renderers for the first and last columns may only be partially visible.  
+		 *  The returned vector's contents are in the order they're displayed.
+		 * 
+		 *  <p>The following example function uses this method to compute a vector of 
+		 *  visible GridColumn objects.</p>
+		 *  <pre>
+		 *  function getVisibleColumns():Vector.&lt;GridColumn&gt;
+		 *  {
+		 *      var visibleColumns = new Vector.&lt;GridColumn&gt;;
+		 *      for each (var columnIndex:int in grid.getVisibleColumnIndices())
+		 *          visibleColumns.push(grid.columns.getItemAt(columnIndex));
+		 *      return visibleColumns;
+		 *  }
+		 *  </pre> 
+		 * 
+		 *  @return A vector of the visible column indices.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */ 
+		/*		
+		public function getVisibleColumnIndices():Vector.<int>
+		{
+			const gridLayout:GridLayout = layout as GridLayout;
+			const leftGridView:GridView = gridLayout.leftGridView;        
+			const centerGridView:GridView = gridLayout.centerGridView;
+			
+			//const centerColumnIndices:Vector.<int> = centerGridView.gridViewLayout.getVisibleColumnIndices();
+			//if (!leftGridView)
+			//	return centerColumnIndices;
+			
+			const leftColumnIndices:Vector.<int> = leftGridView.gridViewLayout.getVisibleColumnIndices();
+			return leftColumnIndices.concat(centerColumnIndices);
+		}
+		*/
+		/**
+		 *  Returns the current pixel bounds of the specified cell, or null if no such cell exists.
+		 *  Cell bounds are reported in grid coordinates.
+		 * 
+		 *  <p>If all of the columns for the the specfied row and all of the rows preceeding 
+		 *  it have not yet been scrolled into view, the returned bounds may only be an approximation, 
+		 *  based on all of the columns' <code>typicalItem</code>s.</p>
+		 * 
+		 *  @param rowIndex The 0-based index of the row.
+		 *
+		 *  @param columnIndex The 0-based index of the column. 
+		 *
+		 *  @return A <code>Rectangle</code> that represents the cell's pixel bounds, or null.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */ 
+		public function getCellBounds(rowIndex:int, columnIndex:int):Rectangle
+		{
+			return gridDimensions.getCellBounds(rowIndex, columnIndex);
+		}
+		
+		/**
+		 *  Returns the current pixel bounds of the specified row, or null if no such row exists.
+		 *  Row bounds are reported in grid coordinates.
+		 *
+		 *  <p>If all of the columns for the the specfied row and all of the rows preceeding 
+		 *  it have not yet been scrolled into view, the returned bounds may only be an approximation, 
+		 *  based on all of the columns' <code>typicalItem</code>s.</p>
+		 * 
+		 *  @param rowIndex The 0-based index of the row.
+		 * 
+		 *  @return A <code>Rectangle</code> that represents the row's pixel bounds, or null.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function getRowBounds(rowIndex:int):Rectangle
+		{
+			return gridDimensions.getRowBounds(rowIndex);      
+		}
+		
+		/**
+		 *  Returns the current pixel bounds of the specified column, or null if no such column exists.
+		 *  Column bounds are reported in grid coordinates.
+		 * 
+		 *  <p>If all of the cells in the specified column have not yet been scrolled into view, the 
+		 *  returned bounds may only be an approximation, based on the column's <code>typicalItem</code>.</p>
+		 *  
+		 *  @param columnIndex The 0-based index of the column. 
+		 *
+		 *  @return A <code>Rectangle</code> that represents the column's pixel bounds, or null.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function getColumnBounds(columnIndex:int):Rectangle
+		{
+			return gridDimensions.getColumnBounds(columnIndex);
+		}
+		
+		/**
+		 *  Returns the row index corresponding to the specified grid coordinates,
+		 *  or -1 if the coordinates are out of bounds. 
+		 * 
+		 *  <p>If all of the columns or rows for the grid have not yet been scrolled
+		 *  into view, the returned index may only be an approximation, 
+		 *  based on all of the columns' <code>typicalItem</code>s.</p>
+		 *  
+		 *  @param x The x coordinate.
+		 * 
+		 *  @param y The y coordinate.
+		 *
+		 *  @return The index of the row corresponding to the specified coordinates.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function getRowIndexAt(x:Number, y:Number):int
+		{
+			return gridDimensions.getRowIndexAt(x, y);
+		}
+		
+		/**
+		 *  Returns the column index corresponding to the specified grid coordinates,
+		 *  or -1 if the coordinates are out of bounds. 
+		 * 
+		 *  <p>If all of the columns or rows for the grid have not yet been scrolled
+		 *  into view, the returned index may only be an approximation, 
+		 *  based on all of the columns' <code>typicalItem</code>s.</p>
+		 *  
+		 *  @param x The pixel's x coordinate relative to the grid.
+		 *
+		 *  @param y The pixel's y coordinate relative to the grid.
+		 *
+		 *  @return The index of the column, or -1 if the coordinates are out of bounds. 
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function getColumnIndexAt(x:Number, y:Number):int
+		{
+			return gridDimensions.getColumnIndexAt(x, y); 
+		}
+		
+		/**
+		 *  Return the width of the specified column.  If the cell's entire bounds
+		 *  aren't needed, this method is more efficient than <code>getColumnBounds().width</code>.
+		 * 
+		 *  <p>If the specified column's width property isn't defined, then the returned value 
+		 *  may only be an approximation.  The actual column width is only computed after the column
+		 *  has been scrolled into view.</p>
+		 * 
+		 *  @param columnIndex The 0-based index of the column. 
+		 *  @return The width of the specified column.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		
+		public function getColumnWidth(columnIndex:int):Number
+		{
+			const column:GridColumn = getGridColumn(columnIndex);
+			return (column && !isNaN(column.width)) ? column.width : gridDimensions.getColumnWidth(columnIndex);
+		}
+		
+		/**
+		 *  Return the row and column indices of the cell that overlaps the pixel at the 
+		 *  specified grid coordinate.
+		 *  If no such cell exists, null is returned.
+		 * 
+		 *  <p>The example function below uses this method to compute the value of the 
+		 *  <code>dataField</code> for a grid cell.</p> 
+		 *  <pre>
+		 *  function getCellData(x:Number, y:Number):Object
+		 *  {
+		 *      var cell:CellPosition = getCellAt(x, y);
+		 *      if (!cell)
+		 *          return null;
+		 *      var GridColumn:column = grid.columns.getItemAt(cell.columnIndex);
+		 *      return grid.dataProvider.getItemAt(cell.rowIndex)[column.dataField];
+		 *  }
+		 *  </pre> 
+		 * 
+		 *  @param x The pixel's x coordinate relative to the grid.
+		 *
+		 *  @param y The pixel's y coordinate relative to the grid.
+		 *
+		 *  @return The cell position, or null. 
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function getCellAt(x:Number, y:Number):CellPosition
+		{
+			const rowIndex:int = gridDimensions.getRowIndexAt(x, y);
+			const columnIndex:int = gridDimensions.getColumnIndexAt(x, y);
+			if ((rowIndex == -1) || (columnIndex == -1))
+				return null;
+			return new CellPosition(rowIndex, columnIndex);
+		}
+		
+		/**
+		 *  Returns a vector of CellPosition objects whose 
+		 *  <code>rowIndex</code> and <code>columnIndex</code> properties specify the 
+		 *  row and column indices of the cells that overlap the specified grid region.  
+		 *  If no such cells exist, an empty vector is returned.
+		 *  
+		 *  @param x The x coordinate of the pixel at the origin of the region, relative to the grid.
+		 * 
+		 *  @param x The x coordinate of the pixel at the origin of the region, relative to the grid. 
+		 * 
+		 *  @param w The width of the region, in pixels. 
+		 * 
+		 *  @param h The height of the region, in pixels. 
+		 *  
+		 *  @return A vector of objects like <code>Vector.&lt;Object&gt;([{rowIndex:0, columnIndex:0}, ...])</code>. 
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function getCellsAt(x:Number, y:Number, w:Number, h:Number):Vector.<CellPosition>
+		{ 
+			var cells:Vector.<CellPosition> = new Vector.<CellPosition>;
+			
+			if (w <= 0 || h <= 0)
+				return cells;
+			
+			// Get the row/column indexes of the corners of the region.
+			var topLeft:CellPosition = getCellAt(x, y);
+			var bottomRight:CellPosition = getCellAt(x + w, y + h);
+			if (!topLeft || !bottomRight)
+				return cells;
+			
+			for (var rowIndex:int = topLeft.rowIndex; 
+				rowIndex <= bottomRight.rowIndex; rowIndex++)
+			{
+				for (var columnIndex:int = topLeft.columnIndex; 
+					columnIndex <= bottomRight.columnIndex; columnIndex++)
+				{
+					cells.push(new CellPosition(rowIndex, columnIndex));
+				}
+			}
+			
+			return cells;
+		}
+		
+		/**
+		 *  Return the X coordinate of the specified cell's origin.  If the cell's entire bounds
+		 *  aren't needed, this method is more efficient than <code>getCellBounds().x</code>.
+		 * 
+		 *  <p>If all of the columns for the the specfied row and all of the rows preceeding 
+		 *  it have not yet been scrolled into view, the returned value may only be an approximation, 
+		 *  based on all of the columns' <code>typicalItem</code>s.</p>
+		 * 
+		 *  @param rowIndex The 0-based index of the row.
+		 *  @param columnIndex The 0-based index of the column. 
+		 *  @return The x coordindate of the specified cell's origin.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function getCellX(rowIndex:int, columnIndex:int):Number
+		{ 
+			return gridDimensions.getCellX(rowIndex, columnIndex);
+		}
+		
+		/**
+		 *  Return the Y coordinate of the specified cell's origin.  If the cell's entire bounds
+		 *  aren't needed, this method is more efficient than <code>getCellBounds().y</code>.
+		 * 
+		 *  <p>If all of the columns for the the specfied row and all of the rows preceeding 
+		 *  it have not yet been scrolled into view, the returned value may only be an approximation, 
+		 *  based on all of the columns' <code>typicalItem</code>s.</p>
+		 * 
+		 *  @param rowIndex The 0-based index of the row.
+		 *  @param columnIndex The 0-based index of the column. 
+		 *  @return The y coordindate of the specified cell's origin.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function getCellY(rowIndex:int, columnIndex:int):Number
+		{ 
+			return gridDimensions.getCellY(rowIndex, columnIndex);
+		}      
+		
+		/**
+		 *  If the requested item renderer is visible, returns a reference to 
+		 *  the item renderer currently displayed at the specified cell.  
+		 *  Note that once the returned item renderer is no longer visible it may be 
+		 *  recycled and its properties reset.  
+		 * 
+		 *  <p>If the requested item renderer is not visible. then 
+		 *  each time this method is called, a new item renderer is created.  
+		 *  The new item renderer is not visible</p>
+		 * 
+		 *  <p>If the specified column does not have an explicit width, then the width
+		 *  of this cell is based on the <code>typicalItem</code>.  
+		 *  If a <code>typicalItem</code> was not specified or has not been measured yet, 
+		 *  then the item renderer's width defaults to <code>150</code>.</p>
+		 * 
+		 *  <p>If the grid property <code>variableRowHeight</code> is 
+		 *  <code>true</code> (the default) and an overall row height hasn't been 
+		 *  cached for the specified row, then the item renderer's height is based 
+		 *  on the <code>typicalItem</code>.  
+		 *  If the <code>typicalItem</code> was not 
+		 *  specified or has not been measured yet, then the item renderer's height 
+		 *  defaults to its preferred height.</p>
+		 *  
+		 *  @param rowIndex The 0-based row index of the item renderer's cell.
+		 * 
+		 *  @param columnIndex The 0-based column index of the item renderer's cell.
+		 * 
+		 *  @return The item renderer or null if the cell location is invalid.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		/*
+		public function getItemRendererAt(rowIndex:int, columnIndex:int):IGridItemRenderer
+		{
+			const view:GridView = getGridViewAt(rowIndex, columnIndex);
+			if (!view)
+				return null;
+			
+			return view.gridViewLayout.getItemRendererAt(rowIndex, columnIndex);
+		}    
+		*/
+		/**
+		 *  Returns <code>true</code> if the specified cell is at least partially visible. 
+		 *  If <code>columnIndex == -1</code>, then return 
+		 *  <code>true</code> if the specified row is at least partially visible. 
+		 *  If <code>rowIndex == -1</code>, then return <code>true</code> 
+		 *  if the specified column is at least partially visible. 
+		 *  If both <code>columnIndex</code> and <code>rowIndex</code> are -1, 
+		 *  then return <code>false</code>.
+		 *  
+		 *  @param rowIndex The 0-based row index of the item renderer's cell.
+		 * 
+		 *  @param columnIndex The 0-based column index of the item renderer's cell.
+		 * 
+		 *  @return True if the specified cell (or row if columnIndex == -1) is at least partially visible
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */        
+		public function isCellVisible(rowIndex:int = -1, columnIndex:int = -1):Boolean
+		{
+			const view:GridView = getGridViewAt(rowIndex, columnIndex);
+			return view ;//&& view.gridViewLayout.isCellVisible(rowIndex, columnIndex);
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Tracking Grid invalidateDisplayList() "reasons", invalid cells
+		//
+		//-------------------------------------------------------------------------- 
+		
+		/**
+		 *  @private
+		 *  Low cost "list" of invalidateDisplayList() reasons.
+		 */
+		private var invalidateDisplayListReasonsMask:uint = 0;
+		
+		/**
+		 *  @private
+		 *  This flag makes it possible to defer clearing the invalidateDisplayListReasonsMask
+		 *  until after the Grid's subtree has been redisplayed.   It's set by updateDisplayList()
+		 *  and not cleared until the next invalidateDisplayListFor() call, on the assumption
+		 *  that the Grid subtree's updateDisplayList() methods will not reset any Grid properties
+		 *  (that call invalidateDisplayListFor()).
+		 */
+		private var clearInvalidateDisplayListReasons:Boolean = false;
+		
+		/**
+		 *  @private
+		 *  Table that maps from reason names to bit fields.
+		 */
+		private static const invalidateDisplayListReasonBits:Object = {
+			verticalScrollPosition: uint(1 << 0),
+			horizontalScrollPosition: uint(1 << 1),
+			bothScrollPositions: (uint(1 << 0) | uint(1 << 1)),
+			hoverIndicator: uint(1 << 2),
+			caretIndicator: uint(1 << 3),
+			selectionIndicator: uint(1 << 4),
+			editorIndicator: uint(1 << 5),
+			none: uint(~0)
+		};
+		
+		/**
+		 *  @private
+		 *  Set the bit that corresponds to reason.  Only used by invalidateDisplayListFor().
+		 */
+		private function setInvalidateDisplayListReason(reason:String):void
+		{
+			if (clearInvalidateDisplayListReasons)
+			{
+				invalidateDisplayListReasonsMask = 0;
+				clearInvalidateDisplayListReasons = false;
+			}
+			
+			invalidateDisplayListReasonsMask |= invalidateDisplayListReasonBits[reason];
+		}
+		
+		/**
+		 *  @private
+		 *  Return true if invalidateDisplayListFor() was called with the specified reason
+		 *  since the last updateDisplayList() pass.
+		 */
+		mx_internal function isInvalidateDisplayListReason(reason:String):Boolean
+		{
+			const bit:uint = invalidateDisplayListReasonBits[reason];
+			return (invalidateDisplayListReasonsMask & bit) == bit;
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Method Overrides
+		//
+		//--------------------------------------------------------------------------  
+		
+		/**
+		 *  @private
+		 */
+		/*override*/ 
+		public function getHorizontalScrollPositionDelta(navigationUnit:uint):Number
+		{
+			const gridLayout:GridLayout = layout as GridLayout;
+			const centerGridView:GridView = gridLayout.centerGridView;			
+			return (centerGridView) ? 0 /*centerGridView.getHorizontalScrollPositionDelta(navigationUnit)*/ : 0;     
+		}
+		
+		/**
+		 *  @private
+		 */
+		/*override*/ 
+		public function getVerticalScrollPositionDelta(navigationUnit:uint):Number
+		{
+			const gridLayout:GridLayout = layout as GridLayout;
+			const centerGridView:GridView = gridLayout.centerGridView;			
+			return (centerGridView) ? 0 /*centerGridView.getVerticalScrollPositionDelta(navigationUnit)*/ : 0;     
+		}
+		
+		
+		/**
+		 *  @private
+		 *  During virtual layout updateDisplayList() eagerly validates lazily
+		 *  created (or recycled) IRs.   We don't want changes to those IRs to
+		 *  invalidate the size of the grid.
+		 * 
+		 *  This method also dispatches an invalidateSize event that's used 
+		 *  by the DataGrid to invalidate IDataGridElements.
+		 */
+		override public function invalidateSize():void
+		{
+			if (!inUpdateDisplayList)
+			{
+				super.invalidateSize();
+				
+				for each (var view:GridView in allGridViews)
+				{
+					if (!view)
+						continue;
+					view.invalidateSize();    
+				}
+				
+				dispatchChangeEvent("invalidateSize");            
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  During virtual layout updateDisplayList() eagerly validates lazily
+		 *  created (or recycled) IRs.  Calls to invalidateDisplayList() eventually
+		 *  short-circuit but doing so early saves a few percent.
+		 * 
+		 *  This method also dispatches an invalidateDisplayList event that's used 
+		 *  by the DataGrid to invalidate IDataGridElements.
+		 */
+		override public function invalidateDisplayList():void
+		{
+			if (!inUpdateDisplayList)
+			{
+				setInvalidateDisplayListReason("none");            
+				super.invalidateDisplayList();
+				
+				for each (var view:GridView in allGridViews)
+				{
+					if (!view)
+						continue;
+					view.invalidateDisplayList();    
+				}
+				
+				dispatchChangeEvent("invalidateDisplayList");
+			}
+		}
+		
+		private function get allGridViews():Array
+		{
+			const gridLayout:GridLayout = layout as GridLayout;
+			return gridLayout ? [gridLayout.topLeftGridView, gridLayout.topGridView, gridLayout.leftGridView, gridLayout.centerGridView] : [];
+		}
+		
+		private function createGridView():GridView
+		{
+			const elt:GridView = gridView.newInstance() as GridView;
+			addElement(elt);
+			return elt;
+		}
+		
+		private function configureGridView(gv:GridView, viewRowIndex:int, viewColumnIndex:int, viewRowCount:int, viewColumnCount:int):void
+		{
+			/*
+			const gridViewLayout:GridViewLayout = gv.gridViewLayout;
+			gridViewLayout.grid = this;
+			gridViewLayout.viewRowIndex = viewRowIndex;
+			gridViewLayout.viewColumnIndex = viewColumnIndex;
+			gridViewLayout.viewRowCount = viewRowCount;
+			gridViewLayout.viewColumnCount = viewColumnCount;
+			*/
+		}
+		
+		/**
+		 *  Create and/or configure this Grid's GridViews.  We're assuming that the
+		 *  Grid's viewFactory, columns and dataProvider are specified.
+		 * 
+		 *  If GridViews are added or removed, a "gridViewsChanged" event is dispatched.
+		 */
+		private function configureGridViews():void
+		{
+			const columnCount:int = columns.length;
+			const rowCount:int = (dataProvider) ? dataProvider.length : 0;
+			
+			lockedColumnCount = Math.min(lockedColumnCount, columnCount);
+			lockedRowCount = Math.min(lockedRowCount, rowCount);
+			
+			const centerRowCount:int = Math.max(0, rowCount - lockedRowCount);
+			const centerColumnCount:int = Math.max(0, columnCount - lockedColumnCount); 
+			
+			const gridLayout:GridLayout = layout as GridLayout;
+			var topLeftGridView:GridView = gridLayout.topLeftGridView;    
+			var topGridView:GridView = gridLayout.topGridView;        
+			var leftGridView:GridView = gridLayout.leftGridView;
+			var centerGridView:GridView = gridLayout.centerGridView;
+			var lockedRowsSeparatorElement:IVisualElement = gridLayout.lockedRowsSeparatorElement;
+			var lockedColumnsSeparatorElement:IVisualElement = gridLayout.lockedColumnsSeparatorElement;
+			
+			var gridViewsChanged:Boolean = false;
+			
+			// Unconditionally create and configure the "center" GridView
+			
+			if (centerGridView == null)
+			{
+				gridLayout.centerGridView = centerGridView = createGridView();
+				gridViewsChanged = true;
+			}
+			
+			configureGridView(centerGridView, lockedRowCount, lockedColumnCount, -1, -1);
+			
+			// centerGridView.gridViewLayout.requestedRowCount = requestedRowCount - lockedRowCount;
+			// centerGridView.gridViewLayout.requestedColumnCount = requestedColumnCount - lockedColumnCount; 
+			
+			// Remove or create/configure the topLeftGridView
+			
+			if ((lockedRowCount > 0) && (lockedColumnCount > 0))
+			{
+				if (!topLeftGridView)
+				{
+					gridLayout.topLeftGridView = topLeftGridView = createGridView();
+					// topLeftGridView.gridViewLayout.verticalScrollingLocked = true;
+					// topLeftGridView.gridViewLayout.horizontalScrollingLocked = true;
+					gridViewsChanged = true;
+				}
+				
+			}
+			else if (topLeftGridView)
+			{
+				removeElement(topLeftGridView);
+				gridLayout.topLeftGridView = topLeftGridView = null;
+				gridViewsChanged = true;
+			}
+			
+			if (topLeftGridView)
+				configureGridView(topLeftGridView, 0, 0, lockedRowCount, lockedColumnCount);
+			
+			// Remove or create/configure the topGridView
+			
+			if (lockedRowCount > 0)
+			{
+				if (!topGridView)
+				{
+					gridLayout.topGridView = topGridView = createGridView();
+					// topGridView.gridViewLayout.verticalScrollingLocked = true;
+					gridViewsChanged = true;
+				}
+				
+				if (lockedRowsSeparator && !lockedRowsSeparatorElement)
+				{
+					gridLayout.lockedRowsSeparatorElement = lockedRowsSeparatorElement /*= lockedRowsSeparator.newInstance() as IVisualElement*/;
+					// addElement(lockedRowsSeparatorElement);
+				}
+			}
+			else
+			{
+				if (topGridView)
+				{
+					removeElement(topGridView);
+					gridLayout.topGridView = topGridView = null;
+					gridViewsChanged = true;
+				}
+				
+				if (lockedRowsSeparatorElement)
+				{
+					// removeElement(lockedRowsSeparatorElement);
+					gridLayout.lockedRowsSeparatorElement = lockedRowsSeparatorElement = null;
+				}
+			}
+			
+			if (topGridView)
+				configureGridView(topGridView, 0, lockedColumnCount, lockedRowCount, centerColumnCount);
+			
+			// Remove or create/configure the leftGridView
+			
+			if (lockedColumnCount > 0)
+			{
+				if (!leftGridView)
+				{
+					gridLayout.leftGridView = leftGridView = createGridView();
+					// leftGridView.gridViewLayout.horizontalScrollingLocked = true;
+					gridViewsChanged = true;
+				}
+				
+				if (lockedColumnsSeparator && !lockedColumnsSeparatorElement)
+				{
+					gridLayout.lockedColumnsSeparatorElement = lockedColumnsSeparatorElement/* = lockedColumnsSeparator.newInstance() as IVisualElement*/;
+					// addElement(lockedColumnsSeparatorElement);
+				}
+			}
+			else
+			{
+				if (leftGridView)
+				{
+					removeElement(leftGridView);
+					gridLayout.leftGridView = leftGridView = null;
+					gridViewsChanged = true;
+				}
+				
+				if (lockedColumnsSeparatorElement)
+				{
+					// removeElement(lockedColumnsSeparatorElement);
+					gridLayout.lockedColumnsSeparatorElement = lockedColumnsSeparatorElement = null;
+				}
+			}
+			
+			if (leftGridView)
+				configureGridView(leftGridView, lockedRowCount, 0, centerRowCount, lockedColumnCount);
+			
+			if (gridViewsChanged)
+				dispatchChangeEvent("gridViewsChanged");
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function commitProperties():void
+		{
+			// rowHeight and variableRowHeight can be set in either order
+			if (variableRowHeightChanged || rowHeightChanged)
+			{
+				if (rowHeightChanged)
+					gridDimensions.defaultRowHeight = _rowHeight;
+				gridDimensions.variableRowHeight = variableRowHeight;
+				
+				if ((!variableRowHeight && rowHeightChanged) || variableRowHeightChanged)
+				{
+					clearGridLayoutCache(false);
+					invalidateSize();
+					invalidateDisplayList();
+				}
+				
+				rowHeightChanged = false;
+				variableRowHeightChanged = false;
+			}
+			
+			// item renderer changed or typical item changed
+			if (itemRendererChanged || typicalItemChanged)
+			{
+				clearGridLayoutCache(true);
+				itemRendererChanged = false;
+			}
+			
+			// Try to generate columns if there aren't any or there are generated
+			// ones which need to be regenerated because the typicalItem or 
+			// dataProvider changed.
+			if (!columns || (generatedColumns && 
+				(typicalItemChanged || (!typicalItem && dataProviderChanged))))
+			{
+				const oldColumns:IList = columns;
+				columns = generateColumns();
+				generatedColumns = (columns != null);
+				columnsChanged = columns != oldColumns;
+			}
+			typicalItemChanged = false;
+			
+			// If the dataProvider or columns change, reset the selection and 
+			// the grid dimensions.  This has to be done here rather than in the 
+			// setters because the gridSelection and gridDimensions might not 
+			// be set yet, depending on the order they are initialized when the 
+			// grid skin part is added to the data grid.
+			
+			if (dataProviderChanged || columnsChanged)
+			{
+				
+				// Remove the current selection and, if requireSelection, make
+				// sure the selection is reset to row 0 or cell 0,0.
+				if (gridSelection)
+				{
+					var savedRequireSelection:Boolean = gridSelection.requireSelection;
+					gridSelection.requireSelection = false;
+					gridSelection.removeAll();
+					gridSelection.requireSelection = savedRequireSelection;
+				} 
+				
+				// make sure we have the right number of columns.
+				if (columnsChanged)
+					gridDimensions.columnCount = _columns ? _columns.length : 0;
+				
+				// Keep typical item size cache only when the typical item is still valid
+				// and the columns haven't changed.
+				if (typicalItem != null && !columnsChanged)
+					clearGridLayoutCache(false);
+				else
+					clearGridLayoutCache(true);
+				
+				if (!caretChanged)
+					initializeCaretPosition();
+				
+				if (!anchorChanged)
+					initializeAnchorPosition();
+				
+				dataProviderChanged = false;
+				columnsChanged = false;
+			}
+			
+			anchorChanged = false;
+			
+			// Create or reconfigure the Grid's GridViews
+			
+			if (gridView && columns)
+				configureGridViews();
+			
+			// Deferred selection operations
+			
+			if (dataProvider)
+			{
+				for each (var deferredOperation:Function in deferredOperations)
+				deferredOperation();
+				deferredOperations.length = 0;                
+			}
+			
+			// Only want one event if both caretRowIndex and caretColumnIndex changed
+			
+			if (caretChanged)
+			{
+				// Validate values now.  Need to let caret be set in the same
+				// update as the dp and/or columns.  -1 is a valid value.            
+				if (_dataProvider && caretRowIndex >= _dataProvider.length)
+					_caretRowIndex = _dataProvider.length - 1;
+				if (_columns && caretColumnIndex >= _columns.length)
+					_caretColumnIndex = getPreviousVisibleColumnIndex(_columns.length - 1);
+				
+				caretSelectedItem = 
+					_dataProvider && _caretRowIndex >= 0 ?
+					_dataProvider.getItemAt(_caretRowIndex) : null;
+				
+				dispatchCaretChangeEvent();
+				
+				// Last reported values.
+				_oldCaretRowIndex = _caretRowIndex;
+				_oldCaretColumnIndex = _caretColumnIndex;
+				
+				caretChanged = false;        
+			}
+			
+			if (updateCaretForDataProviderChanged)
+			{
+				updateCaretForDataProviderChanged = false;
+				updateCaretForDataProviderChange(updateCaretForDataProviderChangeLastEvent);
+				updateCaretForDataProviderChangeLastEvent = null;
+			}
+		}
+		
+		
+		/**
+		 *  @private
+		 */
+		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+		{
+			inUpdateDisplayList = true;
+			super.updateDisplayList(unscaledWidth, unscaledHeight);
+			inUpdateDisplayList = false;
+			
+			clearInvalidateDisplayListReasons = true;
+			
+			if (!variableRowHeight)
+				setFixedRowHeight(gridDimensions.getRowHeight(0));
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Methods
+		//
+		//--------------------------------------------------------------------------      
+		
+		/**
+		 *  @private
+		 *  This version of invlaidateDisplayList() stores the "reason" for the invalidate
+		 *  request so that GridLayout/updateDisplayList() can do its job more efficiently.
+		 *  GridLayout tests the accumulated invalidateDisplayList reasons with 
+		 *  isInvalidateDisplayListReason() and they're automatically cleared by 
+		 *  updateDisplayList() here.
+		 * 
+		 *  Note that if invalidateDisplayList() is called directly, all possible 
+		 *  invalidateDispayList reasons are implicitly specified, in other words if
+		 *  no reason is specified then they all are (see invalidateDisplayListReasonBits.none).
+		 *  That way, callers need not be aware of this internal API.
+		 * 
+		 *  Also: most reason="selectionIndicator" calls also change the caret index which
+		 *  in turn adds reason="caretIndicator" to the invalidateDisplayList reasons, if the
+		 *  caret index actually changed.
+		 */
+		mx_internal function invalidateDisplayListFor(reason:String):void
+		{
+			if (!inUpdateDisplayList)
+			{
+				setInvalidateDisplayListReason(reason);          
+				super.invalidateDisplayList();
+				
+				// Minor optimization: if the reason for this invalidation is a 
+				// scroll, don't invalidate GridViews that can't change. 
+				
+				const vspReason:Boolean = reason == "verticalScrollPosition";
+				const hspReason:Boolean = reason == "horizontalScrollPosition";
+				const bothReason:Boolean = reason == "bothScrollPositions";
+				
+				const gridLayout:GridLayout = layout as GridLayout;
+				const topLeftGridView:GridView = gridLayout.topLeftGridView;    
+				const topGridView:GridView = gridLayout.topGridView;        
+				const leftGridView:GridView = gridLayout.leftGridView;
+				const centerGridView:GridView = gridLayout.centerGridView;			
+				
+				if (topLeftGridView && !vspReason && !hspReason && !bothReason)
+					topLeftGridView.invalidateDisplayList();
+				
+				if (topGridView && !vspReason)
+					topGridView.invalidateDisplayList();
+				
+				if (leftGridView && !hspReason)
+					leftGridView.invalidateDisplayList();			
+				
+				if (centerGridView)  
+					centerGridView.invalidateDisplayList();
+				
+				dispatchChangeEvent("invalidateDisplayList");
+			}
+		}
+		
+		/**
+		 *  If the specified cell is visible, it is redisplayed.  
+		 *  If <code>variableRowHeight=true</code>, 
+		 *  then doing so may cause the height of the corresponding row to change.
+		 * 
+		 *  <p>If columnIndex is -1, then the entire row is invalidated.  
+		 *  Similarly if <code>rowIndex is -1</code>, then the entire column is invalidated.</p>
+		 * 
+		 *  <p>This method should be called when there is a change to any aspect of 
+		 *  the data provider item at <code>rowIndex</code> that might have some 
+		 *  impact on the way the  specified cell is displayed. 
+		 *  Calling this method is similar to calling the
+		 *  <code>dataProvider.itemUpdated()</code> method, which advises the Grid that all rows
+		 *  displaying the specified item should be redisplayed.  
+		 *  Using this method can be relatively efficient, since it narrows 
+		 *  the scope of the change to a single cell.</p>
+		 * 
+		 *  @param rowIndex The 0-based row index of the cell that changed, or -1.
+		 *
+		 *  @param columnIndex The 0-based column index of the cell that changed or -1.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		/*public function invalidateCell(rowIndex:int, columnIndex:int):void
+		{
+			if ((rowIndex == -1) && (columnIndex == -1))
+			{
+				invalidateDisplayList();
+				return;
+			}
+			
+			const view:GridView = getGridViewAt(rowIndex, columnIndex);
+			if (!dataProvider || !view)
+				return;
+			
+			
+			const gridLayout:GridViewLayout = view.gridViewLayout;
+			const dataProviderLength:int = dataProvider.length;
+			if (!gridLayout || (rowIndex >= dataProvider.length))
+				return;
+			
+			if (!isCellVisible(rowIndex, columnIndex))
+				return;
+			
+			if (invalidateDisplayListFlag || invalidateSizeFlag)
+				return;        
+			
+			if ((rowIndex >= 0) && (columnIndex >= 0))
+			{
+				gridLayout.invalidateCell(rowIndex, columnIndex);
+			}
+			else if (rowIndex >= 0)  // invalidate a row
+			{
+				const visibleColumnIndices:Vector.<int> = getVisibleColumnIndices();
+				for each (var visibleColumnIndex:int in visibleColumnIndices)
+				{
+					gridLayout.invalidateCell(rowIndex, visibleColumnIndex);
+					
+					// If invalidating the cell caused the entire grid to be invalid, punt 
+					if (invalidateDisplayListFlag || invalidateSizeFlag)
+						break;                
+				}
+			}
+			else if (columnIndex >= 0)  // invalidate a column
+			{
+				const visibleRowIndices:Vector.<int> = getVisibleRowIndices();
+				for each (var visibleRowIndex:int in visibleRowIndices)
+				{
+					// If there are any padding rows, skip them.
+					if (visibleRowIndex >= dataProviderLength)
+						break;
+					
+					gridLayout.invalidateCell(visibleRowIndex, columnIndex);
+					
+					// If invalidating the cell caused the entire grid to be invalid, punt 
+					if (invalidateDisplayListFlag || invalidateSizeFlag)
+						break;
+				}
+			}
+			
+		}*/
+		
+		/**
+		 *  Creates a grid selection object to use to manage selection. Override this method if you have a custom grid 
+		 *  selection that you want to use in place of the default and this grid is not a skin part for DataGrid.  
+		 *  This method is not used when this grid is a skin part for DataGrid.
+		 *
+		 *  @see spark.components.DataGrid.createGridSelection
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		mx_internal function createGridSelection():GridSelection
+		{
+			return new GridSelection();    
+		}
+		
+		
+		/**
+		 *  This will search through a dataprovider checking the given field and for the given value and return the index for the match.
+		 *  It can start the find from a given startingIndex;
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function findRowIndex(field:String, value:String, startingIndex:int = 0, patternType:String = RegExPatterns.EXACT):int
+		{
+			var pattern:RegExp; 
+			var currentObject:Object = null;
+			var dataProviderTotal:int = 0;
+			var loopingIndex:int = startingIndex;
+			
+			
+			pattern = RegExPatterns.createRegExp(value, patternType);
+			
+			
+			if (dataProvider && dataProvider.length > 0)
+			{
+				dataProviderTotal = dataProvider.length;
+				
+				if (startingIndex >= dataProviderTotal)
+				{
+					return -1;
+				}
+				
+				
+				for (loopingIndex; loopingIndex < dataProviderTotal; loopingIndex++)
+				{
+					currentObject = dataProvider.getItemAt(loopingIndex);
+					
+					if (currentObject.hasOwnProperty(field) == true && pattern.test(currentObject[field]) == true)
+					{
+						return loopingIndex;
+					}
+				}
+				
+			}
+			
+			return -1;
+		}
+		
+		
+		/**
+		 *  This will search through a dataprovider checking the given field and for the given values and return an array of indices that matched.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function findRowIndices(field:String, values:Array, patternType:String = RegExPatterns.EXACT):Array
+		{
+			var currentObject:Object = null;
+			var regexList:Array = [];
+			var matchedIndices:Array = [];
+			var dataProviderTotal:uint = 0;
+			var valuesTotal:uint = 0;
+			var loopingDataProviderIndex:uint = 0;
+			var loopingValuesIndex:uint = 0;
+			
+			
+			if (dataProvider != null && dataProvider.length > 0 && values != null && values.length > 0)
+			{
+				dataProviderTotal = dataProvider.length;
+				valuesTotal = values.length;
+				
+				
+				//Set the regex patterns in an array once.
+				for (loopingValuesIndex = 0; loopingValuesIndex < valuesTotal; loopingValuesIndex++)
+				{
+					regexList.push(RegExPatterns.createRegExp(values[loopingValuesIndex], patternType));
+				}
+				
+				
+				//Loop through dataprovider
+				for (loopingDataProviderIndex; loopingDataProviderIndex < dataProviderTotal; loopingDataProviderIndex++)
+				{
+					currentObject = dataProvider.getItemAt(loopingDataProviderIndex);
+					
+					if (currentObject.hasOwnProperty(field) == false)
+					{
+						continue;
+					}
+					
+					//Loop through regex patterns from the values array.
+					for (loopingValuesIndex = 0; loopingValuesIndex < valuesTotal; loopingValuesIndex++)
+					{
+						if (regexList[loopingValuesIndex].test(currentObject[field]) == true)
+						{
+							matchedIndices.push(loopingDataProviderIndex);
+							
+							break;
+						}
+					}
+				}
+				
+			}
+			
+			
+			return matchedIndices;
+		}
+		
+		
+		/**
+		 *  This will search through a dataprovider checking the given field and will set the selectedIndex to a matching value.
+		 *  It can start the search from the startingIndex;
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 *
+		 */
+		public function moveIndexFindRow(field:String, value:String, startingIndex:int = 0, patternType:String = RegExPatterns.EXACT):Boolean
+		{
+			var indexFound:int = -1;
+			
+			indexFound = findRowIndex(field, value, startingIndex, patternType);
+			
+			if (indexFound != -1)
+			{
+				selectedIndex = indexFound;
+				
+				return true;
+			}
+			
+			return false;
+		}
+		
+		
+		/**
+		 *  Changes the selectedIndex to the first row of the dataProvider.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function moveIndexFirstRow():void
+		{
+			if (dataProvider && dataProvider.length > 0)
+			{
+				selectedIndex = 0;
+			}
+		}
+		
+		
+		/**
+		 *  Changes the selectedIndex to the last row of the dataProvider.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function moveIndexLastRow():void
+		{
+			if (dataProvider && dataProvider.length > 0)
+			{
+				selectedIndex = dataProvider.length - 1;
+			}
+		}
+		
+		
+		/**
+		 *  Changes the selectedIndex to the next row of the dataProvider.  If there isn't a current selectedIndex, it silently returns.
+		 *  If the selectedIndex is on the first row, it does not wrap around.  However the <code>isFirstRow</code> property returns true.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function moveIndexNextRow():void
+		{
+			if (dataProvider && dataProvider.length > 0 && selectedIndex >= 0)
+			{
+				if (isLastRow == false)
+				{
+					selectedIndex += 1;
+				}
+			}
+		}
+		
+		
+		/**
+		 *  Changes the selectedIndex to the previous row of the dataProvider.  If there isn't a current selectedIndex, it silently returns.
+		 *  If the selectedIndex is on the last row, it does not wrap around.  However the <code>isLastRow</code> property returns true.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 11.1
+		 *  @playerversion AIR 3.4
+		 *  @productversion Flex 4.10
+		 */
+		public function moveIndexPreviousRow():void
+		{
+			if (dataProvider && dataProvider.length > 0 && selectedIndex >= 0)
+			{
+				if (isFirstRow == false)
+				{
+					selectedIndex -= 1;
+				}
+			}
+		}
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Methods: Internal Grid Access
+		//
+		//--------------------------------------------------------------------------      
+		
+		/**
+		 *  @private
+		 */
+		
+		private function getGridColumn(columnIndex:int):GridColumn
+		{
+			const columns:IList = columns;
+			if ((columns == null) || (columnIndex < 0) || (columnIndex >= columns.length))
+				return null;
+			
+			return columns.getItemAt(columnIndex) as GridColumn;
+		}
+		
+		/**
+		 *  @private
+		 */
+		mx_internal function getDataProviderItem(rowIndex:int):Object
+		{
+			const dataProvider:IList = dataProvider;
+			if ((dataProvider == null) || (rowIndex >= dataProvider.length))
+				return null;
+			
+			return dataProvider.getItemAt(rowIndex);
+		}
+		
+		/**
+		 *  @private
+		 */
+		
+		private function getVisibleItemRenderer(rowIndex:int, columnIndex:int):IGridItemRenderer
+		{
+			const view:GridView = getGridViewAt(rowIndex, columnIndex);
+			if (!view)
+				return null;
+			
+			/*const gridViewLayout:GridViewLayout = view.gridViewLayout;
+			const viewRowIndex:int = rowIndex - gridViewLayout.viewRowIndex;
+			const viewColumnIndex:int = columnIndex - gridViewLayout.viewColumnIndex;*/
+			return null; // gridViewLayout.getVisibleItemRenderer(viewRowIndex, viewColumnIndex);
+		}
+		
+		
+		//--------------------------------------------------------------------------
+		//
+		//  GridEvents
+		//
+		//--------------------------------------------------------------------------  
+		
+		private var rollRowIndex:int = -1;
+		private var rollColumnIndex:int = -1;
+		private var mouseDownRowIndex:int = -1;
+		private var mouseDownColumnIndex:int = -1;
+		private var lastClickedColumnIndex:int = -1;
+		private var lastClickedRowIndex:int = -1;
+		private var lastClickTime:Number;
+		
+		// default max time between clicks for a double click is 480ms.
+		mx_internal var DOUBLE_CLICK_TIME:Number = 480;
+		
+		/** 
+		 *  @private
+		 *  Return the GridView whose bounds contain the MouseEvent, or null.  Note that the 
+		 *  comparison is based strictly on the event's location and the GridViews' bounds.
+		 *  The event's target can be anything.
+		 */
+		private function mouseEventGridView(event:MouseEvent):GridView
+		{
+			const gridLayout:GridLayout = layout as GridLayout;
+			
+			const centerGridView:GridView = gridLayout.centerGridView;
+			if (centerGridView && centerGridView.containsMouseEvent(event))
+				return centerGridView;
+			
+			const leftGridView:GridView = gridLayout.leftGridView;
+			if (leftGridView && leftGridView.containsMouseEvent(event))
+				return leftGridView;
+			
+			const topGridView:GridView = gridLayout.topGridView;
+			if (topGridView && topGridView.containsMouseEvent(event))
+				return topGridView;
+			
+			const topLeftGridView:GridView = gridLayout.topLeftGridView;
+			if (topLeftGridView && topLeftGridView.containsMouseEvent(event))
+				return topLeftGridView;
+			
+			return null;
+		}
+		
+		/** 
+		 *  @private
+		 *  Return the Grid-relative row,column (gridCP) and X,Y location (gridXY) of the MouseEvent.
+		 */    
+		private function eventToGridLocations(event:MouseEvent, gridCP:CellPosition, gridXY:Point):void
+		{
+			const stageXY:Point = new Point(event.stageX, event.stageY);
+			const localXY:Point = globalToLocal(stageXY);
+			gridXY.x = localXY.x;  // event may not have targeted the Grid
+			gridXY.y = localXY.y;
+			
+			const view:GridView = mouseEventGridView(event);
+			if (view)
+			{
+				const viewXY:Point = view.globalToLocal(stageXY);
+				/*
+				const gridViewLayout:GridViewLayout = view.gridViewLayout;
+				const gdv:GridDimensionsView = gridViewLayout.gridDimensionsView;
+				
+				
+				gridCP.rowIndex = gdv.getRowIndexAt(viewXY.x, viewXY.y) + gridViewLayout.viewRowIndex;
+				gridCP.columnIndex = gdv.getColumnIndexAt(viewXY.x, viewXY.y) + gridViewLayout.viewColumnIndex;
+				
+				gridXY.x = viewXY.x + gdv.viewOriginX;
+				gridXY.y = viewXY.y + gdv.viewOriginY;
+				*/
+			}
+			else
+			{
+				gridCP.rowIndex = -1;
+				gridCP.columnIndex = -1;
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  This method is called when a MOUSE_DOWN event occurs within the grid and 
+		 *  for all subsequent MOUSE_MOVE events until the button is released (even if the 
+		 *  mouse leaves the grid).  The last event in such a "down drag up" gesture is 
+		 *  always a MOUSE_UP.  By default this method dispatches GRID_MOUSE_DOWN, 
+		 *  GRID_MOUSE_DRAG, or a GRID_MOUSE_UP event in response to the the corresponding
+		 *  mouse event.  The GridEvent's rowIndex, columnIndex, column, item, and itemRenderer 
+		 *  properties correspond to the grid cell under the mouse.  
+		 * 
+		 *  @param event A MOUSE_DOWN, MOUSE_MOVE, or MOUSE_UP MouseEvent from a down/move/up gesture initiated within the grid.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */    
+		protected function grid_mouseDownDragUpHandler(event:MouseEvent):void
+		{
+			const eventGridCP:CellPosition = new CellPosition();
+			const eventGridXY:Point = new Point();
+			eventToGridLocations(event, eventGridCP, eventGridXY);
+			
+			const eventRowIndex:int = eventGridCP.rowIndex;
+			const eventColumnIndex:int = eventGridCP.columnIndex;
+			
+			var gridEventType:String;
+			switch(event.type)
+			{
+				case MouseEvent.MOUSE_MOVE: 
+				{
+					gridEventType = GridEvent.GRID_MOUSE_DRAG; 
+					break;
+				}
+				case MouseEvent.MOUSE_UP: 
+				{
+					gridEventType = GridEvent.GRID_MOUSE_UP;
+					break;
+				}
+				case MouseEvent.MOUSE_DOWN:
+				{
+					gridEventType = GridEvent.GRID_MOUSE_DOWN;
+					mouseDownRowIndex = eventRowIndex;
+					mouseDownColumnIndex = eventColumnIndex;
+					dragInProgress = true;
+					break;
+				}
+			}
+			
+			dispatchGridEvent(event, gridEventType, eventGridXY, eventRowIndex, eventColumnIndex);
+			if (gridEventType == GridEvent.GRID_MOUSE_UP)
+				dispatchGridClickEvents(event, eventGridXY, eventRowIndex, eventColumnIndex);        
+		}
+		
+		/**
+		 *  @private
+		 *  This method is called whenever a MOUSE_MOVE event occurs within the grid
+		 *  without the button pressed.  By default it dispatches a GRID_ROLL_OVER for the
+		 *  first MOUSE_MOVE GridEvent whose location is within a grid cell, and a 
+		 *  GRID_ROLL_OUT GridEvent when the mouse leaves a cell.  Listeners are guaranteed
+		 *  to receive a GRID_ROLL_OUT event for every GRID_ROLL_OVER event.
+		 * 
+		 *  @param event A MOUSE_MOVE MouseEvent within the grid, without the button pressed.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */    
+		protected function grid_mouseMoveHandler(event:MouseEvent):void
+		{
+			const eventGridCP:CellPosition = new CellPosition();
+			const eventGridXY:Point = new Point();
+			eventToGridLocations(event, eventGridCP, eventGridXY);
+			
+			const eventRowIndex:int = eventGridCP.rowIndex;
+			const eventColumnIndex:int = eventGridCP.columnIndex;
+			
+			if ((eventRowIndex != rollRowIndex) || (eventColumnIndex != rollColumnIndex))
+			{
+				if ((rollRowIndex != -1) || (rollColumnIndex != -1))
+					dispatchGridEvent(event, GridEvent.GRID_ROLL_OUT, eventGridXY, rollRowIndex, rollColumnIndex);
+				if ((eventRowIndex != -1) && (eventColumnIndex != -1))
+					dispatchGridEvent(event, GridEvent.GRID_ROLL_OVER, eventGridXY, eventRowIndex, eventColumnIndex);
+				rollRowIndex = eventRowIndex;
+				rollColumnIndex = eventColumnIndex;
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  This method is called whenever a ROLL_OUT occurs on the grid.
+		 *  By default it dispatches a GRID_ROLL_OUT event.
+		 * 
+		 *  @param event A ROLL_OUT MouseEvent from the grid.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */       
+		protected function grid_mouseRollOutHandler(event:MouseEvent):void
+		{
+			if ((rollRowIndex != -1) || (rollColumnIndex != -1))
+			{
+				const eventStageXY:Point = new Point(event.stageX, event.stageY);
+				const eventGridXY:Point = globalToLocal(eventStageXY);      
+				
+				dispatchGridEvent(event, GridEvent.GRID_ROLL_OUT, eventGridXY, rollRowIndex, rollColumnIndex);
+				rollRowIndex = -1;
+				rollColumnIndex = -1;
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  This method is called whenever a GRID_MOUSE_UP occurs on the grid.
+		 *  By default it dispatches a GRID_MOUSE_UP event.
+		 * 
+		 *  @param event A GRID_MOUSE_UP MouseEvent from the grid.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */       
+		protected function grid_mouseUpHandler(event:MouseEvent):void 
+		{
+			if (dragInProgress)
+			{
+				// drag handler has already dispatched a mouse up event, don't do so again here
+				dragInProgress = false;
+				return;
+			}
+			
+			const eventGridCP:CellPosition = new CellPosition();
+			const eventGridXY:Point = new Point();
+			eventToGridLocations(event, eventGridCP, eventGridXY);
+			
+			const eventRowIndex:int = eventGridCP.rowIndex;
+			const eventColumnIndex:int = eventGridCP.columnIndex;        
+			
+			dispatchGridEvent(event, GridEvent.GRID_MOUSE_UP, eventGridXY, eventRowIndex, eventColumnIndex);
+			dispatchGridClickEvents(event, eventGridXY, eventRowIndex, eventColumnIndex);
+		}
+		
+		/**
+		 *  @private
+		 *  This method is called after we dispatch a GRID_MOUSE_UP.
+		 *  It determines whether to dispatch a GRID_CLICK or GRID_DOUBLE_CLICK
+		 *  event following a GRID_MOUSE_UP.
+		 * 
+		 *  A GRID_CLICK event is dispatched when the mouse up event happens in
+		 *  the same cell as the mouse down event.
+		 * 
+		 *  A GRID_DOUBLE_CLICK event is dispatched in place of the GRID_CLICK
+		 *  event when the last click event happened within DOUBLE_CLICK_TIME.
+		 */       
+		private function dispatchGridClickEvents(mouseEvent:MouseEvent, gridXY:Point, rowIndex:int, columnIndex:int):void
+		{
+			const dispatchGridClick:Boolean = ((rowIndex == mouseDownRowIndex) && (columnIndex == mouseDownColumnIndex));
+			const newClickTime:Number = 0;// getTimer();
+			var isDoubleClick:Boolean = false;
+			
+			// In the case that we dispatched a click last time, check if we
+			// should dispatch a double click this time.  The type of check will be based on the double click mode.
+			if (doubleClickEnabled && dispatchGridClick && !isNaN(lastClickTime) &&
+				(newClickTime - lastClickTime <= DOUBLE_CLICK_TIME))
+			{
+				switch(_doubleClickMode)
+				{
+					case GridDoubleClickMode.CELL:
+					{
+						if (rowIndex != -1 && columnIndex != -1 && rowIndex == lastClickedRowIndex && columnIndex == lastClickedColumnIndex)
+						{
+							isDoubleClick = true;
+						}
+						
+						break;
+					}
+						
+					case GridDoubleClickMode.GRID:
+					{
+						isDoubleClick = true;
+						
+						break;
+					}
+						
+					case GridDoubleClickMode.ROW:
+					{
+						if (rowIndex != -1 && rowIndex == lastClickedRowIndex)
+						{
+							isDoubleClick = true;
+						}
+						
+						break;
+					}
+				}
+				
+				if (isDoubleClick == true)
+				{
+					dispatchGridEvent(mouseEvent, GridEvent.GRID_DOUBLE_CLICK, gridXY, rowIndex, columnIndex);
+					lastClickTime = NaN;
+					lastClickedColumnIndex = -1;
+					lastClickedRowIndex = -1;
+					isDoubleClick = false;
+					
+					return;
+				}
+			}
+			
+			// Otherwise, just dispatch the click event.
+			if (dispatchGridClick)
+			{
+				dispatchGridEvent(mouseEvent, GridEvent.GRID_CLICK, gridXY, rowIndex, columnIndex);
+				lastClickTime = newClickTime;
+				lastClickedColumnIndex = columnIndex;
+				lastClickedRowIndex = rowIndex;
+				isDoubleClick = false;
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function dispatchGridEvent(mouseEvent:MouseEvent, type:String, gridXY:Point, rowIndex:int, columnIndex:int):void
+		{
+			
+			const column:GridColumn = columnIndex >= 0 ? getGridColumn(columnIndex) : null;
+			const item:Object = rowIndex >= 0 ? getDataProviderItem(rowIndex) : null;
+			const itemRenderer:IGridItemRenderer = getVisibleItemRenderer(rowIndex, columnIndex);
+			const bubbles:Boolean = mouseEvent.bubbles;
+			const cancelable:Boolean = mouseEvent.cancelable;
+			// const relatedObject:InteractiveObject = mouseEvent.relatedObject;
+			const ctrlKey:Boolean = mouseEvent.ctrlKey;
+			const altKey:Boolean = mouseEvent.altKey;
+			const shiftKey:Boolean = mouseEvent.shiftKey;
+			const buttonDown:Boolean = mouseEvent.buttonDown;
+			const delta:int = mouseEvent.delta;        
+			
+			/*const event:GridEvent = new GridEvent(
+				type, bubbles, cancelable, 
+				gridXY.x, gridXY.y, 
+				relatedObject, ctrlKey, altKey, shiftKey, buttonDown, delta,
+				rowIndex, columnIndex, column, item, itemRenderer);
+			dispatchEvent(event);*/
+			
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  IList listeners: columns, dataProvider
+		//
+		//--------------------------------------------------------------------------  
+		
+		/**
+		 *  @private
+		 *  Update caretRowIndex if necessary.  This method should only be called when 
+		 *  caretRowIndex is valid, i.e. != -1.
+		 */
+		private function updateCaretForDataProviderChange(event:CollectionEvent):void
+		{
+			const oldCaretRowIndex:int = caretRowIndex;
+			const location:int = event.location;
+			const itemsLength:int = event.items ? event.items.length : 0;                
+			var newCaretRowIndex:int; 
+			
+			switch (event.kind)
+			{
+				case CollectionEventKind.ADD:
+					if (oldCaretRowIndex >= location)
+						caretRowIndex += event.items.length;
+					break;
+				
+				case CollectionEventKind.REMOVE:
+					if (oldCaretRowIndex >= location)
+					{
+						// ToDo(cframpto):  If the caret is on an item that is deleted, rather than
+						// removing the caret, which is what we do now, it is preferable
+						// to have the caret "stick" to the same position.  There is some complexity 
+						// to picking a row/cell based on what’s currently visible or partially 
+						// visible – after – the delete operation.
+						if (oldCaretRowIndex < (location + itemsLength))
+							caretRowIndex = -1; 
+						else
+							caretRowIndex -= itemsLength;    
+					}
+					
+					break;
+				
+				case CollectionEventKind.MOVE:
+				{
+					const oldLocation:int = event.oldLocation;
+					if ((oldCaretRowIndex >= oldLocation) && (oldCaretRowIndex < (oldLocation + itemsLength)))
+					{
+						caretRowIndex += location - oldLocation;
+						ensureCellIsVisible(caretRowIndex, -1);
+					}
+				}
+					break;                        
+				
+				case CollectionEventKind.REPLACE:
+				case CollectionEventKind.UPDATE:
+					break;
+				
+				case CollectionEventKind.REFRESH:
+				{
+					newCaretRowIndex = 
+						caretSelectedItem ?
+						_dataProvider.getItemIndex(caretSelectedItem) : -1; 
+					
+					// Caret sticks to item if possible and ensure it is totally 
+					// visible by scrolling vertically if necessary.
+					if (newCaretRowIndex != -1)
+					{
+						caretRowIndex = newCaretRowIndex;
+						ensureCellIsVisible(caretRowIndex, -1);
+					}
+					else
+					{
+						// No caret.  Maintain the existing scroll position if
+						// within the current data.
+						
+						var oldVsp:int = verticalScrollPosition;
+						
+						validateNow();
+						
+						// If variable row heights the height is 
+						// approximate so the scroll position may not be
+						// in exactly the same place.
+						
+						const cHeight:Number = Math.ceil(gridDimensions.getContentHeight());
+						const maximum:int = Math.max(cHeight - height, 0);
+						verticalScrollPosition = (oldVsp > maximum) ? maximum : oldVsp;                        
+					}
+					break;
+				}
+					
+				case CollectionEventKind.RESET:
+				{
+					newCaretRowIndex = 
+						caretSelectedItem ?
+						_dataProvider.getItemIndex(caretSelectedItem) : -1; 
+					
+					// Caret sticks to item if possible and ensure it is totally 
+					// visible by scrolling vertically if necessary.
+					if (newCaretRowIndex != -1)
+					{
+						caretRowIndex = newCaretRowIndex;
+						ensureCellIsVisible(caretRowIndex, -1);
+					}
+						
+						// No caret item so reset caret and vsp.
+					else 
+					{
+						caretRowIndex = _dataProvider.length > 0 ? 0 : -1;
+						// we need to call validateSize() to force computing maxTypicalCellHeight  or verticalScrollPosition will fail
+						GridLayout(layout).centerGridView.validateSize();
+						verticalScrollPosition = 0;
+					}
+					
+					break;
+				}
+			}   
+			
+		}
+		
+		/**
+		 *  @private
+		 *  Update caretColumnIndex if necessary.  This method should only be 
+		 *  called when caretColumnIndex is valid, i.e. != -1.
+		 */
+		private function updateCaretForColumnsChange(event:CollectionEvent):void
+		{
+			const oldCaretColumnIndex:int = caretColumnIndex;
+			const location:int = event.location;
+			const itemsLength:int = event.items ? event.items.length : 0;
+			
+			switch (event.kind)
+			{
+				case CollectionEventKind.ADD:
+					if (oldCaretColumnIndex >= location)
+						caretColumnIndex += itemsLength;
+					break;
+				
+				case CollectionEventKind.REMOVE:
+					if (oldCaretColumnIndex >= location)
+					{
+						if (oldCaretColumnIndex < (location + itemsLength))
+							caretColumnIndex = _columns.length > 0 ? 0 : -1; 
+						else
+							caretColumnIndex -= itemsLength;    
+					}                   
+					break;
+				
+				case CollectionEventKind.MOVE:
+					const oldLocation:int = event.oldLocation;
+					if ((oldCaretColumnIndex >= oldLocation) && (oldCaretColumnIndex < (oldLocation + itemsLength)))
+						caretColumnIndex += location - oldLocation;
+					break;                        
+				
+				case CollectionEventKind.REPLACE:
+					break;
+				
+				case CollectionEventKind.UPDATE:
+					// column may have changed visiblity which matters if cell 
+					// selection mode.
+					var pe:PropertyChangeEvent;
+					
+					if (selectionMode == GridSelectionMode.SINGLE_CELL || 
+						selectionMode == GridSelectionMode.MULTIPLE_CELLS)
+					{
+						for (var i:int = 0; i < itemsLength; i++)
+						{
+							pe = event.items[i] as PropertyChangeEvent;
+							if (pe && pe.property == "visible")
+							{	
+								
+								const column:GridColumn = pe.source as GridColumn;
+								if (!column || column.visible)
+									continue;
+								
+								if (column.columnIndex == caretColumnIndex)
+									initializeCaretPosition(true);  // column only
+								if (column.columnIndex == anchorColumnIndex)
+									initializeAnchorPosition(true);  // column only
+								
+							}
+						}
+					}
+					break;
+				
+				case CollectionEventKind.REFRESH:
+				case CollectionEventKind.RESET:
+					initializeCaretPosition(true);  // column only
+					horizontalScrollPosition = 0;
+					break;
+			}            
+		}
+		
+		/**
+		 *  @private
+		 *  Update hoverRowIndex if necessary.  This method should only be called when 
+		 *  hoverRowIndex is valid, i.e. != -1.
+		 */
+		private function updateHoverForDataProviderChange(event:CollectionEvent):void
+		{
+			const oldHoverRowIndex:int = hoverRowIndex;
+			const location:int = event.location;
+			
+			switch (event.kind)
+			{
+				case CollectionEventKind.ADD:
+				case CollectionEventKind.REMOVE:
+				case CollectionEventKind.REPLACE:
+				case CollectionEventKind.UPDATE:
+				case CollectionEventKind.MOVE:
+					if (oldHoverRowIndex >= location)
+						hoverRowIndex = gridDimensions.getRowIndexAt(mouseX, mouseY);
+					break;
+				
+				case CollectionEventKind.REFRESH:
+				case CollectionEventKind.RESET:
+					hoverRowIndex = gridDimensions.getRowIndexAt(mouseX, mouseY);
+					break;
+			}                        
+		}
+		
+		/**
+		 *  @private
+		 *  Update hoverColumnIndex if necessary.  This method should only be called when 
+		 *  hoverColumnIndex is valid, i.e. != -1.
+		 */
+		private function updateHoverForColumnsChange(event:CollectionEvent):void
+		{
+			switch (event.kind)
+			{
+				case CollectionEventKind.ADD:
+				case CollectionEventKind.REMOVE:
+				case CollectionEventKind.REPLACE:
+				case CollectionEventKind.UPDATE:
+				case CollectionEventKind.MOVE:
+					if (hoverColumnIndex >= event.location)
+						hoverColumnIndex = gridDimensions.getColumnIndexAt(mouseX, mouseY);
+					break;
+				
+				case CollectionEventKind.REFRESH:
+				case CollectionEventKind.RESET:
+					hoverColumnIndex = gridDimensions.getColumnIndexAt(mouseX, mouseY);
+					break;
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function dataProvider_collectionChangeHandler(event:CollectionEvent):void
+		{
+			var selectionChanged:Boolean = false;
+			
+			
+			// If no columns exist, we should try to generate them.
+			if (!columns && dataProvider.length > 0)
+			{
+				columns = generateColumns();
+				generatedColumns = (columns != null);
+				this.gridDimensions.columnCount = generatedColumns ? columns.length : 0;
+			}
+			
+			const gridDimensions:GridDimensions = this.gridDimensions;
+			if (gridDimensions)
+			{
+				gridDimensions.dataProviderCollectionChanged(event);
+				gridDimensions.rowCount = dataProvider.length;
+			}
+			
+			for each (var view:GridView in allGridViews)
+			{
+				if (!view)
+					continue;
+				// view.gridViewLayout.dataProviderCollectionChanged(event);      
+			}
+			
+			if (gridSelection)
+				selectionChanged = gridSelection.dataProviderCollectionChanged(event);            
+			
+			if (gridDimensions && hoverRowIndex != -1)
+				updateHoverForDataProviderChange(event);
+			
+			// The data has changed so need to do this here so the grid dimensions
+			// will be accurate if setting the caret requires scrolling.
+			invalidateSize();
+			invalidateDisplayList();
+			
+			if (caretRowIndex != -1)  {
+				if (event.kind == CollectionEventKind.RESET){
+					// defer for reset events 
+					updateCaretForDataProviderChanged = true;
+					updateCaretForDataProviderChangeLastEvent = event;
+					invalidateProperties();
+				}
+				else {
+					updateCaretForDataProviderChange(event);
+				}         
+			}
+			
+			
+			// Trigger bindings to selectedIndex/selectedCell/selectedItem and the plurals of those.
+			if (selectionChanged)
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function columns_collectionChangeHandler(event:CollectionEvent):void
+		{
+			
+			var column:GridColumn;
+			var columnIndex:int = event.location;
+			var i:int;
+			var selectionChanged:Boolean = false;
+			
+			switch (event.kind)
+			{
+				case CollectionEventKind.ADD: 
+				{
+					// Note: multiple columns may be added.
+					while (columnIndex < columns.length)
+					{
+						column = GridColumn(columns.getItemAt(columnIndex));
+						column.setGrid(this);
+						column.setColumnIndex(columnIndex);
+						columnIndex++;
+					}                  
+					break;
+				}
+					
+				case CollectionEventKind.MOVE:
+				{
+					// All columns between the old and new locations need to 
+					// have their index updated.
+					columnIndex = Math.min(event.oldLocation, event.location);
+					var maxIndex:int = Math.max(event.oldLocation, event.location);
+					while (columnIndex <= maxIndex)
+					{
+						column = GridColumn(columns.getItemAt(columnIndex));
+						column.setColumnIndex(columnIndex);
+						columnIndex++;
+					}                
+					break;
+				}
+					
+				case CollectionEventKind.REPLACE:
+				{
+					var items:Array = event.items;                   
+					var length:int = items.length;
+					for (i = 0; i < length; i++)
+					{
+						if (items[i].oldValue is GridColumn)
+						{
+							column = GridColumn(items[i].oldValue);
+							column.setGrid(null);
+							column.setColumnIndex(-1);
+						}
+						if (items[i].newValue is GridColumn)
+						{
+							column = GridColumn(items[i].newValue);
+							column.setGrid(this);
+							column.setColumnIndex(columnIndex);
+						}
+					}
+					break;
+				}
+					
+				case CollectionEventKind.UPDATE:
+				{
+					break;
+				}
+					
+				case CollectionEventKind.REFRESH:
+				{
+					for (columnIndex = 0; columnIndex < columns.length; columnIndex++)
+					{
+						column = GridColumn(columns.getItemAt(columnIndex));
+						column.setColumnIndex(columnIndex);
+					}                
+					break;
+				}
+					
+				case CollectionEventKind.REMOVE:
+				{
+					// Note: multiple columns may be removed.
+					var count:int = event.items.length;
+					
+					for (i = 0; i < count; i++)
+					{
+						column = GridColumn(event.items[i]);
+						column.setGrid(null);
+						column.setColumnIndex(-1);
+					}
+					
+					// Renumber the columns which follow the removed columns.
+					while (columnIndex < columns.length)
+					{
+						column = GridColumn(columns.getItemAt(columnIndex));
+						column.setColumnIndex(columnIndex);
+						columnIndex++;
+					}                  
+					
+					break;
+				}
+					
+				case CollectionEventKind.RESET:
+				{
+					for (columnIndex = 0; columnIndex < columns.length; columnIndex++)
+					{
+						column = GridColumn(columns.getItemAt(columnIndex));
+						column.setGrid(this);
+						column.setColumnIndex(columnIndex);
+					}                     
+					break;
+				}                                
+			}
+			
+			if (gridDimensions)
+				gridDimensions.columnsCollectionChanged(event);
+			
+			for each (var view:GridView in allGridViews)
+			{
+				if (!view)
+					continue;
+				// view.gridViewLayout.columnsCollectionChanged(event);      
+			}
+			
+			
+			if (gridSelection)
+				selectionChanged = gridSelection.columnsCollectionChanged(event);
+			
+			if (caretColumnIndex != -1)
+				updateCaretForColumnsChange(event);                
+			
+			if (gridDimensions && hoverColumnIndex != -1)
+				updateHoverForColumnsChange(event); 
+			
+			invalidateSize();
+			invalidateDisplayList(); 
+			
+			// Trigger bindings to selectedCell/selectedItem and the plurals of those.
+			if (selectionChanged)
+				dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+			
+		} 
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Methods
+		//
+		//--------------------------------------------------------------------------  
+		
+		/**
+		 *  @private
+		 *  Clears the layout's renderers and cached sizes. Also clears
+		 *  the typical item's size if clearTypicalSizes is true.
+		 */
+		mx_internal function clearGridLayoutCache(clearTypicalSizes:Boolean):void
+		{
+			for each (var view:GridView in allGridViews)
+			{
+				if (!view)
+					continue;
+				// view.gridViewLayout.clearVirtualLayoutCache();
+			}
+			
+			const gridDimensions:GridDimensions = this.gridDimensions;
+			if (gridDimensions)
+			{
+				if (clearTypicalSizes)
+				{
+					gridDimensions.clearTypicalCellWidthsAndHeights();
+					gridDimensions.clearColumns(0, gridDimensions.columnCount);
+				}
+				
+				gridDimensions.clearHeights();
+				
+				// Reset row count because dataProvider length may have changed.
+				gridDimensions.rowCount = _dataProvider ? _dataProvider.length : 0;
+			}
+			
+			// Reset content size so scroller's viewport can be resized.  There
+			// is loop-prevention logic in the scroller which may not allow the
+			// width/height to be reduced if there are automatic scrollbars.
+			// See ScrollerLayout/measure().
+			setContentSize(0, 0);
+		}
+		
+		/**
+		 *  @private
+		 *  Returns the index of the next GridColumn.visible==true column
+		 *  after index.
+		 *  Returns -1 if there are no more visible columns.
+		 *  To find the first GridColumn.visible==true column index, use
+		 *  getNextVisibleColumnIndex(-1).
+		 */
+		mx_internal function getNextVisibleColumnIndex(index:int=-1):int
+		{
+			if (index < -1)
+				return -1;
+			
+			const columns:IList = this.columns;
+			const columnsLength:int = (columns) ? columns.length : 0;
+			
+			for (var i:int = index + 1; i < columnsLength; i++)
+			{
+				
+				var column:GridColumn = columns.getItemAt(i) as GridColumn;
+				if (column && column.visible)
+					return i;
+				
+			}
+			
+			return -1;
+		}
+		
+		/**
+		 *  @private
+		 *  Returns the index of the previous GridColumn.visible==true column
+		 *  before index.
+		 *  Returns -1 if there are no more visible columns.
+		 *  To find the last GridColumn.visible==true column index, use
+		 *  getPreviousVisibleColumnIndex(columns.length).
+		 */
+		mx_internal function getPreviousVisibleColumnIndex(index:int):int
+		{
+			const columns:IList = this.columns;
+			if (!columns || index > columns.length)
+				return -1;
+			
+			for (var i:int = index - 1; i >= 0; i--)
+			{
+				
+				var column:GridColumn = columns.getItemAt(i) as GridColumn;
+				if (column && column.visible)
+					return i;
+				
+			}
+			
+			return -1;
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function initializeAnchorPosition(columnOnly:Boolean=false):void
+		{
+			if (!columnOnly)
+				anchorRowIndex = _dataProvider && _dataProvider.length > 0 ? 0 : -1; 
+			
+			// First visible column, or -1, if there are no columns or none are visible.
+			anchorColumnIndex = getNextVisibleColumnIndex(); 
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function initializeCaretPosition(columnOnly:Boolean=false):void
+		{
+			if (!columnOnly)
+				caretRowIndex = _dataProvider && _dataProvider.length > 0 ? 0 : -1;
+			
+			// First visible column, or -1, if there are no columns or none are visible.
+			caretColumnIndex = getNextVisibleColumnIndex();
+		}
+		
+		/**
+		 *  @private
+		 *  The caret change has already been comitted.  Dispatch the "caretChange"
+		 *  event.
+		 */
+		private function dispatchCaretChangeEvent():void
+		{
+			if (hasEventListener(GridCaretEvent.CARET_CHANGE))
+			{
+				const caretChangeEvent:GridCaretEvent = 
+					new GridCaretEvent(GridCaretEvent.CARET_CHANGE);
+				caretChangeEvent.oldRowIndex = _oldCaretRowIndex;
+				caretChangeEvent.oldColumnIndex = _oldCaretColumnIndex;
+				caretChangeEvent.newRowIndex = _caretRowIndex;
+				caretChangeEvent.newColumnIndex = _caretColumnIndex;
+				dispatchEvent(caretChangeEvent);
+			}
+		}
+		
+		
+		/**
+		 *  @private
+		 *  Renders a background for the container, if necessary.  It is used to fill in
+		 *  a transparent background fill as necessary to support the _mouseEnabledWhereTransparent flag.  It 
+		 *  is also used in ItemRenderers when handleBackgroundColor is set to true.
+		 *  We assume for now that we are the first layer to be rendered into the graphics
+		 *  context.
+		 * 
+		 *  This is mostly copied from GroupBase, but always chooses the virtualLayout path.  The Grid's
+		 *  layout has useVirtualLayout=false but the Grid's GridView always has useVirtualLayout=true
+		 *  which causes the GroupBase logic to go down the wrong path.  It also always positions at 0,0
+		 *  because the grid itself doesn't scroll, it scrols the layers
+		 */
+		/*override*/ 
+		mx_internal function drawBackground():void
+		{
+			/*
+			if (!mouseEnabledWhereTransparent || !hasMouseListeners)
+				return;
+			
+			var w:Number = (resizeMode == ResizeMode.SCALE) ? measuredWidth : unscaledWidth;
+			var h:Number = (resizeMode == ResizeMode.SCALE) ? measuredHeight : unscaledHeight;
+			
+			if (isNaN(w) || isNaN(h))
+				return;
+			
+			graphics.clear();
+			graphics.beginFill(0xFFFFFF, 0);
+			
+			graphics.drawRect(0, 0, w, h);
+			
+			graphics.endFill();
+			*/
+		}
+	
+		public function set nestLevel(value:int):void 
+		{
+			
+		}
+		
+		public function get nestLevel():int {
+			return 0;
+		}
+		
+		public function set processedDescriptors(value:Boolean):void {
+			
+		}
+		
+		public function get processedDescriptors():Boolean {
+			return false;
+		}
+		
+		public function set updateCompletePendingFlag(value:Boolean):void {
+			
+		}
+		
+		public  function get updateCompletePendingFlag():Boolean {
+			return false;
+		}
+		
+		private var _invalidatePropertiesFlag:Boolean = false;
+		
+		public function get invalidatePropertiesFlag():Boolean {
+			return _invalidatePropertiesFlag;
+		}
+		
+		public function set invalidatePropertiesFlag(value:Boolean):void {
+			_invalidatePropertiesFlag = value;
+		}
+		
+	}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/CellPosition.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/CellPosition.as
new file mode 100644
index 000000000..a429c506f
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/CellPosition.as
@@ -0,0 +1,151 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+
+/**
+ *  The CellPosition class defines a data structure 
+ *  used by the Spark data grid classes to represent selected cells in the 
+ *  control.  
+ *  Each selected cell is represented by an instance of this class.
+ *
+ *  @see spark.components.DataGrid#selectedCell
+ *  @see spark.components.DataGrid#selectedCells
+ *  @see spark.components.Grid#selectedCell
+ *  @see spark.components.Grid#selectedCells
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5
+ */
+public class CellPosition
+{    
+    // include "../../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructor.
+     * 
+     *  @param rowIndex The 0-based row index of the cell. 
+     *  A value of -1 indicates that the value is not set.
+     * 
+     *  @param columnIndex The 0-based column index of the cell. 
+     *  A value of -1 indicates that the value is not set.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function CellPosition(rowIndex:int = -1, columnIndex:int = -1)
+    {
+        super();
+        
+        _rowIndex = rowIndex;
+        _columnIndex = columnIndex;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+    
+    //----------------------------------
+    //  columnIndex
+    //----------------------------------
+    
+    private var _columnIndex:int;
+    
+    /**
+     *  The 0-based column index of the cell.
+     *  A value of -1 indicates that the value is not set.
+     * 
+     *  @default -1
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get columnIndex():int
+    {
+        return _columnIndex;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set columnIndex(value:int):void
+    {
+        _columnIndex = value;
+    }
+    
+    //----------------------------------
+    //  rowIndex
+    //----------------------------------
+    
+    private var _rowIndex:int;
+    
+    /**
+     *  The 0-based row index of the cell.  
+     *  A value of -1 indicates that the value is not set.
+     * 
+     *  @default -1
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get rowIndex():int
+    {
+        return _rowIndex;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set rowIndex(value:int):void
+    {
+        _rowIndex = value;
+    }    
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: Object
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     */
+    public function toString():String
+    {
+        return "[rowIndex=" + rowIndex + " columnIndex=" + columnIndex + "]";
+    }   
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/CellRegion.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/CellRegion.as
new file mode 100644
index 000000000..3bbae7a97
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/CellRegion.as
@@ -0,0 +1,220 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+    
+/**
+ *  The CellRegion class defines a data structure 
+ *  used by the Spark data grid classes to represent a rectangular region of
+ *  cells in the control. 
+ *  The origin of the region is specified by the  
+ *  <code>rowIndex</code> and <code>columnIndex</code> properties.
+ *  The extent of the region is specified by the 
+ *  <code>rowCount</code> and the <code>columnCount</code> properties.
+ *
+ *  @see spark.components.DataGrid
+ *  @see spark.components.Grid
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5
+ */
+public class CellRegion
+{        
+    // include "../../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructor.
+     * 
+     *  @param rowIndex The 0-based row index of the origin cell. 
+     *  A value of -1 indicates that the value is not set.
+     * 
+     *  @param columnIndex The 0-based column index of the origin cell. 
+     *  A value of -1 indicates that the value is not set.
+     * 
+     *  @param rowCount The number of rows in the cell region.
+     * 
+     *  @param columnCount The number of columns in the cell region.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function CellRegion(rowIndex:int = -1, columnIndex:int = -1,
+                               rowCount:int = 0, columnCount:int = 0)
+    {
+        super();
+        
+        _rowIndex = rowIndex;
+        _columnIndex = columnIndex;
+        
+        _rowCount = rowCount;
+        _columnCount = columnCount;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+    
+    //----------------------------------
+    //  columnCount
+    //----------------------------------
+    
+    private var _columnCount:int;
+    
+    /**
+     *  The number of columns in the cell region.
+     *
+     *  @default 0
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get columnCount():int
+    {
+        return _columnCount;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set columnCount(value:int):void
+    {
+        _columnCount = value;
+    }
+    
+    //----------------------------------
+    //  columnIndex
+    //----------------------------------
+    
+    private var _columnIndex:int;
+    
+    /**
+     *  The 0-based column index of the origin of the cell region.
+     *  A value of -1 indicates that the value is not set.
+     * 
+     *  @default -1
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get columnIndex():int
+    {
+        return _columnIndex;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set columnIndex(value:int):void
+    {
+        _columnIndex = value;
+    }
+    
+    //----------------------------------
+    //  rowCount
+    //----------------------------------
+    
+    private var _rowCount:int;
+    
+    /**
+     *  The number of rows in the cell region.
+     *
+     *  @default 0
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get rowCount():int
+    {
+        return _rowCount;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set rowCount(value:int):void
+    {
+        _rowCount = value;
+    }
+
+    //----------------------------------
+    //  rowIndex
+    //----------------------------------
+    
+    private var _rowIndex:int;
+    
+    /**
+     *  The 0-based row index of the origin of the cell region.  
+     *  A value of -1 indicates that the value is not set.
+     * 
+     *  @default -1
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+
+     */
+    public function get rowIndex():int
+    {
+        return _rowIndex;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set rowIndex(value:int):void
+    {
+        _rowIndex = value;
+    }  
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: Object
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     */
+    public function toString():String
+    {
+        return "[rowIndex=" + rowIndex + " columnIndex=" + columnIndex + 
+                " rowCount=" + rowCount + " columnCount=" + columnCount + "]";
+    }   
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/ComplexSortField.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/ComplexSortField.as
new file mode 100644
index 000000000..244410171
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/ComplexSortField.as
@@ -0,0 +1,53 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.collections {
+    import mx.collections.IComplexSortField;
+    import mx.utils.ObjectUtil;
+
+    public class ComplexSortField extends SortField implements IComplexSortField {
+        private var _nameParts:Array;
+
+        public function ComplexSortField(name:String = null, descending:Boolean = false, numeric:Object = null, sortCompareType:String = null, customCompareFunction:Function = null)
+        {
+            super(name, descending, numeric, sortCompareType, customCompareFunction);
+            _nameParts = name ? name.split(".") : [];
+        }
+
+        public function get nameParts():Array
+        {
+            return _nameParts;
+        }
+
+        override public function objectHasSortField(object:Object):Boolean
+        {
+            return object && nameParts && nameParts.length && object.hasOwnProperty(nameParts[0]);
+        }
+
+        override protected function getSortFieldValue(obj:Object):*
+        {
+            return ObjectUtil.getValue(obj, _nameParts);
+        }
+
+        override public function get arraySortOnOptions():int
+        {
+            return -1;
+        }
+    }
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridColumn.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridColumn.as
new file mode 100644
index 000000000..762d837ab
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridColumn.as
@@ -0,0 +1,1828 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+    // import flash.events.Event;
+    // import flash.events.EventDispatcher;
+	
+	import org.apache.royale.events.Event;
+	import org.apache.royale.events.EventDispatcher;
+
+    // import mx.collections.ComplexFieldChangeWatcher;//
+    import mx.collections.ISortField;
+    import mx.collections.ListCollectionView;
+    import mx.core.ClassFactory;
+    import mx.core.IFactory;
+    import mx.events.CollectionEvent;
+    import mx.events.CollectionEventKind;
+    import mx.events.PropertyChangeEvent;
+    import mx.formatters.IFormatter;
+    import mx.styles.IAdvancedStyleClient;
+    import mx.utils.ObjectUtil;
+    import mx.core.mx_internal;
+	import mx.collections.SortField;// import spark.collections.SortField;
+    import spark.components.Grid;
+
+    use namespace mx_internal;
+
+/**
+ *  The GridColumn class defines a column of a Spark grid control,
+ *  such as the Spark DataGrid or Grid control.
+ *  Each data provider item for the control corresponds to one row of the grid. 
+ *  The GridColumn class specifies the field of the data provider item 
+ *  whose value is to be displayed in the column.
+ *  It also specifies the item renderer used to display that value, the item editor
+ *  used to change the value, and other properties of the column.
+ *
+ *  @mxml <p>The <code>&lt;s:GridColumn&gt;</code> tag inherits all of the tag 
+ *  attributes of its superclass and adds the following tag attributes:</p>
+ *
+ *  <pre>
+ *  &lt;s:GridColumn
+ *    <strong>Properties</strong>
+ *    dataField="null"
+ *    dataTipField="null"
+ *    dataTipFormatter="null"
+ *    dataTipFunction="null"
+ *    editable="true"
+ *    formatter="null"
+ *    headerRenderer="null"
+ *    headerText="<i>value of dataField</i>"
+ *    imeMode="null"
+ *    itemEditor="null"
+ *    itemRenderer="null"
+ *    itemRendererFunction="null"
+ *    labelFunction="null"
+ *    maxWidth="NaN"
+ *    minWidth="20"
+ *    rendererIsEditable="false"
+ *    resizeable="true"
+ *    showDataTips="undefined"
+ *    sortable="true"
+ *    sortCompareFunction="null"
+ *    sortDescending="false"
+ *    visible="true"
+ *    width="NaN"
+ *  /&gt;
+ *  </pre>
+ * 
+ *  @see spark.components.Grid
+ *  @see spark.components.DataGrid
+ * 
+ *  @includeExample examples/GridColumnExample.mxml
+ *  @includeExample examples/GridColumnVisibilityExample.mxml
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5
+ */   
+public class GridColumn extends EventDispatcher
+{
+    // include "../../core/Version.as";
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Class constants
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  The return value for the <code>itemToLabel()</code> or 
+     *  <code>itemToDataTip()</code> method  if resolving the corresponding 
+     *  property name (path) fails.  
+     *  The value of this constant is a single space String: <code>" "</code>.
+     * 
+     *  @see #itemToLabel
+     *  @see #itemToDataTip
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public static const ERROR_TEXT:String = " ";
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Class variables and methods
+    //
+    //--------------------------------------------------------------------------
+    
+    //----------------------------------
+    //  defaultItemEditorFactory
+    //----------------------------------
+    
+    private static var _defaultItemEditorFactory:IFactory;
+    
+    /**
+     *  @private
+     */
+    /*mx_internal static function get defaultItemEditorFactory():IFactory
+    {
+        if (!_defaultItemEditorFactory)
+            //_defaultItemEditorFactory = new ClassFactory(DefaultGridItemEditor);
+        return _defaultItemEditorFactory;
+    }*/
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor. 
+     * 
+     *  @param columnName Initial value for the <code>dataField</code> and 
+     *     <code>headerText</code> properties. 
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function GridColumn(columnName:String = null)
+    {
+        super();
+        
+        if (columnName)
+            dataField = headerText = columnName;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+    
+    //----------------------------------
+    //  grid
+    //----------------------------------
+    
+    private var _grid:Grid = null;
+    
+    /** 
+     *  @private
+     *  Set by the Grid when this column is added to grid.columns, set
+     *  to null when the column is removed.
+     */
+    mx_internal function setGrid(value:Grid):void
+    {
+        if (_grid == value)
+            return;
+        
+        _grid = value;
+        dispatchChangeEvent("gridChanged");        
+    }
+
+    [Bindable("gridChanged")]    
+    
+    /**
+     *  The Grid object associated with this column.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get grid():Grid
+    {
+        return _grid;
+    }
+    
+    //----------------------------------
+    //  columnIndex
+    //----------------------------------
+    
+    private var _columnIndex:int = -1;
+    
+    /** 
+     *  @private
+     *  Set by the Grid when this column is added to the grid.columns, set
+     *  to -1 when the column is removed.
+     */
+    mx_internal function setColumnIndex(value:int):void
+    {
+        if (_columnIndex == value)
+            return;
+        
+        _columnIndex = value;
+        dispatchChangeEvent("columnIndexChanged");        
+    }
+    
+    [Bindable("columnIndexChanged")]    
+    
+    /**
+     *  The position of this column in the grid's column list, 
+     *  or -1 if this column's grid is null.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get columnIndex():int
+    {
+        return _columnIndex;
+    }   
+    
+    //----------------------------------
+    //  dataField
+    //----------------------------------
+    
+    private var _dataField:String = null;
+    mx_internal var dataFieldPath:Array = [];
+    
+    [Bindable("dataFieldChanged")]    
+    
+    /**
+     *  The name of the field or property in the data provider item associated 
+     *  with the column. 
+     *  Each GridColumn requires this property or 
+     *  the <code>labelFunction</code> property to be set 
+     *  to calculate the displayable text for the item renderer.
+     *  If the <code>dataField</code>
+     *  and <code>labelFunction</code> properties are set, 
+     *  the data is displayed using the <code>labelFunction</code> and sorted
+     *  using the <code>dataField</code>.  
+     *
+     *  <p>This value of this property is not necessarily the String that 
+     *  is displayed in the column header.  This property is
+     *  used only to access the data in the data provider. 
+     *  For more information, see the <code>headerText</code> property.</p>
+     * 
+     *  <p>If the column or its grid specifies a <code>labelFunction</code>, 
+     *  then the dataField is not used.</p>
+     *      
+     *  @default null
+     * 
+     *  @see #itemToLabel
+     *  @see #labelFunction
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get dataField():String
+    {
+        return _dataField;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set dataField(value:String):void
+    {
+        if (_dataField == value)
+            return;
+        
+        _dataField = value;
+        
+        if (value == null)
+        {
+            dataFieldPath = [];
+        }
+        else if (value.indexOf( "." ) != -1) 
+        {
+            dataFieldPath = value.split(".");
+        }
+        else
+        {
+            dataFieldPath = [value];
+        }
+
+        invalidateGrid();
+        if (grid)
+            grid.clearGridLayoutCache(true);
+        
+        dispatchChangeEvent("dataFieldChanged");
+    }
+    
+    //----------------------------------
+    //  dataTipField
+    //----------------------------------
+    
+    private var _dataTipField:String = null;
+    
+    [Bindable("dataTipFieldChanged")]    
+    
+    /**
+     *  The name of the field in the data provider to display as the datatip. 
+     *  By default, if <code>showDataTips</code> is <code>true</code>,
+     *  the associated grid control looks for a property named 
+     *  <code>label</code> on each data provider item and displays it.
+     *  However, if the data provider does not contain a <code>label</code>
+     *  property, you can set the <code>dataTipField</code> property to
+     *  specify a different property name.  
+     *  For example, you could set the value to "FullName" when a user views a
+     *  set of people's names included from a database.
+     *
+     *  <p><code>GridColumn.dataTipField</code> takes precedence over this property.</p>
+     * 
+     *  <p>If this column or its grid specifies a value for the 
+     *  <code>dataTipFunction</code> property, then the
+     *  <code>dataTipField</code> property is ignored.</p>
+     * 
+     *  @default null
+     *  @see #dataTipFunction
+     *  @see #itemToDataTip
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get dataTipField():String
+    {
+        return _dataTipField;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set dataTipField(value:String):void
+    {
+        if (_dataTipField == value)
+            return;
+        
+        _dataTipField = value;
+        
+        if (grid)
+            grid.invalidateDisplayList();
+        
+        dispatchChangeEvent("dataTipFieldChanged");
+    }
+    
+    //----------------------------------
+    //  dataTipFormatter
+    //----------------------------------
+    
+    private var _dataTipFormatter:IFormatter = null;
+    private var dataTipFormatterStyleParentInvalid:Boolean = false;
+    
+    [Bindable("dataTipFormatterChanged")]
+    [Inspectable(category="General")]
+    
+    /**
+     *  Specifies the formatter used by the column's <code>itemToDataTip()</code> method to 
+     *  convert data provider items to Strings.
+     * 
+     *  <p>If the formatter's <code>styleParent</code> was not specified, it's set
+     *  to the column's grid, so that the formatter inherits the grid's <code>locale</code> style.</p>
+     *
+     *  @default null
+     * 
+     *  @see #itemToDataTip
+     *  @see #formatter
+     *
+     *  @default null
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get dataTipFormatter():IFormatter
+    {
+        if (dataTipFormatterStyleParentInvalid && grid)
+        {
+            const asc:IAdvancedStyleClient = _dataTipFormatter as IAdvancedStyleClient;
+            if (asc && (asc.styleParent != grid))
+                // grid.addStyleClient(asc);            
+            dataTipFormatterStyleParentInvalid = false;
+        }
+        
+        return _dataTipFormatter;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set dataTipFormatter(value:IFormatter):void
+    {
+        if (_dataTipFormatter == value)
+            return;
+        
+        if (grid && _dataTipFormatter)
+        {
+            const oldASC:IAdvancedStyleClient = _dataTipFormatter as IAdvancedStyleClient;
+            //if (oldASC && (oldASC.styleParent == grid))
+            //    //grid.removeStyleClient(oldASC);
+        }        
+        
+        _dataTipFormatter = value;
+        dataTipFormatterStyleParentInvalid = true;
+        
+        if (grid)
+            grid.invalidateDisplayList();
+        
+        dispatchChangeEvent("dataTipFormatterChanged");
+    }
+    
+    
+    //----------------------------------
+    //  dataTipFunction
+    //----------------------------------
+    
+    private var _dataTipFunction:Function = null;
+    
+    [Bindable("dataTipFunctionChanged")]
+    
+    /**
+     *  Specifies a callback function to run on each item of the data provider 
+     *  to determine its data tip.
+     *  This property is used by the <code>itemToDataTip</code> method.
+     * 
+     *  <p>By default, if <code>showDataTips</code> is <code>true</code>,
+     *  the column looks for a property named <code>label</code>
+     *  on each data provider item and displays it as its data tip.
+     *  However, some data providers do not have a <code>label</code> property 
+     *  nor do they have another property that you can use for displaying data 
+     *  in the rows.</p>
+     *
+     *  <p>For example, you have a data provider that contains a lastName 
+     *  and firstName fields, but you want to display full names as the data tip.
+     *  You can specify a function to the <code>dataTipFunction</code> property 
+     *  that returns a single String containing the value of both fields. You 
+     *  can also use the <code>dataTipFunction</code> property for handling 
+     *  formatting and localization.</p>
+     * 
+     *  <p>The signature of the <code>dataTipFunction</code> function must match the following:
+     * 
+     *  <pre>dataTipFunction(item:Object, column:GridColumn):String</pre>
+     *
+     *  The <code>item</code> parameter is the data provider item for an entire row.  
+     *  The second parameter is this column object.</p>
+     *
+     *  <p>A typical function might concatenate an item's firstName and
+     *  lastName properties, or do some custom formatting on a Date value
+     *  property.</p>
+     *
+     *  @default null
+     * 
+     *  @see #itemToDataTip
+     *  @see #dataTipField
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get dataTipFunction():Function
+    {
+        return _dataTipFunction;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set dataTipFunction(value:Function):void
+    {
+        if (_dataTipFunction == value)
+            return;
+        
+        _dataTipFunction = value;
+        
+        if (grid)
+            grid.invalidateDisplayList();
+        
+        dispatchChangeEvent("dataTipFunctionChanged");
+    }
+    
+    //----------------------------------
+    //  editable
+    //----------------------------------
+    
+    private var _editable:Boolean = true;
+    
+    [Bindable("editableChanged")]
+    [Inspectable(category="General")]
+    
+    /**
+     *  Indicates whether the items in the column are editable.
+     *  If <code>true</code>, and the associated grid's <code>editable</code>
+     *  property is also <code>true</code>, the items in a column are 
+     *  editable and can be individually edited
+     *  by clicking on a selected item, or by navigating to the item and 
+     *  pressing the F2 key.
+     *
+     *  @default true
+     * 
+     *  @see spark.components.DataGrid#editable
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get editable():Boolean
+    {
+        return _editable;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set editable(value:Boolean):void
+    {
+        if (_editable == value)
+            return;
+        
+        _editable = value;
+        dispatchChangeEvent("editableChanged");
+    }
+    
+    //----------------------------------
+    //  editorActivationMouseEvent
+    //----------------------------------
+    
+    private var _editorActivationMouseEvent:String = null;
+    
+    [Bindable("editorActivationMouseEventChanged")]
+    [Inspectable(category="General", enumeration="doubleClick,none,singleClick,singleClickOnSelectedCell", defaultValue="singleClickOnSelectedCell")]
+
+    /**
+     *  The type of mouse event that starts an editor session. Must be one of
+     *  values in <code>GridItemEditorMouseEvent</code>. Each grid
+     *  column may use a different value for cell activation. If no
+     *  value is specified the DataGrid's <code>editorActivationMouseEvent
+     *  </code> will be used.
+     *       
+     *  @default null
+     * 
+     *  @see spark.components.DataGrid
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 11
+     *  @playerversion AIR 3.0
+     *  @productversion Flex 5.0
+     */
+    public function get editorActivationMouseEvent():String
+    {
+        return _editorActivationMouseEvent;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set editorActivationMouseEvent(value:String):void
+    {
+        if (_editorActivationMouseEvent == value)
+            return;
+        
+        _editorActivationMouseEvent = value;
+        dispatchChangeEvent("editorActivationMouseEventChanged");
+    }
+    
+    //----------------------------------
+    //  formatter
+    //----------------------------------
+    
+    private var _formatter:IFormatter = null;
+    private var formatterStyleParentInvalid:Boolean = false;
+    
+    [Bindable("formatterChanged")]
+    [Inspectable(category="General")]
+    
+    /**
+     *  Specifies the formatter used by the column's <code>itemToLabel()</code> method to 
+     *  convert data provider items to strings.
+     * 
+     *  <p>If the formatter's <code>styleParent</code> was not specified, it's set
+     *  to the column's grid, so that the formatter inherits the grid's <code>locale</code> style.</p>
+     *
+     *  @default null
+     * 
+     *  @see #itemToLabel
+     *  @see #dataTipFormatter
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get formatter():IFormatter
+    {
+        if (formatterStyleParentInvalid && grid)
+        {
+            const asc:IAdvancedStyleClient = _formatter as IAdvancedStyleClient;
+            if (asc && (asc.styleParent != grid))
+                // grid.addStyleClient(asc);            
+            formatterStyleParentInvalid = false;
+        }
+        
+        return _formatter;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set formatter(value:IFormatter):void
+    {
+        if (_formatter == value)
+            return;
+        
+        if (grid && _formatter)
+        {
+            const oldASC:IAdvancedStyleClient = _formatter as IAdvancedStyleClient;
+            // if (oldASC && (oldASC.styleParent == grid))
+            //     grid.removeStyleClient(oldASC);
+        }
+        
+        _formatter = value;
+        formatterStyleParentInvalid = true;
+
+        
+        if (grid)
+        {
+            invalidateGrid();
+            grid.clearGridLayoutCache(true);
+        }
+        
+        dispatchChangeEvent("formatterChanged");
+    }
+    
+    //----------------------------------
+    //  headerRenderer
+    //----------------------------------
+    
+    private var _headerRenderer:IFactory = null;
+    
+    [Bindable("headerRendererChanged")]
+    
+    /**
+     *  The class factory for the IGridItemRenderer class used as 
+     *  the header for this column.  
+     *  If unspecified, the DataGrid controls's <code>columnHeaderGroup</code>
+     *  skin part defines the default header renderer.
+     * 
+     *  @default null
+     *
+     *  @see #headerText
+     *  @see IGridItemRenderer
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get headerRenderer():IFactory
+    {
+        return _headerRenderer;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set headerRenderer(value:IFactory):void
+    {
+        if (_headerRenderer == value)
+            return;
+        
+        _headerRenderer = value;
+
+        if (grid)
+            grid.invalidateDisplayList();
+        
+        dispatchChangeEvent("headerRendererChanged");
+    }
+    
+    //----------------------------------
+    //  headerText
+    //----------------------------------
+    
+    private var _headerText:String;
+    
+    [Bindable("headerTextChanged")]
+    
+    /**
+     *  Text for the header of this column. 
+     *  By default, the associated grid control uses the value of 
+     *  the <code>dataField</code> property  as the header text.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get headerText():String
+    {
+        return (_headerText != null) ? _headerText : ((dataField) ? dataField : "");
+    }
+    
+    /**
+     *  @private
+     */
+    public function set headerText(value:String):void
+    {
+        _headerText = value;
+        
+        if (grid)
+            grid.invalidateDisplayList();
+
+        dispatchChangeEvent("headerTextChanged");
+    }
+   
+    //----------------------------------
+    //  imeMode
+    //----------------------------------
+    
+    private var _imeMode:String = null;
+    
+    [Inspectable(environment="none")]
+    
+    /**
+     *  @copy spark.components.gridClasses.GridItemEditor#imeMode
+     *
+     *  @see flash.system.IMEConversionMode
+     *
+     *  @default null
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get imeMode():String
+    {
+        return _imeMode;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set imeMode(value:String):void
+    {
+        _imeMode = value;
+    }
+    
+    //----------------------------------
+    //  itemEditor
+    //----------------------------------
+    
+    private var _itemEditor:IFactory = null;
+    
+    [Bindable("itemEditorChanged")]
+    
+    /**
+     *  A class factory for IGridItemEditor class used to edit individual 
+     *  grid cells in this column.
+     *  If this property is null, and the column grid's owner is a DataGrid control, 
+     *  then the value of the DataGrid control's <code>itemEditor</code> property is used.   
+     *  If no item editor is specified by the DataGrid control, 
+     *  then use the DefaultGridItemEditor class.
+     * 
+     *  <p>The default item editor is the DefaultGridItemEditor class, 
+     *  which lets you edit a simple text field. 
+     *  You can create custom item renderers by creating a subclass of the GridItemEditor class.
+     *  Your custom item editor can write data to the entire row of the grid
+     *  to define more complex editor. </p>
+     * 
+     *  @default null
+     *
+     *  @see spark.components.gridClasses.DefaultGridItemEditor
+     *  @see spark.components.gridClasses.GridItemEditor
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get itemEditor():IFactory
+    {
+        return _itemEditor;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set itemEditor(value:IFactory):void
+    {
+        if (_itemEditor == value)
+            return;
+        
+        _itemEditor = value;
+        
+        dispatchChangeEvent("itemEditorChanged");
+    }
+
+    //----------------------------------
+    //  itemRenderer
+    //----------------------------------
+
+    private var _itemRenderer:IFactory = null;
+    
+    [Bindable("itemRendererChanged")]
+    
+    /**
+     *  The class factory for the IGridItemRenderer class used to 
+     *  render individual grid cells.  
+     *  If not specified, use the value of the <code>itemRenderer</code> 
+     *  property from the associated grid control.
+     * 
+     *  <p>The default item renderer is the DefaultGridItemRenderer class, 
+     *  which displays the data item as text. 
+     *  You can create custom item renderers by creating a subclass of the GridItemRenderer class.
+     *  Your custom item renderer can access the data from the entire row of the grid
+     *  to define more complex visual representation of the cell. </p>
+     * 
+     *  <p>The default value is the value of the <code>itemRenderer</code> 
+     *  property from the associated grid control, or null.</p>
+     *
+     *  @see #dataField 
+     *  @see spark.skins.spark.DefaultGridItemRenderer
+     *  @see spark.components.gridClasses.GridItemRenderer
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get itemRenderer():IFactory
+    {
+        return (_itemRenderer) ? _itemRenderer : grid.itemRenderer;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set itemRenderer(value:IFactory):void
+    {
+        if (_itemRenderer == value)
+            return;
+        
+        _itemRenderer = value;
+
+        invalidateGrid();
+        if (grid)
+            grid.clearGridLayoutCache(true);
+        
+        dispatchChangeEvent("itemRendererChanged");
+    }
+    
+    //----------------------------------
+    //  itemRendererFunction
+    //----------------------------------
+    
+    private var _itemRendererFunction:Function = null;
+    
+    [Bindable("itemRendererFunctionChanged")]
+    
+    /**
+     *  If specified, the value of this property must be an idempotent function 
+     *  that returns an item renderer IFactory based on its data provider item 
+     *  and column parameters.  
+     *  Specifying a value to the <code>itemRendererFunction</code> property
+     *  makes it possible to use more than one item renderer in this column.
+     * 
+     *  <p>The function specified to the <code>itemRendererFunction</code> property 
+     *  must have the following signature:</p>
+     *
+     *  <pre>itemRendererFunction(item:Object, column:GridColumn):IFactory</pre>
+     *
+     *  <p>The <code>item</code> parameter is the data provider item for an entire row.  
+     *  The second parameter is this column object.</p> 
+     * 
+     *  <p>Shown below is an example of an item renderer function:</p>
+     *  <pre>
+     *  function myItemRendererFunction(item:Object, column:GridColumn):IFactory
+     *  {
+     *      return (item is Array) ? myArrayItemRenderer : myItemRenderer;
+     *  }
+     *  </pre>
+     *  
+     *  @default null
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get itemRendererFunction():Function
+    {
+        return _itemRendererFunction;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set itemRendererFunction(value:Function):void
+    {
+        if (_itemRendererFunction == value)
+            return;
+
+        _itemRendererFunction = value;
+        
+        invalidateGrid();
+        if (grid)
+            grid.clearGridLayoutCache(true);
+        
+        dispatchChangeEvent("itemRendererFunctionChanged");
+    }
+    
+    //----------------------------------
+    //  labelFunction
+    //----------------------------------
+    
+    private var _labelFunction:Function = null;
+    
+    [Bindable("labelFunctionChanged")]
+    
+    /**
+     *  An idempotent function that converts a data provider item into a column-specific string
+     *  that's used to initialize the item renderer's <code>label</code> property.
+     * 
+     *  <p>You can use a label function to combine the values of several data provider items
+     *  into a single string.  
+     *  If specified, this property is used by the 
+     *  <code>itemToLabel()</code> method, which computes the value of each item 
+     *  renderer's <code>label</code> property in this column.</p>
+     *
+     *  <p>The function specified to the <code>labelFunction</code> property 
+     *  must have the following signature:</p>
+     *
+     *  <pre>labelFunction(item:Object, column:GridColumn):String</pre>
+     *
+     *  <p>The <code>item</code> parameter is the data provider item for an entire row.  
+     *  The second parameter is this column object.</p>
+     *
+     *  <p>A typical label function could concatenate the firstName and
+     *  lastName properties of the data provider item , 
+     *  or do some custom formatting on a Date value property.</p>
+     * 
+     *  @default null
+     * 
+     *  @see #itemToLabel
+     *  @see #dataField
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get labelFunction():Function
+    {
+        return _labelFunction;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set labelFunction(value:Function):void
+    {
+        if (_labelFunction == value)
+            return;
+
+        _labelFunction = value;
+        
+        invalidateGrid();
+        if (grid)
+            grid.clearGridLayoutCache(true);
+        
+        dispatchChangeEvent("labelFunctionChanged");
+    }
+    
+    //----------------------------------
+    //  width
+    //---------------------------------- 
+    
+    private var _width:Number = NaN;
+    
+    [Bindable("widthChanged")]    
+    [PercentProxy("percentWidth")]
+    
+    /**
+     *  The width of this column in pixels. 
+     *  If specified, the grid's layout ignores its
+     *  <code>typicalItem</code> property and this column's 
+     *  <code>minWidth</code> and <code>maxWidth</code> properties.
+     * 
+     *  @default NaN
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get width():Number
+    {
+        return _width;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set width(value:Number):void
+    {
+        if (_width == value)
+            return;
+        
+        _width = value;
+        
+        invalidateGrid();
+        
+        // Reset content size so scroller's viewport can be resized.  There
+        // is loop-prevention logic in the scroller which may not allow the
+        // width/height to be reduced if there are automatic scrollbars.
+        // See ScrollerLayout/measure().
+        /*
+        if (grid)
+            grid.setContentSize(0, 0);
+        */
+        
+        dispatchChangeEvent("widthChanged");
+    }
+    
+    //----------------------------------
+    //  minWidth
+    //---------------------------------- 
+    
+    private var _minWidth:Number = 20;
+    
+    [Bindable("minWidthChanged")]    
+    
+    /**
+     *  The minimum width of this column in pixels. 
+     *  If specified, the grid's layout makes the column's layout 
+     *  width the larger of the width of the <code>typicalItem</code> and 
+     *  the <code>minWidth</code>.
+     *  If this column is resizable, this property limits how small 
+     *  the user can make this column.
+     *  Setting this property does not change the <code>width</code> 
+     *  or <code>maxWidth</code> properties.
+     *  
+     *  @default 20
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get minWidth():Number
+    {
+        return _minWidth;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set minWidth(value:Number):void
+    {
+        if (_minWidth == value)
+            return;
+        
+        _minWidth = value;
+        
+        invalidateGrid();
+
+        // Reset content size so scroller's viewport can be resized.  There
+        // is loop-prevention logic in the scroller which may not allow the
+        // width/height to be reduced if there are automatic scrollbars.
+        // See ScrollerLayout/measure().
+        if (grid)
+            grid.setContentSize(0, 0);
+        
+        dispatchChangeEvent("minWidthChanged");
+    }    
+       
+    //----------------------------------
+    //  maxWidth
+    //---------------------------------- 
+    
+    private var _maxWidth:Number = NaN;
+    
+    [Bindable("maxWidthChanged")]
+    
+    /**
+     *  The maximum width of this column in pixels. 
+     *  If specified, the grid's layout makes the column's layout width the 
+     *  smaller of the width of the <code>typicalItem</code> and the <code>maxWidth</code>.
+     *  If this column is resizable, this property limits how wide the user can make this column.
+     *  Setting this property does not change the <code>width</code> 
+     *  or <code>minWidth</code> properties.
+     *
+     *  @default NaN
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get maxWidth():Number
+    {
+        return _maxWidth;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set maxWidth(value:Number):void
+    {
+        if (_maxWidth == value)
+            return;
+        
+        _maxWidth = value;
+        
+        invalidateGrid();
+
+        // Reset content size so scroller's viewport can be resized.  There
+        // is loop-prevention logic in the scroller which may not allow the
+        // width/height to be reduced if there are automatic scrollbars.
+        // See ScrollerLayout/measure().
+        if (grid)
+            grid.setContentSize(0, 0);
+        
+        dispatchChangeEvent("maxWidthChanged");
+    }
+    
+    [Inspectable(category="General")]
+    
+    /**
+     *  @private
+     */
+    private var _percentWidth:Number = NaN;
+
+    [Bindable("widthChanged")]
+    [Inspectable(environment="none")]
+    
+    /**
+     *  The width of this column as a percentage of DataGrid width. 
+     *  Setting this property does not change the <code>width</code> 
+     *  or <code>minWidth</code> properties.
+     *
+     *  @default NaN
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 13
+     *  @playerversion AIR 13.0
+     *  @productversion Flex 4.12.2
+     */
+    public function get percentWidth ():Number 
+    {
+        return _percentWidth;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set percentWidth(value:Number):void 
+    {
+        if (_percentWidth == value) 
+        {
+            return;
+        }
+        this._percentWidth = value;
+        invalidateGrid();
+        
+        dispatchChangeEvent("widthChanged");
+    }
+
+    //----------------------------------
+    //  rendererIsEditable
+    //----------------------------------
+    
+    private var _rendererIsEditable:Boolean = false;
+    
+    [Bindable("rendererIsEditableChanged")]
+    
+    /**
+     *  Determines whether any of the item renderer's controls are editable.
+     *  If the column is editable, the focusable controls in the item renderer
+     *  are given keyboard focus when the user starts editing the item
+     *  renderer.
+     *
+     *  <p>When you set this property to <code>true</code>, the cell becomes 
+     *  editable when the user clicks inside of it. 
+     *  Because the cell is editable, the DataGrid displays the <code>editorIndicator</code> 
+     *  skin part, which appears on top of the <code>selectionIndicator</code> skin part. 
+     *  Therefore, the user does not see an indicator for cell selection until the 
+     *  edit session is complete. 
+     *  You can create a custom skin to remove or modify the <code>editorIndicator</code> 
+     *  skin part so that the <code>selectionIndicator</code> skin part appears. 
+     *  For example, you can set <code>alpha</code> property of the <code>editorIndicator</code> 
+     *  to allow the <code>selectionIndicator</code> to show through, or change 
+     *  the size of the editorIndicator so that it is smaller than the cell.</p>
+     * 
+     *  <p>By setting this property to <code>true</code>, you take responsibility for 
+     *  validating and saving input collected by the item renderer.  
+     *  If the item renderer contains an override of the <code>IGridItemRenderer.prepare()</code> method, 
+     *  then you must ensure that unsaved input field changes are not overwritten.   
+     *  For example, <code>rendererIsEditable</code> is <code>true</code>  
+     *  and the renderer contains a single TextInput element that displays
+     *  the value of <code>data.myDataField</code>.
+     *  If the renderer's <code>prepare()</code> method sets the TextInput control's
+     *  <code>text</code> property, then the <code>prepare()</code> method must 
+     *  not set the <code>text</code> property when there are pending changes.</p>
+     * 
+     *  @default false
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get rendererIsEditable():Boolean
+    {
+        return _rendererIsEditable;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set rendererIsEditable(value:Boolean):void
+    {
+        if (_rendererIsEditable == value)
+            return;
+        
+        _rendererIsEditable = value;
+        dispatchChangeEvent("rendererIsEditableChanged");
+    }
+    
+    //----------------------------------
+    //  resizable
+    //----------------------------------
+    
+    private var _resizable:Boolean = true;
+    
+    [Bindable("resizableChanged")]   
+    [Inspectable(category="General")]
+    
+    /**
+     *  Indicates whether the user is allowed to resize
+     *  the width of the column.
+     *  If <code>true</code>, and the <code>resizableColumns</code> property of 
+     *  the associated grid is also <code>true</code>, the user can drag 
+     *  the grid lines between the column headers to resize the column. 
+     * 
+     *  @default true
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get resizable():Boolean
+    {
+        return _resizable;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set resizable(value:Boolean):void
+    {
+        if (_resizable == value)
+            return;
+        
+        _resizable = value;
+        dispatchChangeEvent("resizableChanged");
+    }
+    
+    //----------------------------------
+    //  showDataTips
+    //----------------------------------
+    
+    private var _showDataTips:* = undefined;
+    
+    [Bindable("showDataTipsChanged")]  
+    
+    /**
+     *  Indicates whether the datatips are shown in the column.
+     *  If <code>true</code>, datatips are displayed for text in the rows. 
+     *  Datatips are tooltips designed to show the text that is too long for the row.   
+     * 
+     *  <p>If this property's value is undefined, the default, then the associated 
+     *  grid's <code>showDataTips</code> property determines if datatips are shown.   
+     *  If this property is set, the grid's <code>showDataTips</code> property is ignored.</p>
+     * 
+     *  @default undefined
+     * 
+     *  @see #getShowDataTips
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get showDataTips():*
+    {
+        return _showDataTips;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set showDataTips(value:*):void
+    {
+        if (_showDataTips === value)
+            return;
+
+        _showDataTips = value;
+        
+        if (grid)
+            grid.invalidateDisplayList();
+        
+        dispatchChangeEvent("showDataTipsChanged");        
+    }
+    
+    /**
+     *  @private
+     */
+    mx_internal function getShowDataTips():Boolean
+    {
+        return (showDataTips === undefined) ? grid && grid.showDataTips : showDataTips;    
+    }
+    
+    //----------------------------------
+    //  sortable
+    //----------------------------------
+    
+    private var _sortable:Boolean = true;
+    
+    [Bindable("sortableChanged")]
+    [Inspectable(category="General")]
+    
+    /**
+     *  If <code>true</code>, and if the grid's data provider is an ICollectionView,
+     *  and if the associated grid's <code>sortableColumns</code> property is <code>true</code>,
+     *  then this column supports interactive sorting. 
+     *  Typically the column's header handles mouse clicks by setting the data provider's 
+     *  <code>sort</code> property to a Sort object whose SortField is this column's <code>dataField</code>.
+     *  
+     *  <p>If the data provider is not an ICollectionView, then this property has no effect.</p>
+     *  
+     *  @default true
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get sortable():Boolean
+    {
+        return _sortable;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set sortable(value:Boolean):void
+    {
+        if (_sortable == value)
+            return;
+        
+        _sortable = value;
+        
+        dispatchChangeEvent("sortableChanged");        
+    }
+    
+    //----------------------------------
+    //  sortCompareFunction
+    //----------------------------------
+    
+    private var _sortCompareFunction:Function;
+    
+    [Bindable("sortCompareFunctionChanged")]
+    [Inspectable(category="Advanced")]
+    
+    /**
+     *  The function that compares two elements during a sort of on the
+     *  data elements of this column.
+     *  If you specify a value of the <code>labelFunction</code> property,
+     *  you typically also provide a <code>sortCompareFunction</code>.
+     *
+     *  <p>The sortCompareFunction's signature must match the following:</p>
+     *
+     *  <pre>sortCompareFunction(obj1:Object, obj2:Object, column:GridColumn):int</pre>
+     * 
+     *  <p>The function should return a value based on the comparison
+     *  of the objects: </p>
+     *  <ul>
+     *    <li>-1 if obj1 should appear before obj2 in ascending order. </li>
+     *    <li>0 if obj1 = obj2. </li>
+     *    <li>1 if obj1 should appear after obj2 in ascending order.</li>
+     *  </ul>
+     *  
+     *  <p>The function may use the column parameter to write generic
+     *  compare functions.</p>
+     * 
+     *  <p><strong>Note:</strong> The <code>obj1</code> and
+     *  <code>obj2</code> parameters are entire data provider elements and not
+     *  just the data for the item.</p>
+     * 
+     *  <p>If the dataProvider is not an ICollectionView, then this property has no effect.</p>
+     *  
+     *  @default null
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get sortCompareFunction():Function
+    {
+        return _sortCompareFunction;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set sortCompareFunction(value:Function):void
+    {
+        if (_sortCompareFunction == value)
+            return;
+        
+        _sortCompareFunction = value;
+        
+        dispatchChangeEvent("sortCompareFunctionChanged");
+    }
+
+
+    //----------------------------------
+    //  sortCompareType
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    private var _sortCompareType:String;
+
+    /**
+	 *  The sortCompareType defines the valid constant values for the 
+	 *  <code>sortCompareType</code> property of the <code>SortField</code> and <code>GridColumn</code>.
+	 *  
+	 *  <p>Use the constants in ActionsScript, as the following example shows:</p>
+	 *  <pre>
+	 *    column.sortCompareType = SortFieldCompareTypes.NUMERIC;
+	 *  </pre>
+	 *
+	 *  <p>In MXML, use the String value of the constants, as the following example shows:</p>
+	 *  <pre>
+	 *    &lt;s:GridColumn sortCompareType="numeric" /&gt; 
+	 *  </pre>
+	 * 
+     *  @see spark.collections.SortFieldCompareTypes
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 11.8
+     *  @playerversion AIR 3.8
+     *  @productversion Flex 4.11
+     */
+    [Bindable("sortCompareTypeChanged")]
+    public function get sortCompareType():String
+    {
+        return _sortCompareType;
+    }
+
+    /**
+     *  @private
+     */
+    public function set sortCompareType(value:String):void
+    {
+        if (_sortCompareType != value)
+        {
+            _sortCompareType = value;
+            dispatchEvent(new Event("sortCompareTypeChanged"));
+        }
+    }
+
+
+    //----------------------------------
+    //  sortDescending
+    //----------------------------------
+    
+    private var _sortDescending:Boolean = false;
+    
+    [Bindable("sortDescendingChanged")]
+    
+    /**
+     *  If <code>true</code>, this column is sorted in descending order. 
+     *  For example, if the column's <code>dataField</code> contains a numeric value, 
+     *  then the first row would be the one with the largest value
+     *  for this column. 
+     *
+     *  <p>Setting this property does not start a sort; it only sets the sort direction.
+     *  When the <code>dataProvider.refresh()</code> method is called, the sort is performed.</p>
+     * 
+     *  <p>If the data provider is not an ICollectionView, then this property has no effect.</p>
+     * 
+     *  @default false
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get sortDescending():Boolean
+    {
+        return _sortDescending;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set sortDescending(value:Boolean):void
+    {
+        if (_sortDescending == value)
+            return;
+        
+        _sortDescending = value;
+        
+        dispatchChangeEvent("sortDescendingChanged");
+    }
+    
+    //----------------------------------
+    //  sortField
+    //----------------------------------
+    
+    /**
+     *  Returns a SortField that can be used to sort a collection by this
+     *  column's <code>dataField</code>.
+     *  
+     *  <p>If the <code>sortCompareFunction</code> property is defined, 
+     *  then the SortField's <code>compareFunction</code> is automatically set.</p>
+     * 
+     *  <p>If the <code>sortCompareFunction</code> property is not defined
+     *  and the <code>dataField</code> is complex, then the SortField's
+     *  compare function is assigned to a closure around a default compare
+     *  function that handles the complex <code>dataField</code>.</p>
+     *
+     *  <p>If the <code>sortCompareFunction</code> and 
+     *  <code>dataField</code> properties are not defined, but the
+     *  <code>labelFunction</code> property is defined, then it assigns the 
+     *  <code>compareFunction</code> to a closure that does a basic string compare 
+     *  on the <code>labelFunction</code> applied to the data objects.</p>
+     *
+     *  @see spark.collections.SortField 
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get sortField():ISortField
+    {
+        const column:GridColumn = this;
+        const isComplexDataField:Boolean = dataFieldPath.length > 1;
+
+        // TODO (klin): Might be fixed in Spark Sort. The only reason this is
+        // required is because MX Sort RTEs when the dataField doesn't exist on the
+        // data object even though a sortCompareFunction is defined.
+        var sortField:ISortField = isComplexDataField ? new GridSortFieldComplex(this, dataField) : new GridSortFieldSimple(this, dataField);
+
+        sortField.sortCompareType = column._sortCompareType;
+
+        var compareFunc:Function = null;
+        if (_sortCompareFunction != null)
+        {
+            compareFunc = function (a:Object, b:Object):int
+            { 
+                return _sortCompareFunction(a, b, column);
+            };
+        }
+        else
+        {
+            // If no sortCompareFunction is specified, there is a default for
+            // labelFunctions without dataFields.
+            if(dataField == null && _labelFunction != null)
+            {
+                compareFunc = function (a:Object, b:Object):int
+                { 
+                    return ObjectUtil.stringCompare(_labelFunction(a, column), _labelFunction(b, column));
+                };
+            }
+        }
+        
+        sortField.compareFunction = compareFunc;
+        sortField.descending = column.sortDescending;
+        return sortField;
+    }
+    
+    //----------------------------------
+    //  visible
+    //----------------------------------
+    
+    private var _visible:Boolean = true;
+    
+    [Bindable("visibleChanged")]  
+    
+    /**
+     *  If <code>true</code>, then display this column.  
+     *  If <code>false</code>, no space will be allocated 
+     *  for this column; it will not be included in the layout.
+     * 
+     *  @default true
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get visible():Boolean
+    {
+        return _visible;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set visible(value:Boolean):void
+    {
+        if (_visible == value)
+            return;
+        
+        _visible = value;
+        
+        // dispatch event for grid.
+        if (grid && grid.columns)
+        {
+            var propertyChangeEvent:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "visible", !_visible, _visible);
+            var collectionEvent:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
+            collectionEvent.kind = CollectionEventKind.UPDATE;
+            collectionEvent.items.push(propertyChangeEvent);
+            
+            grid.columns.dispatchEvent(collectionEvent);
+        }
+        
+        dispatchChangeEvent("visibleChanged");
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     *  Common logic for itemToLabel(), itemToDataTip().   Logically this code is
+     *  similar to (not the same as) LabelUtil.itemToLabel().
+     */
+    mx_internal function itemToString(item:Object, labelPath:Array, labelFunction:Function, formatter:IFormatter):String
+    {
+        if (!item)
+            return ERROR_TEXT;
+        
+        if (labelFunction != null)
+            return labelFunction(item, this);
+        
+        var itemString:String = null;
+        try 
+        {
+            var itemData:Object = item;
+            for each (var pathElement:String in labelPath)
+                itemData = itemData[pathElement];
+            
+            if ((itemData != null) && (labelPath.length > 0))
+                itemString = (formatter) ? formatter.format(itemData) : itemData.toString();
+        }
+        catch(ignored:Error)
+        {
+        }        
+        
+        return (itemString != null) ? itemString : ERROR_TEXT;
+    }
+    
+    /**
+     *  Convert the specified data provider item to a column-specific String.   
+     *  This method is used to initialize item renderers' <code>label</code> property.
+     * 
+     *  <p>If <code>labelFunction</code> is null, and <code>dataField</code> 
+     *  is a string that does not contain "." field name separator characters, 
+     *  and formatter is null, then this method is equivalent to:</p>
+     *
+     *  <pre>item[dataField].toString()</pre>   
+     * 
+     *  <p>If the formatter was specified, then this method's value is:</p>
+     * 
+     *  <pre>formatter.format(item[dataField])</pre>
+     *
+     *  <p>If <code>dataField</code> is a "." separated
+     *  path, then this method looks up each successive path element.  
+     *  For example if <code>="foo.bar.baz"</code>, then this method returns 
+     *  a string based on the value of <code>item.foo.bar.baz</code>.   
+     *  If resolving the item's <code>dataField</code>
+     *  causes an error to be thrown, ERROR_TEXT is returned.</p>
+     * 
+     *  <p>If <code>item</code> and <code>labelFunction</code> are not null,
+     *  then this method returns <code>labelFunction(item, this)</code>, 
+     *  where the second argument is this GridColumn.</p> 
+     *
+     *  @param item The value of <code>grid.dataProvider.getItemAt(rowIndex)</code>.
+     * 
+     *  @return A column-specific string for the specified dataProvider item or ERROR_TEXT.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function itemToLabel(item:Object):String
+    {
+        return itemToString(item, dataFieldPath, labelFunction, formatter);
+    }
+
+    /**
+     *  Convert the specified data provider item to a column-specific datatip String. 
+     * 
+     *  <p>This method uses the values <code>dataTipField</code> 
+     *  and <code>dataTipFunction</code>.
+     *  If those properties are null, it uses the corresponding properties
+     *  from the associated grid control.  
+     *  If <code>dataTipField</code> properties is also null in the grid control, 
+     *  then use the <code>dataField</code> property.</p>
+     * 
+     *  <p>If <code>dataTipFunction</code> and <code>dataTipFormatter</code> are
+     *  null, then this method's value is the same as:
+     *  <code>item[dataTipField].toString()</code>.   If <code>dataTipFormatter</code> is 
+     *  specified then this method's value is the same as: 
+     *  <code>dataTipFormatter.format(item[dataTipField])</code>
+     *  If resolving the item's <code>dataField</code>
+     *  causes an error to be thrown, <code>ERROR_TEXT</code> is returned.</p>
+     * 
+     *  <p>If <code>item</code> and <code>dataTipFunction</code> 
+     *  are not null,  then this method returns 
+     *  <code>dataTipFunction(item, this)</code>, where the second argument is
+     *  this GridColumn.</p> 
+     *
+     *  @param item The value of <code>grid.dataProvider.getItemAt(rowIndex)</code>.
+     * 
+     *  @return A column-specific string for the specified data provider item 
+     *  or <code>ERROR_TEXT</code>.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function itemToDataTip(item:Object):String
+    {
+        const tipFunction:Function = (dataTipFunction != null) ? dataTipFunction : grid.dataTipFunction;
+        const tipField:String = (dataTipField) ? dataTipField : grid.dataTipField;
+        const tipPath:Array = (tipField) ? [tipField] : dataFieldPath;
+        
+        return itemToString(item, tipPath, tipFunction, dataTipFormatter);      
+    }
+    
+    /**
+     *  Convert the specified data provider item to a column-specific item renderer factory.
+     *  By default this method calls the <code>itemRendererFunction</code> if it's 
+     *  non-null, otherwise it just returns the value of the column's <code>itemRenderer</code> 
+     *  property.
+     *
+     *  @param item The value of <code>grid.dataProvider.getItemAt(rowIndex)</code>.
+     * 
+     *  @return A column-specific item renderer factory for the specified dataProvider item.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function itemToRenderer(item:Object):IFactory
+    {
+        const itemRendererFunction:Function = itemRendererFunction;
+        return (itemRendererFunction != null) ? itemRendererFunction(item, this) : itemRenderer;
+    }
+    
+    /**
+     *  @private
+     */
+    private function dispatchChangeEvent(eventType:String):void
+    {
+        if (hasEventListener(eventType))
+            dispatchEvent(new Event(eventType));
+    }
+    
+    /**
+     *  @private
+     */
+    private function invalidateGrid():void
+    {
+        if (grid)
+        {
+            grid.invalidateSize();
+            grid.invalidateDisplayList();
+        }
+    }
+}
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridDimensions.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridDimensions.as
new file mode 100644
index 000000000..96e0eb8c6
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridDimensions.as
@@ -0,0 +1,1918 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+// import flash.geom.Rectangle;
+import org.apache.royale.geom.Rectangle;
+
+import mx.collections.IList;
+import mx.events.CollectionEvent;
+import mx.events.CollectionEventKind;
+import mx.events.PropertyChangeEvent;
+
+[ExcludeClass]
+
+/**
+ *  A sparse data structure that represents the widths and heights of a grid.
+ *  
+ *  <p>Provides efficient support for finding the cumulative y distance to the
+ *  start of a particular cell as well as finding the index of a particular
+ *  cell at a certain y value.
+ *  GridDimensions optimizes these operations by bookmarking the most recently
+ *  visited rows.</p>
+ * 
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.0
+ *  @productversion Flex 4.5
+ */
+public class GridDimensions 
+{
+    // include "../../core/Version.as";
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Class methods
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Inserts specified elements starting from startIndex.
+     *  
+     *  <pre>Our implementation of:
+     *      var argArray:Array = [];
+     *      for each (var x:Number in values)
+     *      {
+     *          argArray.push(x);
+     *      }
+     *      argArray.splice(0, 0, startIndex, 0);
+     *      vec.splice.apply(vec, argArray);</pre>
+     * 
+     *  @param vec The vector to insert into.
+     *  @param startIndex The index to insert at.
+     *  @param elements The elements to be inserted.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public static function insertElementsToVector(vec:Vector.<Number>, startIndex:int, elements:Vector.<Number>):void
+    {
+        const oldLength:int = vec.length;
+        const count:int = elements.length;
+        vec.length += count;
+        const vecLength:int = vec.length;
+        var i:int;
+
+        // Shift elements down by count.
+        for (i = oldLength - 1; i >= startIndex; i--)
+            vec[i + count] = vec[i];
+        
+        const endIndex:int = startIndex + elements.length;
+        var j:int = 0;
+        for (i = startIndex; i < endIndex; i++)
+            vec[i] = elements[j++];
+    }
+    
+    /**
+     *  Insert count elements of the specified value starting from
+     *  startIndex.
+     *  
+     *  @param vec The vector to insert into.
+     *  @param startIndex The index to insert at.
+     *  @param count The number of elements to insert
+     *  @param value The value of the inserted elements
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public static function insertValueToVector(vec:Vector.<Number>, startIndex:int, count:int, value:Number):void
+    {
+        const oldLength:int = vec.length;
+        vec.length += count;
+        const vecLength:int = vec.length;
+        
+        // Shift elements down by count.
+        for (var i:int = oldLength - 1; i >= startIndex; i--)
+            vec[i + count] = vec[i];
+        
+        clearVector(vec, value, startIndex, count);
+    }
+    
+    /**
+     *  Sets all of the numbers in a vector to be value unless otherwise
+     *  specified.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public static function clearVector(vec:Vector.<Number>, value:Number, startIndex:int = 0, count:int = -1):void
+    {
+        const endIndex:int = (count == -1) ? vec.length : startIndex + count;
+        
+        for (var i:int = startIndex; i < endIndex; i++)
+            vec[i] = value;
+    }
+    
+    /**
+     *  @private
+     *  Restrict a number to a particular min and max.
+     */
+    private static function bound(a:Number, min:Number, max:Number):Number
+    {
+        if (a < min)
+            a = min;
+        else if (a > max)
+            a = max;
+        
+        return a;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+
+    private var rowList:GridRowList = new GridRowList();
+    private var _columnWidths:Vector.<Number> = new Vector.<Number>();
+
+    // Bookmark recently visited rows by caching the node representing the row
+    // and the y-value corresponding to the start of the node.
+    // startY/recentNode is the bookmark used by getRowIndexAt()
+    private var startY:Number = 0;
+    private var recentNode:GridRowNode = null;
+    // startY2/recentNode2 is bookmark used by getCellY()
+    private var startY2:Number = 0;
+    private var recentNode2:GridRowNode = null;
+    
+    private const typicalCellWidths:Vector.<Number> = new Vector.<Number>();
+    private const typicalCellHeights:Vector.<Number> = new Vector.<Number>();
+    private var maxTypicalCellHeight:Number = NaN;
+    private var useMaxTypicalCellHeight:Boolean = true;
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructor.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function GridDimensions()
+    {
+        super();
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+    
+    //----------------------------------
+    //  rowCount
+    //----------------------------------
+    
+    private var _rowCount:int = 0;
+    
+    /**
+     *  The number of rows in the Grid. If this is decreased, the 
+     *  excess rows will be removed.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get rowCount():int
+    {
+        return _rowCount;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set rowCount(value:int):void
+    {
+        if (value == _rowCount)
+            return;
+        
+        // remove rows greater than value.
+        // This also clears the cached nodes.
+        if (value < _rowCount)
+            removeRowsAt(value, value - _rowCount)
+        
+        _rowCount = value;
+    }
+    
+    //----------------------------------
+    //  columnCount
+    //----------------------------------
+    
+    private var _columnCount:int = 0;
+    
+    /**
+     *  The number of columns in the Grid.
+     *  Setting this property will clear the cache.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get columnCount():int
+    {
+        return _columnCount;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set columnCount(value:int):void
+    {
+        // Don't short-circuit return if the column count didn't change.
+        // There might be a new set of columns which is the same length
+        // as the old set of columns.
+
+        // clear cached information
+        clearHeights();
+        
+        // fix up the number of columns
+        _columnCount = value;
+        _columnWidths.length = value;
+        typicalCellHeights.length = value;
+        typicalCellWidths.length = value;
+        rowList.numColumns = value;
+        
+        // clear the rest of the vectors
+        clearTypicalCellWidthsAndHeights();
+        clearVector(_columnWidths, NaN, 0, _columnCount);
+    }
+
+    //----------------------------------
+    //  rowGap
+    //----------------------------------
+
+    private var _rowGap:Number = 0;
+    
+    /**
+     *  The gap between rows.
+     * 
+     *  @default 0 
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get rowGap():Number
+    {
+        return _rowGap;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set rowGap(value:Number):void
+    {
+        if (value == _rowGap)
+            return;
+        
+        _rowGap = value;
+
+        clearCachedNodes();
+    }
+    
+    //----------------------------------
+    //  columnGap
+    //----------------------------------
+
+    private var _columnGap:Number = 0;
+    
+    /**
+     *  The gap between columns.
+     * 
+     *  @default 0
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5 
+     */
+    public function get columnGap():Number
+    {
+        return _columnGap;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set columnGap(value:Number):void
+    {
+        if (value == _columnGap)
+            return;
+        
+        _columnGap = value;
+
+        clearCachedNodes();
+    }
+    
+    //----------------------------------
+    //  defaultRowHeight
+    //----------------------------------
+
+    private var _defaultRowHeight:Number = NaN;
+    
+    /**
+     *  The default height of a row.
+     *
+     *  <p>If this property is not set explicitly, it will use the maximum
+     *  of the typical cell heights.</p>
+     *
+     *  <p>When variableRowHeight is false, all rows have a height of
+     *  defaultRowHeight.</p>
+     *
+     *  @default NaN
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get defaultRowHeight():Number
+    {
+        return useMaxTypicalCellHeight ? maxTypicalCellHeight : _defaultRowHeight;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set defaultRowHeight(value:Number):void
+    {
+        if (value == _defaultRowHeight)
+            return;
+        
+        _defaultRowHeight = bound(value, _minRowHeight, _maxRowHeight);
+        useMaxTypicalCellHeight = isNaN(_defaultRowHeight);
+        
+        clearCachedNodes();
+    }
+    
+    //----------------------------------
+    //  defaultColumnWidth
+    //----------------------------------
+    
+    private var _defaultColumnWidth:Number = 150;
+    
+    /**
+     *  The default width of a column.
+     *  If this changes, update the ASDoc for GridLayout/getItemRendererAt().
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get defaultColumnWidth():Number
+    {
+        return _defaultColumnWidth;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set defaultColumnWidth(value:Number):void
+    {
+        if (value == _defaultColumnWidth)
+            return;
+        
+        _defaultColumnWidth = value;
+    }    
+    
+    //----------------------------------
+    //  variableRowHeight
+    //----------------------------------
+    
+    private var _variableRowHeight:Boolean = false;  // default value must match Grid property default value
+    
+    /**
+     *  If variableRowHeight is false, calling getRowHeight
+     *  will return the value of defaultRowHeight.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get variableRowHeight():Boolean
+    {
+        return _variableRowHeight;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set variableRowHeight(value:Boolean):void
+    {
+        if (value == _variableRowHeight)
+            return;
+        
+        _variableRowHeight = value;
+    }       
+    
+    //----------------------------------
+    //  minRowHeight
+    //----------------------------------
+    
+    private var _minRowHeight:Number = 0;
+    
+    /**
+     *  The minimum height of each row.
+     * 
+     *  @default 0
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get minRowHeight():Number
+    {
+        return _minRowHeight;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set minRowHeight(value:Number):void
+    {
+        if (value == _minRowHeight)
+            return;
+        
+        _minRowHeight = value;
+        _defaultRowHeight = Math.max(_defaultRowHeight, _minRowHeight);
+    }
+    
+    //----------------------------------
+    //  maxRowHeight
+    //----------------------------------
+    
+    private var _maxRowHeight:Number = 10000;
+    
+    /**
+     *  The maximum height of each row.
+     * 
+     *  @default 10000
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get maxRowHeight():Number
+    {
+        return _maxRowHeight;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set maxRowHeight(value:Number):void
+    {
+        if (value == _maxRowHeight)
+            return;
+        
+        _maxRowHeight = value;
+        _defaultRowHeight = Math.min(_defaultRowHeight, _maxRowHeight);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Clears bookmarked nodes.
+     *  Each bookmarked node is associated with a cumulative y-value representing
+     *  the total height of the grid up to the start of the row.
+     *  These values are cleared as well.
+     */
+    private function clearCachedNodes():void
+    {
+        recentNode = null;
+        startY = 0;
+        recentNode2 = null;
+        startY2 = 0;
+    }
+    
+    /**
+     *  Returns the height of the row at the given index. If variableRowHeight
+     *  is true, then the height in precendence order is: the height set by setRowHeight,
+     *  the natural height of the row (determined by the maximum of its cell heights),
+     *  and defaultRowHeight. If variableRowHeight is false, then the height returned
+     *  is the defaultRowHeight. The returned height is always bounded by the minRowHeight
+     *  and maxRowHeight.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getRowHeight(row:int):Number
+    {
+        // Unless setRowHeight is called, return the max cell height for this row
+        var height:Number = defaultRowHeight;
+        
+        if (variableRowHeight)
+        {
+            var node:GridRowNode = rowList.find(row);
+            if (node)
+            {
+                if (node.fixedHeight >= 0)
+                    height = node.fixedHeight;
+                else if (node.maxCellHeight >= 0)
+                    height = node.maxCellHeight;
+            }
+        }
+        
+        return (!isNaN(height)) ? bound(height, minRowHeight, maxRowHeight) : height;
+    }
+    
+    /**
+     *  Sets the height of a given row. This height takes precedence over
+     *  the natural height of the row (determined by the maximum of its 
+     *  cell heights) and the defaultRowHeight. However, if variableRowHeight
+     *  is true, this method has no effect.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function setRowHeight(row:int, height:Number):void
+    {
+        if (!variableRowHeight)
+            return;
+        
+        var node:GridRowNode = rowList.find(row);
+        
+        if (node)
+        {
+            node.fixedHeight = bound(height, minRowHeight, maxRowHeight);
+        }
+        else
+        {
+            node = rowList.insert(row);
+            
+            if (node)
+                node.fixedHeight = bound(height, minRowHeight, maxRowHeight);
+        }
+        
+        clearCachedNodes();
+    }
+
+    /**
+     *  Returns the width of the column at the given index. Returns
+     *  the width specified by setColumnWidth. If no width has been
+     *  specified, returns the typical width. If no typical width has
+     *  been set, it returns the defaultColumnWidth.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getColumnWidth(col:int):Number
+    {    
+        var w:Number = NaN;
+
+        w = _columnWidths[col];
+        
+        if (isNaN(w))
+            w = typicalCellWidths[col];
+        
+        if (isNaN(w))
+            w = this.defaultColumnWidth;
+        
+        return w;
+    }
+    
+    /**
+     *  Sets the width of a given column.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function setColumnWidth(col:int, width:Number):void
+    {
+        _columnWidths[col] = width;
+    }
+
+    /**
+     *  Returns the height of the specified cell. Returns the height
+     *  specified by setCellHeight. If the height has not been specified,
+     *  returns NaN.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getCellHeight(row:int, col:int):Number
+    {
+        var node:GridRowNode = rowList.find(row);
+        
+        if (node)
+            return node.getCellHeight(col);
+        
+        return NaN;
+    }
+    
+    /**
+     *  Sets the height of the specified cell.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function setCellHeight(row:int, col:int, height:Number):void
+    {
+        if (!variableRowHeight)
+            return;
+        
+        var node:GridRowNode = rowList.find(row);
+        var oldHeight:Number = defaultRowHeight;
+        
+        if (node == null)
+            node = rowList.insert(row);
+        else
+            oldHeight = node.maxCellHeight;
+        
+        if (node && node.setCellHeight(col, height))
+        {
+           if (recentNode && node.rowIndex < recentNode.rowIndex)
+               startY += node.maxCellHeight - oldHeight;
+           
+           if (recentNode2 && node.rowIndex < recentNode2.rowIndex)
+               startY2 += node.maxCellHeight - oldHeight;
+        }
+    }
+    
+    /**
+     *  Returns the layout bounds of the specified cell. The cell height
+     *  and width are determined by its row's height and column's width.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getCellBounds(row:int, col:int):Rectangle
+    {
+        // TODO (klin): provide optional return value (Rectangle) parameter
+        if (row < 0 || row >= rowCount || col < 0 || col >= columnCount)
+            return null;
+        
+        var x:Number = getCellX(row, col);
+        var y:Number = getCellY(row, col);
+        
+        var width:Number = getColumnWidth(col);
+        var height:Number = getRowHeight(row);
+        
+        return new Rectangle(x, y, width, height);
+    }
+    
+    /**
+     *  Returns the X coordinate of the origin of the specified cell.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getCellX(row:int, col:int):Number
+    {   
+        var x:Number = 0;
+        
+        for (var i:int = 0; i < col; i++)
+        {
+            x += getColumnWidth(i) + columnGap;
+        }
+        
+        return x;
+    }
+    
+    /**
+     *  Returns the Y coordinate of the origin of the specified cell.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getCellY(row:int, col:int):Number
+    { 
+        // no cache so we use default heights for each row.
+        if (!variableRowHeight || rowList.length == 0)
+            return row * (defaultRowHeight + rowGap);
+        
+        if (row == 0)
+            return 0;
+        
+        // initialize first node.
+        if (!recentNode2)
+        {
+            recentNode2 = rowList.first;
+            startY2 = recentNode2.rowIndex * (defaultRowHeight + rowGap);
+        }
+        
+        var y:Number;
+        var recentIndex:int = recentNode2.rowIndex;
+
+        if (row == recentIndex)
+            y = startY2;
+        else if (row < recentIndex)
+            y = getPrevYAt(row, recentNode2, startY2);
+        else
+            y = getNextYAt(row, recentNode2, startY2);
+
+        return y;
+    }
+
+    /**
+     *  @private
+     *  Returns the starting y value of the specified row. The row must be before
+     *  startNode.
+     *  
+     *  @param row the target row
+     *  @param startNode the node to search from
+     *  @param startY the cumulative y value from the first row to the beginning
+     *  of startNode's row.
+     * 
+     *  @return the y value of the start of the row.
+     */
+    private function getPrevYAt(row:int, startNode:GridRowNode, startY:Number):Number
+    {
+        var node:GridRowNode = startNode;
+        var nodeY:Number = startY;
+        var prevNode:GridRowNode;
+        var currentY:Number = startY;
+        var indDiff:int;
+        
+        while (node)
+        {
+            if (node.rowIndex == row)
+                break;
+            
+            prevNode = node.prev;
+            
+            if (!prevNode || (row < node.rowIndex && row > prevNode.rowIndex))
+            {
+                // at the beginning or somewhere between nodes
+                // so we've found the target row.
+                indDiff = node.rowIndex - row;
+                currentY -= indDiff * (defaultRowHeight + rowGap);
+                break;
+            }
+            
+            // subtract previous node's height and its gap.
+            indDiff = node.rowIndex - prevNode.rowIndex - 1;
+            currentY = currentY - indDiff * (defaultRowHeight + rowGap) - (getRowHeight(prevNode.rowIndex) + rowGap);
+            nodeY = currentY;
+            node = prevNode;
+        }
+        
+        this.recentNode2 = node;
+        this.startY2 = nodeY;
+        
+        return currentY;
+    }
+    
+    /**
+     *  @private
+     *  Returns the starting y value of the specified row. The row must be after
+     *  startNode.
+     *  
+     *  @param row the target row
+     *  @param startNode the node to search from
+     *  @param startY the cumulative y value from the first row to beginning of
+     *  startNode's row.
+     * 
+     *  @return the y value of the start of the row.
+     */
+    private function getNextYAt(row:int, startNode:GridRowNode, startY:Number):Number
+    {
+        var node:GridRowNode = startNode;
+        var nodeY:Number = startY;
+        var nextNode:GridRowNode;
+        var currentY:Number = startY;
+        var indDiff:int;
+        
+        while (node)
+        {
+            if (node.rowIndex == row)
+                break;
+
+            // add next row's height and rowGap
+            currentY += getRowHeight(node.rowIndex);
+            if (node.rowIndex < _rowCount - 1)
+                currentY += rowGap;
+            
+            nextNode = node.next;
+            
+            if (!nextNode || (row > node.rowIndex && row < nextNode.rowIndex))
+            {
+                // at the beginning or somewhere between nodes
+                // so we've found the target row.
+                indDiff = row - node.rowIndex - 1;
+                currentY += indDiff * (defaultRowHeight + rowGap);
+                break;
+            }
+            
+            // add estimated heights of rows in between measured rows.
+            indDiff = nextNode.rowIndex - node.rowIndex - 1;
+            currentY = currentY + indDiff * (defaultRowHeight + rowGap);
+            nodeY = currentY; 
+            node = nextNode;
+        }
+        
+        this.recentNode2 = node;
+        this.startY2 = nodeY;
+        
+        return currentY;
+    }
+    
+    /**
+     *  Returns the layout bounds of the specified row.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getRowBounds(row:int):Rectangle
+    {
+        // TODO (klin): provide optional return value (Rectangle) parameter    
+        if ((row < 0) || (row >= _rowCount))
+            return null;
+        
+        if (_columnCount == 0 || _rowCount == 0)
+            return new Rectangle(0, 0, 0, 0);
+        
+        const x:Number = getCellX(row, 0);
+        const y:Number = getCellY(row, 0);
+        const rowWidth:Number = getCellX(row, _columnCount - 1) + getColumnWidth(_columnCount - 1) - x;
+        const rowHeight:Number = getRowHeight(row);
+        return new Rectangle(x, y, rowWidth, rowHeight);
+    }
+    
+    /**
+     *  Return the dimensions of a row that's being used to "pad" the grid
+     *  by filling unused space below the last row in a layout where all rows
+     *  are visible.  Pad rows have index >= rowCount, height = defaultRowHeight.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getPadRowBounds(row:int):Rectangle
+    {
+        if (row < 0)
+            return null;
+        
+        if (row < rowCount)
+            return getRowBounds(row);
+        
+        const lastRow:int = rowCount - 1;
+        const lastCol:int = columnCount - 1;
+        
+        const x:Number = (lastRow >= 0) ? getCellX(lastRow, 0) : 0;
+        const lastRowBottom:Number = (lastRow >= 0) ? getCellY(lastRow, 0) + getRowHeight(lastRow) : 0;
+        const padRowCount:int = row - rowCount;
+        const padRowTotalGap:Number = (padRowCount > 0) ? (padRowCount - 1) * rowGap : 0;
+        const y:Number = lastRowBottom + (padRowCount * defaultRowHeight) + padRowTotalGap;
+        
+        var rowWidth:Number = 0;
+        if ((lastCol >= 0) && (lastRow >= 0))
+            rowWidth = getCellX(lastRow, lastCol) + getColumnWidth(lastCol) - x;
+        else if (lastCol >= 0)
+            rowWidth = getCellX(0, lastCol) + getColumnWidth(lastCol) - x;
+        else if (lastRow >= 0)
+            rowWidth = getCellX(lastRow, 0) + getColumnWidth(0) - x;
+        
+        return new Rectangle(x, y, rowWidth, defaultRowHeight);
+        
+    }
+    
+    /**
+     *  Returns the layout bounds of the specified column.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getColumnBounds(col:int):Rectangle
+    {
+        // TODO (klin): provide optional return value (Rectangle) parameter
+        if ((col < 0) || (col >= _columnCount))
+            return null;
+        
+        if (_columnCount == 0)
+            return new Rectangle(0, 0, 0, 0);
+
+        const x:Number = getCellX(0, col);
+        const y:Number = getCellY(0, col);
+        const colWidth:Number = getColumnWidth(col);
+        var colHeight:Number = 0;
+		
+		if (_rowCount > 0)
+			colHeight = getCellY(_rowCount - 1, col) + getRowHeight(_rowCount - 1) - y;
+
+        return new Rectangle(x, y, colWidth, colHeight);
+    }
+    
+    /**
+     *  Returns the index of the row at the specified coordinates. If
+     *  the coordinates lie in a gap area, the index returned is the
+     *  previous row.
+     * 
+     *  @return The index of the row at the coordinates provided. If the
+     *  coordinates are out of bounds, return -1.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getRowIndexAt(x:Number, y:Number):int
+    {
+        if (y < 0)
+            return -1;
+        
+        var index:int;
+        
+        if (!variableRowHeight || rowList.length == 0)
+        {
+            index = y / (defaultRowHeight + rowGap);
+            return index < _rowCount ? index : -1;
+        }
+        
+        if (y == 0)
+            return _rowCount > 0 ? 0 : -1;
+        
+        // initialize first node.
+        if (!recentNode)
+        {
+            recentNode = rowList.first;
+            startY = recentNode.rowIndex * (defaultRowHeight + rowGap);
+        }
+        
+        // if we are already at the right row, then use the index.
+        if (isYInRow(y, startY, recentNode))
+            index = recentNode.rowIndex;
+        else if (y < startY)
+            index = getPrevRowIndexAt(y, recentNode, startY);
+        else
+            index = getNextRowIndexAt(y, recentNode, startY);
+        
+        return index < _rowCount ? index : -1;
+    }
+    
+    /**
+     *  @private
+     *  Checks if a certain y value lies in a row's bounds.
+     */
+    private function isYInRow(y:Number, startY:Number, node:GridRowNode):Boolean
+    {
+        var end:Number = startY + getRowHeight(node.rowIndex);
+        
+        // don't add gap for last row.
+        if (node.rowIndex != rowCount - 1)
+            end += rowGap;
+        
+        // if y is between cumY and cumY + rowHeight - 1 then y is in the row.
+        if (y >= startY && y < end)
+            return true;
+        
+        return false;
+    }
+    
+    /**
+     *  @private
+     *  Returns the index of the row that contains the specified y value.
+     *  The row will be before startNode.
+     *  
+     *  @param y the target y value
+     *  @param startNode the node to search from
+     *  @param startY the cumulative y value from the first row to startNode
+     * 
+     *  @return the index of the row that contains the y value.
+     */
+    private function getPrevRowIndexAt(y:Number, startNode:GridRowNode, startY:Number):int
+    {
+        var node:GridRowNode = startNode;
+        var prevNode:GridRowNode = null;
+        var index:int = node.rowIndex;
+        var currentY:Number = startY;
+        var prevY:Number;
+        var targetY:Number = y;
+
+        while (node)
+        {
+            // check the current node.
+            if (isYInRow(targetY, currentY, node))
+                break;
+            
+            // calculate previous y.
+            prevNode = node.prev;
+            
+            if (!prevNode)
+            {
+                prevY = 0;
+            }
+            else
+            {
+                prevY = currentY;
+                
+                var indDiff:int = node.rowIndex - prevNode.rowIndex;
+                
+                // subtract default row heights if difference is greater than one.
+                if (indDiff > 1)
+                    prevY -= (indDiff - 1) * (defaultRowHeight + rowGap);
+            }
+            
+            // check if target Y is in range.
+            if (targetY < currentY && targetY >= prevY)
+            {
+                index = index - Math.ceil(Number(currentY - targetY)/(defaultRowHeight + rowGap));
+                break;
+            }
+
+            // subtract previous node's height and its gap.
+            currentY = prevY - getRowHeight(prevNode.rowIndex) - rowGap;
+            node = node.prev;
+            index = node.rowIndex;
+        }
+        
+        this.recentNode = node;
+        this.startY = currentY;
+        
+        return index;
+    }
+    
+    /**
+     *  @private
+     *  Returns the index of the row that contains the specified y value.
+     *  The row will be after startNode.
+     *  
+     *  @param y the target y value
+     *  @param startNode the node to search from
+     *  @param startY the cumulative y value from the first row to startNode
+     * 
+     *  @return the index of the row that contains the y value.
+     */
+    private function getNextRowIndexAt(y:Number, startNode:GridRowNode, startY:Number):int
+    {
+        var node:GridRowNode = startNode;
+        var nextNode:GridRowNode = null;
+        var index:int = node.rowIndex;
+        var nodeY:Number = startY;
+        var currentY:Number = startY;
+        var nextY:Number;
+        var targetY:Number = y;
+        
+        while (node)
+        {
+            // check the current node.
+            if (isYInRow(targetY, nodeY, node))
+                break;
+            
+            // currentY increments to end of the current node.
+            currentY += getRowHeight(node.rowIndex);
+            if (node.rowIndex != rowCount - 1)
+                currentY += rowGap;
+            
+            // calculate end of next section.
+            nextNode = node.next;
+            nextY = currentY;
+            
+            var indDiff:int;
+            
+            if (!nextNode)
+            {
+                indDiff = rowCount - 1 - node.rowIndex;
+                // the y at the end doesn't have a rowGap, but includes the final pixel.
+                nextY += indDiff * (defaultRowHeight + rowGap) - rowGap + 1;
+            }
+            else
+            {
+                indDiff = nextNode.rowIndex - node.rowIndex;
+                nextY += (indDiff - 1) * (defaultRowHeight + rowGap);
+            }
+            
+            // check if target Y is within default row heights range.
+            if (targetY >= currentY && targetY < nextY)
+            {
+                index = index + Math.ceil(Number(targetY - currentY)/(defaultRowHeight + rowGap));
+                break;
+            }
+            
+            // if no next node and we didn't find the target, then the row doesn't exist.
+            if (!nextNode)
+            {
+                index = -1;
+                break;
+            }
+            
+            // move y values ahead to next node.
+            nodeY = currentY = nextY;
+            
+            node = node.next;
+            index = node.rowIndex;
+        }
+        
+        this.recentNode = node;
+        this.startY = nodeY;
+        
+        return index;
+    }
+    
+    /**
+     *  Returns the index of the column at the specified coordinates. If
+     *  the coordinates lie in a gap area, the index returned is the
+     *  previous column. Returns -1 if the coordinates are out of bounds.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getColumnIndexAt(x:Number, y:Number):int
+    {
+        var current:Number = x;
+        var i:int;
+
+        if(current < 0)
+            return -1;
+
+        for (i = 0; i < _columnCount; i++)
+        {
+            var columnWidth:Number = _columnWidths[i];
+            
+            // fall back on typical widths if the actual width isn't set.
+            if (isNaN(columnWidth))
+            {
+                columnWidth = typicalCellWidths[i];
+                if (columnWidth == 0) // invisible column
+                    continue;
+            }
+            
+            // fall back on defaultColumnWidth
+            if (isNaN(columnWidth))
+                columnWidth = defaultColumnWidth;
+            
+            current -= columnWidth + columnGap;
+
+            if (current < 0)
+                return i;
+        }
+        
+        return -1;
+    }
+    
+    /**
+     *  Returns the total layout width of the content including gaps.   If 
+	 *  columnCountOverride is specified, then the overall width of as many columns
+	 *  is returned.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getContentWidth(columnCountOverride:int = -1, startColumnIndex:int = 0):Number
+    {
+        const nCols:int = (columnCountOverride == -1) ? columnCount - startColumnIndex : columnCountOverride;
+        var contentWidth:Number = 0;
+        var measuredColCount:int = 0;
+        
+        for (var columnIndex:int = startColumnIndex; (columnIndex < columnCount) && (measuredColCount < nCols); columnIndex++)
+        {
+            if (columnIndex >= _columnWidths.length)
+            {
+                contentWidth += defaultColumnWidth;
+                measuredColCount++;
+                continue;
+            }
+            
+            var width:Number = _columnWidths[columnIndex];
+            
+            // fall back on typical width
+            if (isNaN(width))
+            {
+                width = typicalCellWidths[columnIndex];
+                // column.visible==false, skip this column.
+                if (width == 0)
+                    continue;
+            }
+            
+            // fall back on defaultColumnWidth
+            if (isNaN(width))
+                width = defaultColumnWidth;
+            
+            contentWidth += width;
+            measuredColCount++;
+        }
+        
+        if (measuredColCount > 1)
+            contentWidth += (measuredColCount - 1) * columnGap;
+        
+        return contentWidth;
+    }
+    
+    /**
+     *  Returns the total layout height of the content including gaps.  If 
+	 *  rowCountOverride is specified, then the overall height of as many rows
+	 *  is returned.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getContentHeight(rowCountOverride:int = -1, startRowIndex:int = 0):Number
+    {
+        const nRows:int = (rowCountOverride == -1) ? rowCount - startRowIndex : rowCountOverride;        
+        const maxRow:int = (rowCountOverride == -1) ? rowCount : startRowIndex + rowCountOverride;
+		var contentHeight:Number = 0;
+        
+        if (nRows > 1)
+            contentHeight += (nRows - 1) * rowGap;
+        
+        if (!variableRowHeight || rowList.length == 0)
+            return contentHeight + nRows * defaultRowHeight;
+        
+        var node:GridRowNode = (startRowIndex == 0) ? rowList.first : rowList.findNearestLTE(startRowIndex);
+        var numRows:int = 0;
+        
+        while (node && node.rowIndex < maxRow)  
+        {
+            if (node.rowIndex < startRowIndex)
+            {
+                node = node.next;
+                continue;
+            }
+            contentHeight += getRowHeight(node.rowIndex);
+            numRows++;
+            node = node.next;
+        }
+    
+        contentHeight += (nRows - numRows) * defaultRowHeight;
+        
+        return contentHeight;
+    }
+    
+    /**
+     *  Returns the sum of the typical cell widths including gaps.  If 
+	 *  columnCountOverride is specified, then the overall typicalCellWidth 
+     *  of as many columns is returned. 
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getTypicalContentWidth(columnCountOverride:int = -1, startColumnIndex:int = 0):Number
+    {
+        const nCols:int = (columnCountOverride == -1) ? columnCount - startColumnIndex : columnCountOverride;
+        var contentWidth:Number = 0;
+        var measuredColCount:int = 0;
+        
+        for (var columnIndex:int = startColumnIndex; (columnIndex < columnCount) && (measuredColCount < nCols); columnIndex++)
+        {
+            // column.visible==false columns will have a typicalCellWidth of 0, so skip them.
+            var width:Number = columnIndex < columnCount ? typicalCellWidths[columnIndex] : NaN;
+            if (width == 0)
+                continue;
+            
+            if (isNaN(width))
+                width = defaultColumnWidth;
+            
+            contentWidth += width;
+            measuredColCount++;
+        }
+        
+        if (measuredColCount > 1)
+            contentWidth += (measuredColCount - 1) * columnGap;
+
+        return contentWidth;
+    }
+    
+    /**
+     *  Returns the content height which is maximum cell height of the
+     *  typical item times the total number of rows including gaps. 
+     *  If rowCountOverride is specified, then we only include that many rows.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getTypicalContentHeight(rowCountOverride:int = -1, startRowIndex:int = 0):Number
+    {
+        const nRows:int = (rowCountOverride == -1) ? rowCount - startRowIndex : rowCountOverride;          
+        var contentHeight:Number = 0;
+        
+        if (nRows > 1)
+            contentHeight += (nRows - 1) * rowGap;
+        
+        if (!isNaN(defaultRowHeight))
+            return contentHeight + nRows * defaultRowHeight;
+        
+        return 0;
+    }
+        
+    /**
+     *  Return the preferred bounds width of the grid's typicalItem when rendered with the item renderer 
+     *  for the specified column.  If no value has yet been specified, return NaN.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getTypicalCellWidth(columnIndex:int):Number
+    {
+        return typicalCellWidths[columnIndex];
+    }
+    
+    /**
+     *  Sets the preferred bounds width of the grid's typicalItem for the specified column.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function setTypicalCellWidth(columnIndex:int, value:Number):void
+    {
+        typicalCellWidths[columnIndex] = value;
+    }
+    
+    /**
+     *  Return the preferred bounds height of the grid's typicalItem when rendered with the item renderer 
+     *  for the specified column.  If no value has yet been specified, return NaN.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */    
+    public function getTypicalCellHeight(columnIndex:int):Number
+    {
+        return typicalCellHeights[columnIndex];
+    }
+    
+    /**
+     *  Sets the preferred bounds height of the grid's typicalItem for the specified column.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */    
+    public function setTypicalCellHeight(columnIndex:int, value:Number):void
+    {
+        typicalCellHeights[columnIndex] = value;
+        
+        var max:Number = 0;
+        const typicalCellHeightsLength:int = typicalCellHeights.length;
+        for (var i:int = 0; i < typicalCellHeightsLength; i++)
+        {
+            if (!isNaN(typicalCellHeights[i])) 
+                max = Math.max(max, typicalCellHeights[i]);
+        }
+        this.maxTypicalCellHeight = max;
+    }
+    
+    /**
+     *  Clears the typical cell for every column and row.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function clearTypicalCellWidthsAndHeights():void
+    {
+        clearVector(typicalCellWidths, NaN);
+        clearVector(typicalCellHeights, NaN);
+        maxTypicalCellHeight = NaN;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Methods for handling dataProvider and column list changes
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Inserts count number of rows starting from startRow. This shifts
+     *  any rows after startRow down by count and will increment 
+     *  rowCount.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function insertRows(startRow:int, count:int):void
+    {
+        insertRowsAt(startRow, count);
+    }
+    
+    /**
+     *  Inserts count number of columns starting from startColumn. This
+     *  shifts any columns after startColumn down by count and will
+     *  increment columnCount. 
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function insertColumns(startColumn:int, count:int):void
+    {
+        const oldColumnCount:int = _columnCount;
+        const newColumnCount:int = _columnCount + count;
+        
+        if (startColumn < 0 || startColumn > oldColumnCount)
+            return;
+        
+        // change column count of all nodes in GridRowList.
+        rowList.insertColumns(startColumn, count);
+        
+        // add to columnCount
+        _columnCount = newColumnCount;
+        
+        // insert new values into the arrays.
+        insertValueToVector(_columnWidths, startColumn, count, NaN);
+        insertValueToVector(typicalCellWidths, startColumn, count, NaN);
+        insertValueToVector(typicalCellHeights, startColumn, count, NaN);
+    }
+    
+    /**
+     *  Removes count number of rows starting from startRow. This
+     *  shifts any rows after startRow up by count and will
+     *  decrement rowCount.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function removeRows(startRow:int, count:int):void
+    {
+        removeRowsAt(startRow, count);
+    }
+    
+    /**
+     *  Removes count number of columns starting from startColumn. This
+     *  shifts any columns after startColumn up by count and will
+     *  decrement columnCount.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function removeColumns(startColumn:int, count:int):void
+    {
+        const oldColumnCount:int = _columnCount;
+        const newColumnCount:int = _columnCount - count;
+        
+        if (startColumn < 0 || startColumn >= oldColumnCount)
+            return;
+        
+        // if we remove all the columns, clear everything.
+        if (newColumnCount <= 0)
+        {
+            columnCount = 0;
+            return;
+        }
+        
+        // Otherwise, lets remove the specified columns.
+        // change column count of all nodes in GridRowList.
+        rowList.removeColumns(startColumn, count)
+        
+        // lower columnCount without clearing anything else.
+        _columnCount = newColumnCount;
+        
+        // remove values from the needed vectors
+        _columnWidths.splice(startColumn, count);
+        typicalCellWidths.splice(startColumn, count);
+        typicalCellHeights.splice(startColumn, count);
+        
+        // bookmarks are invalid because row heights may have changed.
+        clearCachedNodes();
+    }
+    
+    /**
+     *  Removes any nodes that occupy the indices between startRow
+     *  and startRow + count.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function clearRows(startRow:int, count:int):void
+    {
+        if (startRow < 0 || count <= 0)
+            return;
+        
+        var node:GridRowNode = rowList.findNearestLTE(startRow);
+        var endRow:int = startRow + count;
+        var oldNode:GridRowNode;
+        
+        if (node && node.rowIndex < startRow)
+            node = node.next;
+        
+        while (node && node.rowIndex < endRow)
+        {
+            oldNode = node;
+            node = node.next;
+            rowList.removeNode(oldNode);
+        }
+        
+        // bookmarks are invalid because row heights may have changed.
+        clearCachedNodes();
+    }
+    
+    /**
+     *  Clears any columns that occupy the indices between startColumn
+     *  and startColumn + count.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function clearColumns(startColumn:int, count:int):void
+    {
+        if (startColumn < 0 || startColumn >= _columnCount)
+            return;
+        
+        rowList.clearColumns(startColumn, count);
+        
+        clearVector(typicalCellWidths, NaN, startColumn, count);
+        clearVector(typicalCellHeights, NaN, startColumn, count);
+        clearVector(_columnWidths, NaN, startColumn, count);
+        
+        // bookmarks are invalid because row heights may have changed.
+        clearCachedNodes(); 
+    }
+        
+    /**
+     *  Moves count number of rows from the fromRow index to the toRow
+     *  index. This operation will not affect rowCount.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function moveRows(fromRow:int, toRow:int, count:int):void
+    {
+        var rows:Vector.<GridRowNode> = removeRowsAt(fromRow, count);
+        
+        // Set the row indices of the nodes that are moving.
+        var diff:int = toRow - fromRow;
+        for each (var node:GridRowNode in rows)
+        {
+            node.rowIndex = node.rowIndex + diff;
+        }
+        
+        insertRowsAt(toRow, count, rows);
+    }
+    
+    /**
+     *  Moves count number of columns from the fromCol index to the toCol
+     *  index. This operation will not affect colCount.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function moveColumns(fromCol:int, toCol:int, count:int):void
+    {
+        if (fromCol < 0 || fromCol >= _columnCount || toCol < 0 || toCol > _columnCount)
+            return;
+        
+        rowList.moveColumns(fromCol, toCol, count);
+        
+        insertElementsToVector(_columnWidths, toCol, _columnWidths.splice(fromCol, count));
+        insertElementsToVector(typicalCellWidths, toCol, typicalCellWidths.splice(fromCol, count));
+        insertElementsToVector(typicalCellHeights, toCol, typicalCellHeights.splice(fromCol, count));
+    }
+    
+    /**
+     *  Clears all cached heights.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function clearHeights():void
+    {
+        rowList.removeAll();
+        clearCachedNodes();
+    }
+    
+    /**
+     *  @private
+     *  Inserts count number of rows starting from startRow. This will increment 
+     *  rowCount. If the nodes parameter is set, the nodes will be inserted
+     *  to the rowList.
+     */
+    private function insertRowsAt(startRow:int, count:int, nodes:Vector.<GridRowNode> = null):void
+    {
+        // TODO (klin): Push this to GridRowList.
+        
+        if (startRow < 0 || count <= 0)
+            return;
+        
+        var startNode:GridRowNode = rowList.findNearestLTE(startRow);
+        var node:GridRowNode;
+        
+        if (startNode && startNode.rowIndex < startRow)
+            startNode = startNode.next;
+        
+        // first we insert the nodes before this node if it exists,
+        // if not, we just push it at the end.
+        if (nodes)
+        {
+            if (startNode)
+            {
+                for each (node in nodes)
+                    rowList.insertBefore(startNode, node);
+            }
+            else
+            {
+                for each (node in nodes)
+                    rowList.push(node);
+            }
+        }
+        
+        // increment the index of nodes after the last node.
+        node = startNode;
+        while (node)
+        {
+            node.rowIndex += count;
+            node = node.next;
+        }
+        
+        this.rowCount += count;
+        
+        // bookmarks are invalid because row heights may have changed.
+        clearCachedNodes();
+    }
+    
+    /**
+     *  @private
+     *  Removes count number of rows starting from startRow. This will
+     *  decrement rowCount. Returns any removed nodes.
+     */
+    private function removeRowsAt(startRow:int, count:int):Vector.<GridRowNode>
+    {
+        var vec:Vector.<GridRowNode> = new Vector.<GridRowNode>();
+        if (startRow < 0 || count <= 0)
+            return vec;
+        
+        var node:GridRowNode = rowList.findNearestLTE(startRow);
+        var endRow:int = startRow + count;
+        var oldNode:GridRowNode;
+        
+        if (node && node.rowIndex < startRow)
+            node = node.next;
+        
+        while (node && node.rowIndex < endRow)
+        {
+            oldNode = node;
+            vec.push(oldNode);
+            node = node.next;
+            rowList.removeNode(oldNode);
+        }
+        
+        while (node)
+        {
+            node.rowIndex -= count;
+            node = node.next;
+        }
+        
+        _rowCount -= count;
+        
+        // bookmarks are invalid because row heights may have changed.
+        clearCachedNodes();
+        return vec;
+    }
+    
+    /**
+     *  Handles changes in the dataProvider.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function dataProviderCollectionChanged(event:CollectionEvent):void 
+    {
+        switch (event.kind)
+        {
+            case CollectionEventKind.ADD: 
+            {
+                insertRows(event.location, event.items.length);
+                break;
+            }
+                
+            case CollectionEventKind.REMOVE:
+            {
+                removeRows(event.location, event.items.length);
+                break;
+            }
+                
+            case CollectionEventKind.MOVE:
+            {
+                moveRows(event.oldLocation, event.location, event.items.length);
+                break;
+            }
+                
+            case CollectionEventKind.REFRESH:
+            {
+                clearHeights();
+                break;
+            }
+                
+            case CollectionEventKind.RESET:
+            {
+                clearHeights();
+                clearTypicalCellWidthsAndHeights();
+                break;
+            }
+                
+            case CollectionEventKind.UPDATE:
+            {
+                // handled by GridLayout
+                break;
+            }
+                
+            case CollectionEventKind.REPLACE:
+            {
+                clearRows(event.location, event.items.length);
+                break;
+            }   
+        }
+    }
+    
+    /**
+     *  Handles changes in columns.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function columnsCollectionChanged(event:CollectionEvent):void
+    {
+        switch (event.kind)
+        {
+            case CollectionEventKind.ADD: 
+            {
+                insertColumns(event.location, event.items.length);
+                break;
+            }
+            
+            case CollectionEventKind.REMOVE:
+            {
+                removeColumns(event.location, event.items.length);
+                break;
+            }
+            
+            case CollectionEventKind.MOVE:
+            {
+                moveColumns(event.oldLocation, event.location, event.items.length);
+                break;
+            }
+                    
+            case CollectionEventKind.REFRESH:
+            case CollectionEventKind.RESET:
+            {
+                columnCount = IList(event.target).length;
+                break;
+            }
+                
+            case CollectionEventKind.UPDATE:
+            {
+                // column may have changed visiblity                
+                var pcEvent:PropertyChangeEvent;
+                
+                const itemsLength:int = event.items ? event.items.length : 0;                
+                for (var i:int = 0; i < itemsLength; i++)
+                {
+                    pcEvent = event.items[i] as PropertyChangeEvent;
+                    if (pcEvent && pcEvent.property == "visible")
+                        columns_visibleChangedHandler(pcEvent);
+                }
+                break;
+            }
+            
+            case CollectionEventKind.REPLACE:
+            {
+                clearColumns(event.location, event.items.length);
+                break;
+            }
+        }
+    }
+    
+    /**
+     *  @private
+     *  Handle CollectionEventKind.UPDATE for a column whose 'visibility' 
+     *  property changed.
+     */
+    private function columns_visibleChangedHandler(pcEvent:PropertyChangeEvent):void
+    {
+		/*
+        const column:GridColumn = pcEvent.source as GridColumn;
+        const columnIndex:int = column.columnIndex;
+        if (!column || columnIndex < 0 || columnIndex >= _columnCount)
+            return;
+        
+        clearColumns(columnIndex, 1);
+        
+        // column.visible==true columns need to have their typical sizes and 
+        // actual column width updated, while column.visible==false column
+        // have their typical sizes updated to 0 and actual column width
+        // set to NaN.
+        if (column.visible)
+        {
+            setTypicalCellWidth(columnIndex, NaN);
+            setTypicalCellHeight(columnIndex, NaN);
+            if (!isNaN(column.width))
+                setColumnWidth(columnIndex, column.width);
+        }
+        else
+        {
+            setTypicalCellWidth(columnIndex, 0);
+            setTypicalCellHeight(columnIndex, 0);
+            setColumnWidth(columnIndex, NaN);
+        }
+		*/
+    }
+    
+    /**
+     *  @private
+     *  For debugging purposes.
+     */
+    public function toString():String
+    {
+        return rowList.toString();
+    }
+}
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridDoubleClickMode.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridDoubleClickMode.as
new file mode 100644
index 000000000..f978a6fc8
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridDoubleClickMode.as
@@ -0,0 +1,101 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+
+    /**
+    *  The GridDoubleClickMode class defines the valid constant values for the 
+    *  <code>doubleClickMode</code> property of the Spark DataGrid and Grid controls.
+    *  
+    *  <p>Use the constants in ActionsScript, as the following example shows: </p>
+    *  <pre>
+    *    myDG.doubleClickMode = GridDoubleClickMode.ROW;
+    *    myDG.doubleClickEnabled = true;
+    *  </pre>
+    *
+    *  <p>In MXML, use the String value of the constants, 
+    *  as the following example shows:</p>
+    *  <pre>
+    *    &lt;s:DataGrid id="myGrid" width="350" height="150"
+    *        doubleClickMode="row" doubleClickEnabled="true"&gt; 
+    *        ...
+    *    &lt;/s:DataGrid&gt; 
+    *  </pre>
+    * 
+    *  @see spark.components.DataGrid#doubleClickMode
+    *  @see spark.components.Grid#doubleClickMode
+    *  
+    *  @langversion 3.0
+    *  @playerversion Flash 11.1
+    *  @playerversion AIR 3.4
+    *  @productversion Flex 4.10
+    */
+    public final class GridDoubleClickMode
+    {
+        /**
+        *  Constructor.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public function GridDoubleClickMode()
+        {
+        }
+
+        //----------------------------------------
+        //  Class constants
+        //----------------------------------------
+
+        /**
+        *  Specifies that the doubleClick event should be based on a cell.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const CELL:String = "cell";
+
+
+        /**
+        *  Specifies that the doubleClick event should be based on the entire grid.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const GRID:String = "grid";
+
+
+        /**
+        *  Specifies that the doubleClick event should be based on a row.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const ROW:String = "row";
+
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridLayout.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridLayout.as
new file mode 100644
index 000000000..1ca3a4eae
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridLayout.as
@@ -0,0 +1,471 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+/*
+import flash.events.Event;
+import flash.geom.Rectangle;
+*/
+	
+import org.apache.royale.events.Event;
+import org.apache.royale.geom.Rectangle;
+
+import mx.collections.IList;
+import mx.core.IVisualElement;
+import mx.core.mx_internal;
+
+import spark.collections.SubListView;
+import spark.components.Grid;
+import spark.components.Group;
+import spark.layouts.supportClasses.LayoutBase;
+
+use namespace mx_internal;
+
+//[ExcludeClass]  TBD
+
+/**
+ *  @private
+ *  The internal layout class used by the Grid class.   Responsible for laying out
+ *  the target Grid's 1-4 GridViews: centerGridView, leftGridView, topGridView, topLeftGridView.
+ *  The GridViews are created/removed as needed by the Grid.  The layout arranges the GridViews
+ *  within the available space.  There are no gaps between the GridViews, and no space between
+ *  the GridViews and the edges (no leftPadding, rightPadding, etc..).
+ * 
+ *  This class is private to the DataGrid implementation.  It's only used by the 
+ *  DataGrid's Grid skin part (see Grid/configureGridViews()).
+ */
+public class GridLayout extends LayoutBase
+{
+    public function GridLayout()
+    {
+        super();
+    }
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Properties
+	//
+	//--------------------------------------------------------------------------
+	
+	/**
+	 *  @private
+	 */
+	private function dispatchChangeEvent(type:String):void
+	{
+		if (hasEventListener(type))
+			dispatchEvent(new Event(type));
+	}
+	
+	//----------------------------------
+	//  centerGridView
+	//----------------------------------
+	
+	private var _centerGridView:GridView = null; 
+	
+	[Bindable("centerGridViewChanged")]
+	
+	/**
+	 *  Displays unlocked rows and columns.   This GridView is created unconditionally.
+	 * 
+	 *  <p>The Grid responds to vertical and horizontal scroll position changes by scrolling the 
+	 *  centerGridView</p>
+	 * 
+	 *  @default null
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 5.0
+	 */
+	public function get centerGridView():GridView
+	{
+		return _centerGridView;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public function set centerGridView(value:GridView):void
+	{
+		if (_centerGridView == value)
+			return;
+		
+        _centerGridView = value;
+		dispatchChangeEvent("centerGridViewChanged");
+	}
+    
+    //----------------------------------
+    //  grid (private, read-only)
+    //----------------------------------  
+    
+    private function get grid():Grid
+    {
+        return target as Grid;
+    }
+	
+	//----------------------------------
+	//  leftGridView
+	//----------------------------------
+	
+	private var _leftGridView:GridView = null; 
+	
+	[Bindable("leftGridViewChanged")]
+	
+	/**
+	 *  Displays the unlocked rows subset of the locked columns.  This GridView is created when 
+	 *  lockedColumnCount is greater than 0, it's removed if lockedRowCount is reset to zero.
+	 * 
+	 *  <p>If the Grid is scrolled verticallyi, i.e. if its verticalScrollPosition is changed, 
+	 *  then the leftGridView and centerGridView are also scrolled vertically.  The leftGridView
+	 *  does not scroll horizontally.</p> 
+	 * 
+	 *  @default null
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 5.0
+	 */
+	public function get leftGridView():GridView
+	{
+		return _leftGridView;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public function set leftGridView(value:GridView):void
+	{
+		if (_leftGridView == value)
+			return;
+		
+        _leftGridView = value;
+		dispatchChangeEvent("leftGridViewChanged");
+	}
+	
+	//----------------------------------
+	//  lockedColumnsSeparatorElement
+	//----------------------------------
+	
+	private var _lockedColumnsSeparatorElement:IVisualElement = null; 
+	
+	[Bindable("lockedColumnsSeparatorElementChanged")]
+	
+	/**
+	 *  If lockedColumnCount is greater than zero, this element is displayed in between the locked
+	 *  and unlocked columns.  It's created (and removed) as needed with the lockedColumnssSeparator IFactory.
+	 * 
+	 *  @default null
+	 * 
+	 *  @see spark.components.GridLayout#lockedColumnsSeparator 
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 5.0
+	 */
+	public function get lockedColumnsSeparatorElement():IVisualElement
+	{
+		return _lockedColumnsSeparatorElement;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public function set lockedColumnsSeparatorElement(value:IVisualElement):void
+	{
+		if (_lockedColumnsSeparatorElement == value)
+			return;
+		
+		_lockedColumnsSeparatorElement = value;
+		dispatchChangeEvent("lockedColumnsSeparatorElementChanged");
+	}
+	
+	
+	//----------------------------------
+	//  lockedRowsSeparatorElement
+	//----------------------------------
+	
+	private var _lockedRowsSeparatorElement:IVisualElement = null; 
+	
+	[Bindable("lockedRowsSeparatorElementChanged")]
+	
+	/**
+	 *  If lockedRowCount is greater than zero, this element is displayed in between the locked
+	 *  and unlocked rows.  It's created (and removed) as needed with the lockedRowsSeparator IFactory.
+	 * 
+	 *  @default null
+	 * 
+	 *  @see spark.components.Grid#lockedRowsSeparator
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 5.0
+	 */
+	public function get lockedRowsSeparatorElement():IVisualElement
+	{
+		return _lockedRowsSeparatorElement;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public function set lockedRowsSeparatorElement(value:IVisualElement):void
+	{
+		if (_lockedRowsSeparatorElement == value)
+			return;
+		
+		_lockedRowsSeparatorElement = value;
+		dispatchChangeEvent("lockedRowsSeparatorElementChanged");
+	}	
+	
+	//----------------------------------
+	//  topGridView
+	//----------------------------------
+	
+	private var _topGridView:GridView = null; 
+	
+	[Bindable("topGridViewChanged")]
+	
+	/**
+	 *  Displays the unlocked columns subset of the locked rows.  This GridView is created when 
+	 *  lockedRowCount is greater than 0, it's removed if lockedRowCount is reset to zero.
+	 * 
+	 *  <p>If the Grid is scrolled horizontally, i.e. if its horizontalScrollPosition is changed, 
+	 *  then the topGridView and centerGridView are also scrolled horizontally.   The topGridView
+	 *  does not scroll vertically.</p>
+	 * 	
+	 *  @default null
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 5.0
+	 */
+	public function get topGridView():GridView
+	{
+		return _topGridView;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public function set topGridView(value:GridView):void
+	{
+		if (_topGridView == value)
+			return;
+		
+        _topGridView = value;
+		dispatchChangeEvent("topGridViewChanged");		
+	}
+	
+	
+	//----------------------------------
+	//  topLeftGridView
+	//----------------------------------
+	
+	private var _topLeftGridView:GridView = null; 
+	
+	[Bindable("topLeftGridViewChanged")]
+	
+	/**
+	 *  This GridView is only created when both lockedRowCount and lockedColumnCount are greater
+	 *  than zero.  It displays as many rows and columns and does not scroll.
+	 * 
+	 *  @default null
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5
+	 *  @productversion Flex 5.0
+	 */
+	public function get topLeftGridView():GridView
+	{
+		return _topLeftGridView;
+	}
+	
+	/**
+	 *  @private
+	 */
+	public function set topLeftGridView(value:GridView):void
+	{
+		if (_topLeftGridView == value)
+			return;
+		
+		_topLeftGridView = value;
+		dispatchChangeEvent("topLeftGridViewChanged");			
+	}	
+
+	//--------------------------------------------------------------------------
+	//
+	//  Methods
+	//
+	//--------------------------------------------------------------------------
+    
+	/**
+	 *  @private
+	 */
+    override public function measure():void
+    {
+        const grid:Grid = target as Grid;
+        if (!grid)
+            return;
+        
+        const gridDimensions:GridDimensions = grid.gridDimensions;
+        
+        var measuredRowCount:int = grid.requestedRowCount;
+        if (measuredRowCount == -1)
+        {
+            const rowCount:int = gridDimensions.rowCount;
+            if (grid.requestedMaxRowCount != -1)
+                measuredRowCount = Math.min(grid.requestedMaxRowCount, rowCount);
+            if (grid.requestedMinRowCount != -1)
+                measuredRowCount = Math.max(grid.requestedMinRowCount, measuredRowCount);                
+        }
+        
+        var measuredWidth:Number = gridDimensions.getTypicalContentWidth(grid.requestedColumnCount);
+        var measuredHeight:Number = gridDimensions.getTypicalContentHeight(measuredRowCount);
+        var measuredMinWidth:Number = gridDimensions.getTypicalContentWidth(grid.requestedMinColumnCount);
+        var measuredMinHeight:Number = gridDimensions.getTypicalContentHeight(grid.requestedMinRowCount);
+        
+        if (grid.lockedRowCount > 0)
+        {
+            if (lockedRowsSeparatorElement && lockedRowsSeparatorElement.includeInLayout)
+            {
+                measuredHeight += lockedRowsSeparatorElement.getPreferredBoundsHeight();
+                measuredMinHeight += lockedRowsSeparatorElement.getMinBoundsHeight();
+                measuredMinWidth = Math.max(measuredMinWidth, lockedRowsSeparatorElement.getMinBoundsWidth());                
+            }
+        }
+        
+        if (grid.lockedColumnCount > 0)
+        {
+            if (lockedColumnsSeparatorElement && lockedColumnsSeparatorElement.includeInLayout)
+            {
+                measuredWidth += lockedColumnsSeparatorElement.getPreferredBoundsWidth();
+                measuredMinWidth += lockedColumnsSeparatorElement.getMinBoundsWidth();
+                measuredMinHeight = Math.max(measuredMinHeight, lockedColumnsSeparatorElement.getMinBoundsHeight());
+            }
+        }
+        
+        // Use Math.ceil() to make sure that if the content partially occupies
+        // the last pixel, we'll count it as if the whole pixel is occupied.
+
+		target.measuredWidth = Math.ceil(measuredWidth);    
+        target.measuredHeight = Math.ceil(measuredHeight);
+        target.measuredMinWidth = Math.ceil(measuredMinWidth);    
+        target.measuredMinHeight = Math.ceil(measuredMinHeight);
+		
+		//trace("gridLayout measure", target.measuredWidth, target.measuredHeight);
+    }
+	
+    /**
+	 *  @private
+	 */
+    override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+    {
+        const grid:Grid = target as Grid;
+        if (!grid || !centerGridView)
+            return;
+  
+		//trace("gridLayout updateDisplayList", unscaledWidth, unscaledHeight);
+
+        const lockedRowCount:int = grid.lockedRowCount;
+        const lockedColumnCount:int = grid.lockedColumnCount;
+        const lockedRowsExist:Boolean = lockedRowCount > 0;
+        const lockedColumnsExist:Boolean = lockedColumnCount > 0;
+        
+        // Initialize the size of topLeft,top,leftGridView
+        
+        if (lockedRowsExist)
+        {
+			const lastLockedRowIndex:int = lockedRowCount - 1;
+			const lastRowBounds:Rectangle = grid.getRowBounds(lastLockedRowIndex);
+			const lockedRowsHeight:Number = (lastRowBounds) ? Math.min(unscaledHeight, lastRowBounds.bottom) : NaN;			
+            topGridView.setLayoutBoundsSize(unscaledWidth, lockedRowsHeight);
+			
+            if (lockedRowsSeparatorElement)
+                lockedRowsSeparatorElement.setLayoutBoundsSize(unscaledWidth, NaN);
+        }
+        
+        if (lockedColumnsExist)
+        {
+			const lastLockedColumnIndex:int = lockedColumnCount - 1;
+			const lastColumnBounds:Rectangle = grid.getColumnBounds(lastLockedColumnIndex);
+			const lockedColumnsWidth:Number = (lastColumnBounds) ? Math.min(unscaledWidth, lastColumnBounds.right) : NaN;
+            leftGridView.setLayoutBoundsSize(lockedColumnsWidth, unscaledHeight);
+			
+            if (lockedColumnsSeparatorElement)
+                lockedColumnsSeparatorElement.setLayoutBoundsSize(NaN, unscaledHeight);
+        }
+        
+        if (lockedRowsExist && lockedColumnsExist)
+            topLeftGridView.setLayoutBoundsSize(leftGridView.getLayoutBoundsWidth(), topGridView.getLayoutBoundsHeight());
+        
+        // Position topLeft, compute centerX,Y
+        
+        const separatorX:Number = (lockedColumnsExist) ? leftGridView.getLayoutBoundsWidth() : 0;
+        const separatorY:Number = (lockedRowsExist) ? topGridView.getLayoutBoundsHeight() : 0;
+        
+        var centerX:Number = separatorX;
+        var centerY:Number = separatorY;
+        
+        if (lockedRowsExist && lockedColumnsExist)
+            topLeftGridView.setLayoutBoundsPosition(0, 0);
+        
+        if (lockedRowsExist && lockedRowsSeparatorElement)
+        {
+            lockedRowsSeparatorElement.setLayoutBoundsPosition(0, separatorY);
+            centerY += lockedRowsSeparatorElement.getLayoutBoundsHeight();
+        }
+            
+        if (lockedColumnsExist && lockedColumnsSeparatorElement)
+        {
+            lockedColumnsSeparatorElement.setLayoutBoundsPosition(separatorX, 0);
+            centerX += lockedColumnsSeparatorElement.getLayoutBoundsWidth();
+        }
+		
+        // Set topLeft bounds and fix up top.width and left.height when both lockedRow,ColumnCount > 0
+        
+        if (lockedColumnsExist && lockedRowsExist)
+        {
+            topGridView.setLayoutBoundsSize(unscaledWidth - centerX, lockedRowsHeight);
+            leftGridView.setLayoutBoundsSize(lockedColumnsWidth, unscaledHeight - centerY);
+			
+			topLeftGridView.setLayoutBoundsSize(separatorX, separatorY);
+			topLeftGridView.setLayoutBoundsPosition(0,0);
+        }
+        
+        // Position leftGridView, topGridView, size and position centerGridView.
+		
+		if (lockedRowsExist)
+			topGridView.setLayoutBoundsPosition(centerX, 0);
+		
+		if (lockedColumnsExist)
+			leftGridView.setLayoutBoundsPosition(0, centerY);
+		
+        centerGridView.setLayoutBoundsSize(unscaledWidth - centerX, unscaledHeight - centerY);
+        centerGridView.setLayoutBoundsPosition(centerX, centerY);
+        
+        // Note: Grid overrides its contentWidth,Height properties, no need to set them here
+    }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridRowList.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridRowList.as
new file mode 100644
index 000000000..9963c0606
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridRowList.as
@@ -0,0 +1,705 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+
+import mx.collections.ArrayCollection;
+
+[ExcludeClass]
+
+/**
+ *  Open LinkedList implementation for representing row heights in a Grid
+ *  where each GridRowNode represents a row in the Grid.
+ * 
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.0
+ *  @productversion Flex 4.5
+ */
+public class GridRowList
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+    
+    private var _head:GridRowNode;
+    private var _tail:GridRowNode;
+    private var _length:Number = 0;
+    
+    private var recentNode:GridRowNode;
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructor. 
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function GridRowList():void
+    {
+        super();
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+    
+    //----------------------------------
+    //  first
+    //----------------------------------
+    
+    /**
+     *  First node in list.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get first():GridRowNode
+    {
+        return _head;
+    }
+    
+    //----------------------------------
+    //  last
+    //----------------------------------
+    
+    /**
+     *  Last node in list.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get last():GridRowNode
+    {
+        return _tail;
+    }
+    
+    //----------------------------------
+    //  tail
+    //----------------------------------
+    
+    /**
+     *  Node representing tail of the list.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get tail():GridRowNode
+    {
+        return _tail;
+    }
+    
+    //----------------------------------
+    //  head
+    //----------------------------------
+    
+    /**
+     *  Node representing head of the list.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get head():GridRowNode
+    {
+        return _head;
+    }
+    
+    //----------------------------------
+    //  length
+    //----------------------------------
+    
+    /**
+     *  Returns length of list.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get length():Number
+    {
+        return _length;
+    }
+    
+    //----------------------------------
+    //  numColumns
+    //----------------------------------
+    
+    private var _numColumns:uint = 0;
+
+    /**
+     *  Returns number of columns per row.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get numColumns():uint
+    {
+        return _numColumns;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set numColumns(value:uint):void
+    {
+        if (_numColumns == value)
+            return;
+        
+        _numColumns = value;
+        
+        var cur:GridRowNode = _head;
+        while (cur)
+        {
+            cur.numColumns = value;
+            cur = cur.next;
+        }
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Inserts new node at the specified row index. If a node with the
+     *  index already exists, it will be returned.
+     * 
+     *  @param index The row index in which to create and insert the node.
+     *  
+     *  @return The newly created or existing node for the specified row index.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function insert(index:int):GridRowNode
+    {
+        // empty list
+        if (_head == null)
+        {
+            _head = new GridRowNode(numColumns, index);
+            _tail = _head;
+            _length++;
+            return _head;
+        }
+        
+        // This part can be optimized by a better search mechanism
+        // Bookmarks, LRU node...etc...
+        var cur:GridRowNode = findNearestLTE(index);
+        if (cur && cur.rowIndex == index)
+            return cur;
+        
+        var newNode:GridRowNode = new GridRowNode(numColumns, index);
+        
+        // index is before head.
+        if (!cur)
+            insertBefore(_head, newNode);
+        else // index is after cur.
+            insertAfter(cur, newNode);
+        
+        recentNode = newNode;
+        
+        return newNode;
+    }
+    
+    /**
+     *  Inserts a new node after the specified node. Returns
+     *  the new node.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function insertAfter(node:GridRowNode, newNode:GridRowNode):void
+    {
+        newNode.prev = node;
+        newNode.next = node.next;
+        if (node.next == null)
+            _tail = newNode;
+        else
+            node.next.prev = newNode;
+        node.next = newNode;
+        
+        _length++;
+    }
+    
+    /**
+     *  Inserts a new node after the specified node. Returns
+     *  the new node.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function insertBefore(node:GridRowNode, newNode:GridRowNode):void
+    {
+        newNode.prev = node.prev;
+        newNode.next = node;
+        if (node.prev == null)
+            _head = newNode;
+        else
+            node.prev.next = newNode;
+        node.prev = newNode;
+        
+        _length++;
+    }
+    
+    /**
+     *  Searches through all nodes for the given row index.
+     * 
+     *  @param index The row index to find.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function find(index:int):GridRowNode
+    {
+        // use bookmarks? or maybe a least recently used one.
+        if (!_head)
+            return null;
+        
+        var indexToRecent:int;
+        var temp:int;
+        var lastToIndex:int = _tail.rowIndex - index;
+        var result:GridRowNode = null;
+        
+        if (recentNode)
+        {
+            if (recentNode.rowIndex == index)
+                return recentNode;
+            
+            indexToRecent = recentNode.rowIndex - index;
+            temp = Math.abs(indexToRecent);
+        }
+        
+        // Uses last searched node if its closest to the target.
+        if (lastToIndex < 0)
+        {
+            return null;
+        }
+        else if (recentNode && temp < lastToIndex && temp < index)
+        {
+            if (indexToRecent > 0)
+                result = findBefore(index, recentNode);
+            else
+                result = findAfter(index, recentNode);
+        }
+        else if (lastToIndex < index)
+        {
+            result = findBefore(index, _tail);
+        }
+        else
+        {
+            result = findAfter(index, _head);
+        }
+        
+        if (result)
+            recentNode = result;
+        
+        return result;
+    }
+    
+    /**
+     *  @private
+     *  Searches for the given value after the specified node.
+     */
+    private function findAfter(index:int, node:GridRowNode):GridRowNode
+    {
+        var cur:GridRowNode = node;
+        var result:GridRowNode = null;
+        while (cur && cur.rowIndex <= index)
+        {
+            if (cur.rowIndex == index)
+            {
+                result = cur;
+                break;
+            }
+            cur = cur.next;
+        }
+        return result;
+    }
+    
+    /**
+     *  @private
+     *  Searches for the given value before the specified node.
+     */
+    private function findBefore(index:int, node:GridRowNode):GridRowNode
+    {
+        var cur:GridRowNode = node;
+        var result:GridRowNode = null;
+        while (cur && cur.rowIndex >= index)
+        {
+            if (cur.rowIndex == index)
+            {
+                result = cur;
+                break;
+            }
+            cur = cur.prev;
+        }
+        return result;
+    }
+    
+    /**
+     *  Searches through all nodes for the one with a row index closest and
+     *  less than equal to the specified index. If a node with the row index
+     *  exists, it will just return the node at that index. Returns null if
+     *  all nodes have a row index greater than the provided index.
+     * 
+     *  @param index The row index to find
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function findNearestLTE(index:int):GridRowNode
+    {
+        // use bookmarks? or maybe a least recently used one.
+        if (!_head || index < 0)
+            return null;
+        
+        var indexToRecent:int;
+        var temp:int;
+        var lastToIndex:int;
+        var result:GridRowNode = null;
+        
+        if (recentNode)
+        {
+            if (recentNode.rowIndex == index)
+                return recentNode;
+            
+            indexToRecent = recentNode.rowIndex - index;
+            temp = Math.abs(indexToRecent);
+        }
+        
+        lastToIndex = _tail.rowIndex - index;
+        
+        if (index < _head.rowIndex)
+        {
+            result = null;
+        }
+        // Uses last searched node if its closest to the target.
+        else if (lastToIndex < 0)
+        {
+            result = _tail;
+        }
+        else if (recentNode && temp < lastToIndex && temp < index)
+        {
+            if (indexToRecent > 0)
+                result = findNearestLTEBefore(index, recentNode);
+            else
+                result = findNearestLTEAfter(index, recentNode);
+        }
+        else if (lastToIndex < index)
+        {
+            result = findNearestLTEBefore(index, _tail);
+        }
+        else
+        {
+            result = findNearestLTEAfter(index, _head);
+        }
+        
+        recentNode = result;
+        
+        return result;
+    }
+    
+    /**
+     *  @private
+     *  Searches through all nodes for the one with a row index closest and
+     *  less than equal to the specified index. Searches forwards from the specified node.
+     */
+    private function findNearestLTEAfter(index:int, node:GridRowNode):GridRowNode
+    {
+        var cur:GridRowNode = node;
+        while (cur && cur.rowIndex < index)
+        {
+            if (cur.next == null)
+                break;
+            else if (cur.next.rowIndex > index)
+                break;
+            
+            cur = cur.next;
+        }
+        return cur;
+    }
+    
+    /**
+     *  @private
+     *  Searches through all nodes for the one with a row index closest and
+     *  less than equal to the specified index. Searches backwards from the specified node.
+     */
+    private function findNearestLTEBefore(index:int, node:GridRowNode):GridRowNode
+    {
+        var cur:GridRowNode = node;
+        while (cur && cur.rowIndex > index)
+        {
+            cur = cur.prev;
+        }
+        return cur;
+    }
+    
+    /**
+     *  Inserts the specified node at the end of the list.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function push(node:GridRowNode):void
+    {
+        if (_tail)
+        {
+            node.prev = _tail;
+            node.next = null;
+            _tail.next = node;
+            _tail = node;
+            _length++;
+        }
+        else
+        {
+            node.prev = null;
+            node.next = null;
+            _head = node;
+            _tail = node;
+            _length = 1;
+        }
+    }
+    
+    /**
+     *  Searches through all nodes for the given row index and
+     *  removes it from the list if found.
+     * 
+     *  @param index The row index to remove.
+     *  
+     *  @return The removed node, null otherwise.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function remove(index:int):GridRowNode
+    {
+        var node:GridRowNode = find(index);
+        if (node)
+            removeNode(node);
+        return node;
+    }
+    
+    /**
+     *  Removes specified node from the list.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function removeNode(node:GridRowNode):void
+    {
+        if (node.prev == null)
+            _head = node.next;
+        else
+            node.prev.next = node.next;
+        
+        if (node.next == null)
+            _tail = node.prev;
+        else
+            node.next.prev = node.prev;
+        
+        node.next = null;
+        node.prev = null;
+        
+        if (node == recentNode)
+            recentNode = null;
+        
+        _length--;
+    }
+    
+    /**
+     *  Removes all nodes.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function removeAll():void
+    {
+        this._head = null;
+        this._tail = null;
+        this._length = 0;
+        this.recentNode = null;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Methods for column changes
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Inserts count number of columns into each node and
+     *  increases numColumns by count.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function insertColumns(startColumn:int, count:int):void
+    {
+        _numColumns += count;
+        
+        var node:GridRowNode = first;
+        while (node)
+        {   
+            node.insertColumns(startColumn, count);
+            node = node.next;
+        }
+    }
+    
+    /**
+     *  Inserts count number of columns into each node and
+     *  increases numColumns by count.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function removeColumns(startColumn:int, count:int):void
+    {
+        _numColumns -= count;
+        
+        var node:GridRowNode = first;
+        while (node)
+        {
+            node.removeColumns(startColumn, count);
+            node = node.next;
+        }
+    }
+    
+    /**
+     *  Moves the specified columns in each node.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function moveColumns(fromCol:int, toCol:int, count:int):void
+    {
+        var node:GridRowNode = first;
+        while (node)
+        {
+            node.moveColumns(fromCol, toCol, count);
+            node = node.next;
+        }
+    }
+    
+    /**
+     *  Clears the column values for count number of columns in each
+     *  node.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function clearColumns(startColumn:int, count:int):void
+    {
+        var node:GridRowNode = first;
+        while (node)
+        {
+            node.clearColumns(startColumn, count);
+            node = node.next;
+        }
+    }
+    
+    /**
+     *  @private
+     *  for testing;
+     */
+    public function toString():String
+    {
+        var s:String = "[ ";
+        var node:GridRowNode = this.first;
+        
+        while (node)
+        {
+//            s += "max = " + node.maxCellHeight + "; index = " + node.rowIndex + "; "
+//                 node.cellHeights + "\n";
+            s += "(" + node.rowIndex + "," + node.maxCellHeight + ") -> ";
+            node = node.next;
+        }
+        s += "]";
+        
+        return s;
+    }
+    
+    /**
+     *  @private
+     *  for testing;
+     */
+    public function toArray():ArrayCollection
+    {
+        var arr:ArrayCollection = new ArrayCollection();
+        var node:GridRowNode = this.first;
+        var index:int = 0;
+        
+        while (node)
+        {
+            arr.addItem(node);
+            node = node.next;
+        }
+        return arr;
+    }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridRowNode.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridRowNode.as
new file mode 100644
index 000000000..80f41110a
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridRowNode.as
@@ -0,0 +1,305 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+    
+[ExcludeClass]
+    
+/**
+ *  A GridRowNode represents the heights of each cell for the row at rowIndex,
+ *  and keeps track of the maximum cell height.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.0
+ *  @productversion Flex 4.5
+ */
+public final class GridRowNode
+{
+    private var _rowIndex:int;
+	
+	public function get rowIndex():int
+	{
+		return _rowIndex;
+	}
+    
+	public function set rowIndex(value:int):void
+	{
+		_rowIndex = value;
+	}
+	
+    private var cellHeights:Vector.<Number>;
+    
+	private var _maxCellHeight:Number = -1;
+	public function get maxCellHeight():Number
+	{
+		return _maxCellHeight;
+	}
+	
+	public function set maxCellHeight(value:Number):void
+	{
+		_maxCellHeight = value;
+	}
+	
+    private var _fixedHeight:Number = -1;
+	public function get fixedHeight():Number
+	{
+		return _fixedHeight;
+	}
+	
+	public function set fixedHeight(value:Number):void
+	{
+		_fixedHeight = value;
+	}
+    
+	private var _next:GridRowNode;
+	public function get next():GridRowNode
+	{
+		return _next;
+	}
+	
+	public function set next(value:GridRowNode):void
+	{
+		_next = value;
+	}
+	
+	private var _prev:GridRowNode;
+	public function get prev():GridRowNode
+	{
+		return _prev;
+	}
+	
+	public function set prev(value:GridRowNode):void
+	{
+		_prev = value;
+	}
+	
+    /**
+     *  Constructor.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function GridRowNode(numColumns:uint, rowIndex:int)
+    {
+        super();
+        
+        this.rowIndex = rowIndex;
+        _numColumns = numColumns;
+        
+        // initialize cellHeights. all are -1 to start out with.
+        cellHeights = new Vector.<Number>(numColumns);
+        GridDimensions.clearVector(cellHeights, -1);
+    }
+    
+    private var _numColumns:uint;
+    
+    /**
+     *  Number of columns in this row.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function get numColumns():uint
+    {
+        return _numColumns;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set numColumns(value:uint):void
+    {
+        if (value == _numColumns)
+            return;
+        
+        cellHeights.length = value;
+        
+        if (value > _numColumns)
+        {
+            for (var i:int = value - _numColumns; i < value; i++)
+                cellHeights[i] = -1;
+        }
+        else
+        {
+            updateMaxHeight();
+        }
+        
+        _numColumns = value;
+    }
+
+    /**
+     *  Updates the current max height.
+     * 
+     *  @return true if changed
+     */
+    private function updateMaxHeight():Boolean
+    {
+        var max:Number = -1;
+        for each (var cellHeight:Number in cellHeights)
+        {
+            if (cellHeight > max)
+                max = cellHeight;
+        }
+        
+        const changed:Boolean = maxCellHeight != max;
+        if (changed)
+            maxCellHeight = max;
+        return changed;
+    }
+    
+    /**
+     *  Returns the cell height at the specified column.
+     *  
+     *  @return the cell height at the given column. NaN if index
+     *  is out of bounds.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function getCellHeight(index:int):Number
+    {
+        if (index < 0 || index >= cellHeights.length)
+            return NaN;
+        return cellHeights[index];
+    }
+    
+    /**
+     *  Updates the height at the specified column.
+     * 
+     *  @return true if max height has changed.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function setCellHeight(index:int, value:Number):Boolean
+    {
+        if (cellHeights[index] == value)
+            return false;
+        
+        cellHeights[index] = value;
+        
+        // If new height is equal to maxCellHeight, it doesn't change
+        // so just return.
+        if (value == maxCellHeight)
+            return false;
+        
+        // If new height is greater than maxCellHeight, the new height 
+        // is the new maxCellHeight.
+        if (value > maxCellHeight)
+        {
+            maxCellHeight = value;
+            return true;
+        }
+        
+        // If new height is less than maxCellHeight, we need to check if
+        // the maxCellHeight has changed.
+        return updateMaxHeight();
+    }
+    
+    /**
+     *  Shifts values such that count columns are inserted
+     *  from the startIndex.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function insertColumns(startColumn:int, count:int):void
+    {
+        GridDimensions.insertValueToVector(cellHeights, startColumn, count, -1);
+    }
+    
+    /**
+     *  Removes and adds values such that the specified columns are moved.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function moveColumns(fromCol:int, toCol:int, count:int):void
+    {
+        GridDimensions.insertElementsToVector(cellHeights, toCol, cellHeights.splice(fromCol, count));
+    }
+    
+    /**
+     *  Clears values such that count columns are 0.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function clearColumns(startColumn:int, count:int):void
+    {
+        GridDimensions.clearVector(cellHeights, -1, startColumn, count);
+        updateMaxHeight();
+    }
+    
+    /**
+     *  Shifts values such that count columns are removed
+     *  from the startColumn. We assume that cellHeights is the right length.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.5
+     */
+    public function removeColumns(startColumn:int, count:int):void
+    {
+        cellHeights.splice(startColumn, count);
+        updateMaxHeight();
+    }
+    
+    /**
+     *  @private
+     *  toString method for testing.
+     */
+    public function toString():String
+    {
+        var s:String = "";
+        
+        s += "(" + rowIndex + ", " + maxCellHeight + ") ";
+        s += cellHeights + "\n";
+        if (prev)
+            s += prev.rowIndex;
+        else
+            s += "null";
+        
+        s += " <- -> ";
+        if (next)
+            s += next.rowIndex;
+        else
+            s += "null";
+        
+        return s;
+    }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSelection.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSelection.as
new file mode 100644
index 000000000..77ddec483
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSelection.as
@@ -0,0 +1,1803 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+
+// import flash.geom.Rectangle;
+import org.apache.royale.geom.Rectangle;
+
+import mx.collections.ICollectionView;
+import mx.collections.IList;
+import mx.core.mx_internal;
+import mx.events.CollectionEvent;
+import mx.events.CollectionEventKind;
+
+import spark.components.Grid;
+import spark.components.gridClasses.CellPosition;
+
+use namespace mx_internal;
+  
+[ExcludeClass]
+
+/**
+ *  Use the GridSelection class to track a Grid control's 
+ *  <code>selectionMode</code> property and its set of selected rows, columns, or cells.   
+ *  The selected elements are defined by integer indices.
+ * 
+ *  @see spark.components.Grid
+ *  @see spark.components.Grid#columns
+ *  @see spark.components.Grid#dataProvider
+ *  @see spark.components.gridClasses.GridSelectionMode
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5
+ */
+public class GridSelection
+{
+    //include "../../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class variables
+    //
+    //--------------------------------------------------------------------------
+        
+    /**
+     *  @private
+     *  List of ordered selected/de-selected cell regions used to represent
+     *  either row or cell selections depending on the selection mode.  
+     *  (For row selection, a row region will be in column 0 and column count 
+     *  will be 1.)
+     *
+     *  This is the list of cell regions that have
+     *  been added (isAdd==true) and removed (isAdd==false). 
+     *   
+     *  Internally, regionsContainCell should be used to determine if a cell/row
+     *  is in the selection.
+     */    
+    private var cellRegions:Vector.<CellRect> = new Vector.<CellRect>();
+           
+    /**
+     *  @private
+     *  If preserveSelection, and selectionMode is "singleRow" or "singleCell",
+     *  cache the dataItem that goes with the selection so we can find the
+     *  index of the selection after a collection refresh event.
+     */    
+    private var selectedItem:Object;
+    
+    /**
+     *  @private
+     *  True if in a collection handler.  If this is the case, there is no
+     *  need to validate the index/indices.  In the case of 
+     *  CollectionEventKind.REMOVE, when the last item selected and it is 
+     *  removed from the collection, the validate would fail since the index is 
+     *  now out of range and the item would incorrectly remain in the selection.
+     */    
+    private var inCollectionHandler:Boolean;
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructor.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function GridSelection()
+    {
+        super();
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+   
+    //----------------------------------
+    //  grid
+    //----------------------------------
+    
+    private var _grid:Grid;
+    
+    /**
+     *  The grid control associated with this object. 
+     *  This property should only be set once.
+     *
+     *  <p>For the Spark DataGrid, this value is initialized by 
+     *  the <code>DataGrid.partAdded()</code> method.</p>   
+     * 
+     *  @default null
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get grid():Grid
+    {
+        return _grid;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set grid(value:Grid):void
+    {
+        _grid = value;
+    }
+    
+    //----------------------------------
+    //  preserveSelection
+    //----------------------------------
+    
+    private var _preserveSelection:Boolean = true;
+    
+    /**
+     *  If <code>true</code>, and <code>selectionMode</code> is 
+     *  <code>GridSelectionMode.SINGLE_ROW</code> or 
+     *  <code>GridSelectionMode.SINGLE_CELL</code>, then selection is
+     *  preserved when the <code>dataProvider</code> refreshes its collection,
+     *  and the selected item is contained in the collection after
+     *  the refresh.
+     *
+     *  @default true
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get preserveSelection():Boolean
+    {
+        return _preserveSelection;
+    }
+    
+    /**
+     *  @private
+     */    
+    public function set preserveSelection(value:Boolean):void
+    {
+        if (_preserveSelection == value)
+            return;
+        
+        _preserveSelection = value;
+        
+        selectedItem = null;
+        
+        // If preserving the selection and there is currently a selection,
+        // save the corresponding data item.
+        if (_preserveSelection && 
+            (selectionMode == GridSelectionMode.SINGLE_ROW || 
+                selectionMode == GridSelectionMode.SINGLE_CELL) && 
+            selectionLength > 0)
+        {
+            if (selectionMode == GridSelectionMode.SINGLE_ROW)
+                selectedItem = grid.dataProvider.getItemAt(allRows()[0]);
+            else  // SINGLE_CELL
+                selectedItem = grid.dataProvider.getItemAt(allCells()[0].rowIndex);
+        }
+    }
+    
+    //----------------------------------
+    //  requireSelection
+    //----------------------------------
+    
+    private var _requireSelection:Boolean = false;
+    
+    /**
+     *  If <code>true</code>, a data item must always be selected in the 
+     *  control as long as there is at least one item in 
+     *  <code>dataProvider</code> and one column in <code>columns</code>.
+     *
+     *  @default false
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get requireSelection():Boolean
+    {
+        return _requireSelection;
+    }
+    
+    /**
+     *  @private
+     */    
+    public function set requireSelection(value:Boolean):void
+    {
+        if (_requireSelection == value)
+            return;
+        
+        _requireSelection = value;
+             
+        if (_requireSelection)
+            ensureRequiredSelection();
+    }
+
+    //----------------------------------
+    //  selectionLength
+    //----------------------------------
+       
+    /**
+     *  @private
+     *  Cache the selectionLength.  Only recalculate if selectionLength is -1.
+     */
+    private var _selectionLength:int = 0;    
+    
+    /**
+     *  The length of the selection.
+     * 
+     *  <p>If the <code>selectionMode</code> is either 
+     *  <code>GridSelectionMode.SINGLE_ROW</code> or
+     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, contains the number of
+     *  selected rows.  If a selected row has no <code>columns</code> whose 
+     *  <code>visible</code> property is set to <code>true</code> it is still
+     *  included in the number of selected rows.</p>
+     * 
+     *  <p>If the <code>selectionMode</code> is either 
+     *  <code>GridSelectionMode.SINGLE_CELL</code> or
+     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, contains the number of
+     *  selected cells.  
+     *  If a selected cell is in a column which has its <code>visible</code>
+     *  property set to false after it is selected, the cell is included in 
+     *  the number of selected cells.</p>
+     * 
+     *  <p>If the <code>selectionMode</code> is <code>GridSelectionMode.NONE</code>, 
+     *  contains 0.</p>
+     *  
+     *  @default 0
+     * 
+     *  @return Number of selected rows or cells.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get selectionLength():int
+    {
+        // Note: this assumes there are no duplicate cells in cellRegions - ie
+        // 2 adds of the same cell without an intermediate delete.
+        
+        const isRows:Boolean = isRowSelectionMode();
+        
+        if (_selectionLength < 0)
+        {
+            _selectionLength = 0;
+            
+            const cellRegionsLength:int = cellRegions.length;            
+            /*for (var i:int = 0; i < cellRegionsLength; i++)
+            {
+                var cr:CellRect = cellRegions[i];
+                const numSelected:int = isRows ? cr.height : cr.height * cr.width;
+               
+                if (cr.isAdd)
+                    _selectionLength += numSelected;
+                else
+                    _selectionLength -= numSelected;
+            }*/
+        }
+        
+        return _selectionLength;        
+    }
+    
+    //----------------------------------
+    //  selectionMode
+    //----------------------------------
+    
+    private var _selectionMode:String = GridSelectionMode.SINGLE_ROW;
+    
+    /**
+     *  The selection mode of the control.  Possible values are:
+     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, 
+     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
+     *  <code>GridSelectionMode.NONE</code>, 
+     *  <code>GridSelectionMode.SINGLE_CELL</code>, and 
+     *  <code>GridSelectionMode.SINGLE_ROW</code>.
+     * 
+     *  <p>Changing the <code>selectionMode</code> causes the 
+     *  current selection to be cleared.</p>
+     *
+     *  @default GridSelectionMode.SINGLE_ROW
+     * 
+     *  @see spark.components.gridClasses.GridSelectionMode
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get selectionMode():String
+    {
+        return _selectionMode;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set selectionMode(value:String):void
+    {
+        if (value == _selectionMode)
+            return;
+        
+        switch (value)
+        {
+            case GridSelectionMode.SINGLE_ROW:
+            case GridSelectionMode.MULTIPLE_ROWS:
+            case GridSelectionMode.SINGLE_CELL:
+            case GridSelectionMode.MULTIPLE_CELLS:
+            case GridSelectionMode.NONE:
+                _selectionMode = value;
+                removeAll();
+                break;
+        }
+    }
+    
+    /**
+     *  If the <code>selectionMode</code> is either <code>GridSelectionMode.SINGLE_CELL</code> or
+     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns a list of all the
+     *  selected cells.
+     * 
+     *  @return Vector of selected cell locations as row and column indices or,
+     *  if none are selected, a Vector of length 0.  
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+	
+    public function allCells():Vector.<CellPosition>
+    {
+        var cells:Vector.<CellPosition> = new Vector.<CellPosition>;
+    	/*    
+        if (!isCellSelectionMode())
+            return cells;
+
+        // Iterate over the selected cells region.
+        const bounds:Rectangle = getCellRegionsBounds();        
+        const left:int = bounds.left;
+        const right:int = bounds.right;
+        const bottom:int = bounds.bottom;
+              
+        for (var rowIndex:int = bounds.top; rowIndex < bottom; rowIndex++)
+        {
+            for (var columnIndex:int = left; columnIndex < right; columnIndex++)
+            {
+                if (regionsContainCell(rowIndex, columnIndex))
+                    cells.push(new CellPosition(rowIndex, columnIndex));
+            }
+        }
+        */
+        return cells;
+    }
+     
+    /**
+     *  If the <code>selectionMode</code> is either <code>GridSelectionMode.SINGLE_ROW</code> or
+     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns a list of all the
+     *  selected rows.
+     * 
+     *  @return Vector of selected rows as row indices or, if none, a Vector 
+     *  of length 0.  
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function allRows():Vector.<int>
+    {
+        if (!isRowSelectionMode())
+            return new Vector.<int>(0, true);
+        
+        var rows:Vector.<int> = new Vector.<int>();
+        
+        const bounds:Rectangle = getCellRegionsBounds();
+        const bottom:int = bounds.bottom;
+                
+        for (var rowIndex:int = bounds.top; rowIndex < bottom; rowIndex++)
+        {
+            // row is represented as cell in column 0 of the row   
+            if (regionsContainCell(rowIndex, 0))
+                rows.push(rowIndex);
+        }
+       
+        return rows;
+    }
+
+    /**
+     *  If the <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_ROWS</code> 
+     *  selects all the rows in the grid and if <code>selectionMode</code> is 
+     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, selects all the cells in
+     *  columns with <code>visible</code> set to <code>true</code>.
+     * 
+     *  @return <code>true</code> if the selection changed.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function selectAll():Boolean
+    {
+        const maxRows:int = getGridDataProviderLength();
+
+        if (selectionMode == GridSelectionMode.MULTIPLE_ROWS)
+        {
+            return setRows(0, maxRows);
+        }
+        else if (selectionMode == GridSelectionMode.MULTIPLE_CELLS)
+        {
+            const maxColumns:int = getGridColumnsLength();
+            return setCellRegion(0, 0, maxRows, maxColumns);
+        }
+            
+        return false;
+     }
+    
+    /**
+     *  Remove the current selection.  
+     *  If <code>requireSelection</code> is <code>true</code>,
+     *  and the <code>selectionMode</code> is row-based, then row 0
+     *  is selected.
+     *  If the <code>selectionMode</code> is cell-based,
+     *  then cell 0,0 is selected.
+     * 
+     *  @return <code>true</code> if the list of selected items has changed from the last call.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function removeAll():Boolean
+    {
+        var selectionChanged:Boolean = removeSelection();        
+        return ensureRequiredSelection() || selectionChanged;
+    }
+            
+    //----------------------------------
+    //  Rows
+    //----------------------------------
+
+    /**
+     *  If the <code>selectionMode</code> is either <code>GridSelectionMode.SINGLE_ROW</code> or
+     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, determines if the row is in 
+     *  the current selection. 
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @return <code>true</code> if the row is in the selection
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function containsRow(rowIndex:int):Boolean
+    {
+        if (!validateIndex(rowIndex))
+            return false;
+
+        return regionsContainCell(rowIndex, 0);
+    }
+    
+    /**
+     *  If the <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
+     *  determines if the rows are in the current selection.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @return <code>true</code> if the rows are in the selection
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function containsRows(rowsIndices:Vector.<int>):Boolean
+    {
+        if (!validateIndices(rowsIndices))
+            return false;
+        
+        for each (var rowIndex:int in rowsIndices)
+        {
+            if (!regionsContainCell(rowIndex, 0))
+                return false;            
+        }
+                
+        return true;
+    }
+    
+    /**
+     *  If the <code>selectionMode</code> is either <code>GridSelectionMode.SINGLE_ROW</code> 
+     *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, replaces the current 
+     *  selection with the specified row.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @return <code>true</code> if no errors, or <code>false</code> if the 
+     *  <code>rowIndex</code> is not a valid index in the control's <code>dataProvider</code>, 
+     *  or if the <code>selectionMode</code> is not valid.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function setRow(rowIndex:int):Boolean
+    {        
+        if (!validateIndex(rowIndex))
+            return false;
+    
+        internalSetCellRegion(rowIndex);
+                
+        return true;
+    }
+    
+    /**
+     *  If the <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
+     *  adds the row to the selection.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @return <code>true</code> if no errors, or <code>false</code> if the 
+     *  <code>rowIndex</code> is not a valid index in the 
+     *  control's <code>dataProvider</code>, or the <code>selectionMode</code> is not valid.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function addRow(rowIndex:int):Boolean
+    {
+        if (!validateIndex(rowIndex))
+            return false;
+             
+        if (selectionMode != GridSelectionMode.MULTIPLE_ROWS)
+            return false;
+        
+        internalAddCell(rowIndex);
+
+        return true;
+   }
+    
+    /**
+     *  If the <code>selectionMode</code> is either <code>GridSelectionMode.SINGLE_ROW</code> 
+     *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, removes the row from 
+     *  the selection.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @return <code>true</code> if no errors.
+     *  Returns <code>false</code> if the 
+     *  <code>rowIndex</code> is not a valid index in the 
+     *  control's <code>dataProvider</code>, 
+     *  or if the <code>selectionMode</code> is not valid.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function removeRow(rowIndex:int):Boolean
+    {
+        if (!validateIndex(rowIndex) )
+            return false;
+        
+        if (requireSelection && containsRow(rowIndex) && selectionLength == 1)
+            return false;
+                            
+        internalRemoveCell(rowIndex);
+        
+        return true;
+    }
+    
+    /**
+     *  If the <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
+     *  replaces the current selection with the <code>rowCount</code> rows starting at 
+     *  <code>rowIndex</code>.
+     * 
+     *  @param rowIndex 0-based row index of the first row in the selection.
+     *  @param rowCount Number of rows in the selection.
+     * 
+     *  @return <code>true</code> if no errors. 
+     *  Returns <code>false</code> if any of the indices are invalid,
+     *  if <code>startRowIndex</code> is not less than or equal to <code>endRowIndex</code>,
+     *  or if the <code>selectionMode</code> is not valid.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function setRows(rowIndex:int, rowCount:int):Boolean
+    {
+        if (!validateRowRegion(rowIndex, rowCount))
+            return false;
+
+        internalSetCellRegion(rowIndex, 0, rowCount, 1);
+         
+        return true;
+    }
+     
+    //----------------------------------
+    //  Cells
+    //----------------------------------
+
+    /**
+     *  If the <code>selectionMode</code> is either 
+     *  <code>GridSelectionMode.SINGLE_CELLS</code> 
+     *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, determines if the cell 
+     *  is in the current selection.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @param columnsIndex The 0-based column index.
+     * 
+     *  @return <code>true</code> if the cell is in the selection.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function containsCell(rowIndex:int, columnIndex:int):Boolean
+    {   
+        if (!validateCell(rowIndex, columnIndex))
+            return false;
+                
+        return regionsContainCell(rowIndex, columnIndex);
+    }
+        
+    /**
+     *  If the <code>selectionMode</code> is
+     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, determines if all the 
+     *  cells in the cell region are in the current selection.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @param columnsIndex The 0-based column index.
+     * 
+     *  @param rowCount The row height of the region.
+     * 
+     *  @param columnsCount The width of the cell region, in columns.
+     * 
+     *  @return <code>true</code> if the cells are in the selection.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function containsCellRegion(rowIndex:int, columnIndex:int,
+                                       rowCount:int, columnCount:int):Boolean
+    {
+        if (!validateCellRegion(rowIndex, columnIndex, rowCount, columnCount))
+            return false;
+        
+        if (rowCount * columnCount > selectionLength)
+            return false;
+        
+        const cellRegionsLength:int = cellRegions.length;
+        
+        if (cellRegionsLength == 0)
+            return false;
+        
+        // Simple selection.
+        /*
+        if (cellRegionsLength == 1)
+        {
+            const cr:CellRect = cellRegions[0];
+            return (rowIndex >= cr.top && columnIndex >= cr.left &&
+                    rowIndex + rowCount <= cr.bottom &&
+                    columnIndex + columnCount <= cr.right);
+        }
+        */
+        // Not a simple selection so we're going to have to check each cell.
+        
+        const bottom:int = rowIndex + rowCount;
+        const right:int = columnIndex + columnCount;
+        
+        for (var r:int = rowIndex; r < bottom; r++)
+        {
+            for (var c:int = columnIndex; c < right; c++)
+            {
+                if (!containsCell(r, c))
+                    return false;
+            }
+        }
+        
+        return true;
+    }
+        
+    /**
+     *  If the <code>selectionMode</code> is either <code>GridSelectionMode.SINGLE_CELLS</code> 
+     *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, replaces the current 
+     *  selection with the cell at the given location.  The cell must be in
+     *  a visible column.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @param columnsIndex The 0-based column index.
+     * 
+     *  @return <code>true</code> no errors.
+     *  Returns <code>false</code> if 
+     *  <code>rowIndex</code> is not a valid index in <code>dataProvider</code>, 
+     *  if <code>columnIndex</code> is not a valid index in <code>columns</code>,
+     *  if the <code>selectionMode</code> is invalid or the column is not visible.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function setCell(rowIndex:int, columnIndex:int):Boolean
+    {
+        if (!validateCell(rowIndex, columnIndex))
+            return false;
+        
+        // columns and indexes validated above.
+        const columnVisible:Boolean = isColumnVisible(columnIndex);
+        if (columnVisible)
+            internalSetCellRegion(rowIndex, columnIndex, 1, 1);
+        
+        return columnVisible;
+    }
+        
+    /**
+     *  If the <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_CELLS</code>, 
+     *  adds the cell at the given location to the cell selection.  The cell
+     *  must be in a visible column.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @param columnsIndex The 0-based column index.
+     * 
+     *  @return <code>true</code> no errors.
+     *  Returns <code>false</code> if 
+     *  <code>rowIndex</code> is not a valid index in <code>dataProvider</code>, 
+     *  if <code>columnIndex</code> is not a valid index in <code>columns</code>,
+     *  if the <code>selectionMode</code> is invalid or the column is not visible.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function addCell(rowIndex:int, columnIndex:int):Boolean
+    {   
+        if (!validateCellRegion(rowIndex, columnIndex, 1, 1))
+            return false;
+        
+        // columns and indexes validated above.
+        const columnVisible:Boolean = isColumnVisible(columnIndex);
+        if (columnVisible)
+            internalAddCell(rowIndex, columnIndex);
+        
+        return columnVisible;
+    }
+
+    /**
+     *  If the <code>selectionMode</code> is either <code>GridSelectionMode.SINGLE_CELL</code>
+     *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, removes the cell at the
+     *  given position from the cell selection.
+     * 
+     *  @param rowIndex The 0-based row index.
+     * 
+     *  @param columnsIndex The 0-based column index.
+     * 
+     *  @return <code>true</code> if no errors.
+     *  Returns <code>false</code> if <code>rowIndex</code>
+     *  is not a valid index in <code>dataProvider</code>, or if  
+     *  <code>columnIndex</code> is not a valid index in <code>columns</code>,
+     *  or if the <code>selectionMode</code> is invalid.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function removeCell(rowIndex:int, columnIndex:int):Boolean
+    {
+        if (!validateCell(rowIndex, columnIndex))
+            return false;
+
+        if (requireSelection && containsCell(rowIndex, columnIndex) && selectionLength == 1)
+            return false;
+        
+        internalRemoveCell(rowIndex, columnIndex);
+        
+        return true;
+    }
+
+    /**
+     *  If the <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_CELLS</code>, 
+     *  replaces the current selection with the cells in the given cell region.
+     *  The origin of the cell region is the cell location specified by
+     *  <code>rowIndex</code> and <code>columnIndex</code>, the width is
+     *  <code>columnCount</code> and the height is <code>rowCound</code>.
+     *
+     *  <p>Only cells in columns which are visible at the time of selection are
+     *  included in the selection.</p>
+     *
+     *  @param rowIndex The 0-based row index of the origin.
+     * 
+     *  @param columnsIndex The 0-based column index of the origin.
+     * 
+     *  @param rowCount The row height of the cell region.
+     * 
+     *  @param columnsCount The column width of the cell region.
+     * 
+     *  @return <code>true</code> if no errors.
+     *  Returns <code>false</code> if 
+     *  <code>rowIndex</code> is not a valid index in <code>dataProvider</code>, 
+     *  if <code>columnIndex</code> is not a valid index in <code>columns</code>,
+     *  or if the <code>selectionMode</code> is invalid.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public function setCellRegion(rowIndex:int, columnIndex:int, 
+                                  rowCount:uint, columnCount:uint):Boolean
+    {
+        if (!validateCellRegion(rowIndex, columnIndex, rowCount, columnCount))
+            return false;
+
+        removeSelection();
+        
+        var startColumnIndex:int = columnIndex;
+        var curColumnCount:int = 0;
+        
+        const endColumnIndex:int = columnIndex + columnCount - 1;
+        for (var i:int = columnIndex; i <= endColumnIndex; i++)
+        {    
+            // columns and indexes validated above.
+            const columnVisible:Boolean = isColumnVisible(i);
+            if (columnVisible)
+            {
+                curColumnCount++;
+                continue;
+            }
+            
+            // This column isn't visible so commit the cell region.
+            internalAddCellRegion(rowIndex, startColumnIndex, rowCount, curColumnCount);
+            
+            curColumnCount = 0;
+            startColumnIndex = i + 1;
+        }
+             
+        // If the last column(s) are not visible, need to commit the last
+        // cell region.
+        if (curColumnCount > 0)
+            internalAddCellRegion(rowIndex, startColumnIndex, rowCount, curColumnCount);
+            
+        return true;
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+        
+    /**
+     *  @private
+     */
+    private function isRowSelectionMode():Boolean
+    {
+        const mode:String = selectionMode;       
+        return mode == GridSelectionMode.SINGLE_ROW || 
+                mode == GridSelectionMode.MULTIPLE_ROWS;
+    }
+    
+    /**
+     *  @private
+     */
+    private function isCellSelectionMode():Boolean
+    {
+        const mode:String = selectionMode;        
+        return mode == GridSelectionMode.SINGLE_CELL || 
+                mode == GridSelectionMode.MULTIPLE_CELLS;
+    }     
+    
+    /**
+     *  @private
+     *  Assumes columns is set and index is valid.
+     */
+    private function isColumnVisible(columnIndex:int):Boolean
+    {
+        return false; // GridColumn(grid.columns.getItemAt(columnIndex)).visible;
+    }
+    
+    /**
+     *  @private
+     */
+    private function getGridColumnsLength():uint
+    {
+        if (grid == null)
+            return 0;
+        
+        const columns:IList = grid.columns;
+        return (columns) ? columns.length : 0;
+    }
+    
+    /**
+     *  @private
+     */
+    private function getGridDataProviderLength():uint
+    {
+        if (grid == null)
+            return 0;
+        
+        const dataProvider:IList = grid.dataProvider;
+        return (dataProvider) ? dataProvider.length : 0;
+    }    
+        
+    /**
+     *  @private
+     *  True if the given cell is contained in the list of cell regions.
+     */
+    private function regionsContainCell(rowIndex:int, columnIndex:int):Boolean
+    {   
+        // Find the index of the last isAdd=true cell region that contains 
+        // row,columnIndex.
+        const cellRegionsLength:int = cellRegions.length;
+        var index:int = -1;
+        for (var i:int = 0; i < cellRegionsLength; i++)
+        {
+            var cr:CellRect = cellRegions[i];
+            if (cr.isAdd && cr.containsCell(rowIndex, columnIndex))
+                index = i;
+        }
+        
+        // Is there an isAdd=true CellRegion that contains the cell?
+        if (index == -1) 
+            return false;
+        
+        // Starting with index, if any subsequent isAdd=false cell region
+        // contains row,columnIndex return false.
+        for (i = index + 1; i < cellRegionsLength; i++)
+        {
+            cr = cellRegions[i];
+            if (!cr.isAdd && cr.containsCell(rowIndex, columnIndex))
+                return false;
+        }
+        
+        return true;
+    }
+
+    /**
+     *  @private
+     *  If requiredSelection, then there must always be at least one row/cell
+     *  selected.  If the selection is changed, the caret is changed to match.
+     * 
+     *  @return true if the selection has changed.
+     */    
+    private function ensureRequiredSelection():Boolean
+    {
+        var selectionChanged:Boolean;
+        
+        if (!requireSelection)
+            return false;
+        
+        if (getGridDataProviderLength() == 0 || getGridColumnsLength() == 0)
+             return false;
+        
+        // If there isn't a selection, set one, using the grid method rather
+        // than the internal one, so that the caretPosition will be updated too.
+        if (isRowSelectionMode())
+        {
+            if (selectionLength == 0)
+                selectionChanged = grid.setSelectedIndex(0);
+        }
+        else if (isCellSelectionMode())
+        {
+            if (selectionLength == 0)
+                selectionChanged = grid.setSelectedCell(0, 0);
+        }
+                
+        return selectionChanged;
+    }
+    
+    /**
+     *  @private
+     *  Remove any currently selected rows, cells and cached items.  This
+     *  disregards the requireSelection flag.
+     */    
+    private function removeSelection():Boolean
+    {
+        const selectionChanged:Boolean = (selectionLength > 0);
+        
+        cellRegions.length = 0;       
+        _selectionLength = 0;
+        selectedItem = null;
+        
+        return selectionChanged;
+    }
+        
+    /**
+     *  @private
+     *  True if the selection mode is row-based and the 0-based index is 
+     *  valid index in the <code>dataProvider</code>.
+     */    
+    protected function validateIndex(index:int):Boolean
+    {
+        // Don't validate.
+        if (inCollectionHandler)
+            return true;
+        
+        return isRowSelectionMode() && 
+            index >= 0 && index < getGridDataProviderLength();
+    }
+    
+    /**
+     *  @private
+     *  True if the selection mode is <code>GridSelectionMode.MULTIPLE_ROWS</code>
+     *  and each index in indices is a valid index into the 
+     *  <code>dataProvider</code>.
+     */    
+    protected function validateIndices(indices:Vector.<int>):Boolean
+    {
+        if (selectionMode == GridSelectionMode.MULTIPLE_ROWS)
+        {
+            // Don't validate.
+            if (inCollectionHandler)
+                return true;
+
+            for each (var index:int in indices)
+            {
+                if (index < 0 || index >= getGridDataProviderLength())
+                    return false;
+            }            
+            return true;
+        }
+        
+        return false;
+    }
+    
+    /**
+     *  @private
+     *  True if the selection mode is <code>GridSelectionMode.SINGLE_CELL</code>
+     *  or code>GridSelectionMode.MULTIPLE_CELLS</code>
+     *  and the 0-based index is valid index in <code>columns</code>.
+     */    
+    protected function validateCell(rowIndex:int, columnIndex:int):Boolean
+    {
+        // Don't validate.
+        if (inCollectionHandler)
+            return true;
+
+        return isCellSelectionMode() && 
+            rowIndex >= 0 && rowIndex < getGridDataProviderLength() &&
+            columnIndex >= 0 && columnIndex < getGridColumnsLength();
+    }
+    
+    /**
+     *  @private
+     *  True if the selection mode is 
+     *  <code>GridSelectionMode.MULTIPLE_CELLS</code> and the entire cell region 
+     *  is contained within the grid.
+     */    
+    protected function validateCellRegion(rowIndex:int, columnIndex:int, 
+                                          rowCount:int, columnCount:int):Boolean
+    {
+        if (selectionMode == GridSelectionMode.MULTIPLE_CELLS)
+        {
+            // Don't validate.
+            if (inCollectionHandler)
+                return true;
+
+            const maxRows:int = getGridDataProviderLength();
+            const maxColumns:int = getGridColumnsLength();
+            return (rowIndex >= 0 && rowCount >= 0 &&
+                    rowIndex + rowCount <= maxRows &&
+                    columnIndex >= 0 && columnCount >= 0 &&
+                    columnIndex + columnCount <= maxColumns);
+        }
+        
+        return false;       
+    }
+    
+    /**
+     *  @private
+     *  True if the selection mode is 
+     *  <code>GridSelectionMode.MULTIPLE_ROW</code> and the entire row region 
+     *  is contained within the grid.
+     */    
+    protected function validateRowRegion(rowIndex:int, rowCount:int):Boolean
+    {
+        if (selectionMode == GridSelectionMode.MULTIPLE_ROWS)
+        {
+            // Don't validate.
+            if (inCollectionHandler)
+                return true;
+            
+            const maxRows:int = getGridDataProviderLength();
+            return (rowIndex >= 0 && rowCount >= 0 && rowIndex + rowCount <= maxRows);
+        }
+        
+        return false;       
+    }
+            
+    /**
+     *  @private
+     *  Initalize the list of cellRegions with this one.
+     */
+    private function internalSetCellRegion(rowIndex:int, columnIndex:int=0, 
+                                           rowCount:uint=1, columnCount:uint=1):void
+    {
+        const cr:CellRect = 
+            new CellRect(rowIndex, columnIndex, rowCount, columnCount, true);
+        
+        removeSelection();
+        cellRegions.push(cr);
+        
+        _selectionLength = rowCount * columnCount;
+        
+        if (preserveSelection && 
+            (selectionMode == GridSelectionMode.SINGLE_ROW || 
+            selectionMode == GridSelectionMode.SINGLE_CELL))
+        {
+            selectedItem = grid.dataProvider.getItemAt(rowIndex);
+        }
+    }
+
+    /**
+     *  @private
+     *  This should only be called by setCellRegion after the selection has been
+     *  removed.
+     *  This will add a cellRegion to the list of cellRegions.
+     *  This allows the special-handling needed for setting a cell region 
+     *  which has one of more columns which are not visible since only visible columns should
+     *  be included in the selection.
+     *  
+     *  The code is not equipped to handle the general case of overlapping
+     *  cell regions.
+     */
+    private function internalAddCellRegion(rowIndex:int, columnIndex:int=0, 
+                                           rowCount:uint=1, columnCount:uint=1):void
+    {
+        const cr:CellRect = 
+            new CellRect(rowIndex, columnIndex, rowCount, columnCount, true);
+        
+        cellRegions.push(cr);
+        
+        _selectionLength += rowCount * columnCount;
+    }
+
+    /**
+     *  @private
+     *  Add the given row/cell to the list of cellRegions.
+     */
+    private function internalAddCell(rowIndex:int, columnIndex:int=0):void
+    {
+        if (!regionsContainCell(rowIndex, columnIndex))
+        {
+            const cr:CellRect = 
+                new CellRect(rowIndex, columnIndex, 1, 1, true);
+            cellRegions.push(cr);
+            
+            // If the length is current before this add, just increment the 
+            // length.
+            if (_selectionLength >= 0)
+                _selectionLength++;
+        }
+    }
+              
+    /**
+     *  @private
+     *  Remove the given row/cell from the list of cellRegions.
+     */
+    private function internalRemoveCell(rowIndex:int, columnIndex:int=0):void
+    {
+        if (regionsContainCell(rowIndex, columnIndex))
+        {
+            const cr:CellRect = 
+                new CellRect(rowIndex, columnIndex, 1, 1, false);
+            cellRegions.push(cr);
+            
+            // If the length is current before this remove, just decrement the 
+            // length.
+            if (_selectionLength >= 0)
+                _selectionLength--;
+            
+            selectedItem = null;
+        }
+    }
+    
+    /**
+     *  @private
+     *  Find the bounding box for all the added cell regions.  It could be
+     *  larger than the current selection region if cell regions have been
+     *  removed.
+     */
+
+	private function getCellRegionsBounds():Rectangle
+    {
+        var bounds:Rectangle = new Rectangle();/*                         
+        const cellRegionsLength:int = cellRegions.length;
+        for (var i:int = 0; i < cellRegionsLength; i++)
+        {
+            var cr:CellRect = cellRegions[i];
+            if (!cr.isAdd)
+                continue;
+                
+            bounds = bounds.union(cr);
+        }
+        */
+        return bounds;
+    }
+      
+    //--------------------------------------------------------------------------
+    //
+    //  Data Provider Collection methods
+    //
+    //-------------------------------------------------------------------------- 
+
+    /**
+     *  @private
+     *  Called when the grid's dataProvider dispatches a 
+     *  <code>CollectionEvent.COLLECTION_CHANGE</code> event.  It handles
+     *  each of the events defined in <code>CollectionEventKind</code>.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function dataProviderCollectionChanged(event:CollectionEvent):Boolean
+    {
+        var selectionChanged:Boolean = false;
+        
+        inCollectionHandler = true;
+        
+        switch (event.kind)
+        {
+            case CollectionEventKind.ADD: 
+            {
+                selectionChanged = dataProviderCollectionAdd(event);
+                break;
+            }
+                
+            case CollectionEventKind.MOVE:
+            {
+                selectionChanged = dataProviderCollectionMove(event);
+                break;
+            }
+
+            case CollectionEventKind.REFRESH:
+            {
+                selectionChanged = dataProviderCollectionRefresh(event);
+                break;
+            }
+
+            case CollectionEventKind.REMOVE:
+            {
+                selectionChanged = dataProviderCollectionRemove(event);
+                break;
+            }
+                
+            case CollectionEventKind.REPLACE:
+            {
+                selectionChanged = dataProviderCollectionReplace(event);
+                break;
+            }
+                
+            case CollectionEventKind.RESET:
+            {
+                selectionChanged = dataProviderCollectionReset(event);
+                break;
+            }
+
+            case CollectionEventKind.UPDATE:
+            {
+                selectionChanged = dataProviderCollectionUpdate(event);
+                break;
+            }                
+        }
+        
+        inCollectionHandler = false;
+        
+        return selectionChanged;
+    }
+        
+    /**
+     *  @private
+     *  Add an item to the collection.
+     */
+    private function dataProviderCollectionAdd(event:CollectionEvent):Boolean
+    {
+        var selectionChanged:Boolean = handleRowAdd(event.location, event.items.length);        
+        return ensureRequiredSelection() || selectionChanged;
+    }
+
+    /**
+     *  @private
+     */
+    private function handleRowAdd(insertIndex:int, insertCount:int=1):Boolean
+    {
+        var selectionChanged:Boolean = false;
+        
+        for (var cnt:int = 0; cnt < insertCount; cnt++)
+        {
+            for (var crIndex:int = 0; crIndex < cellRegions.length; crIndex++)
+            {
+                var cr:CellRect = cellRegions[crIndex];
+                
+                // If the insert is before the region or at the first row of
+                // the region, move the region down a row.  If the insert is
+                // in the region (but not the first row), split the region
+                // into two and insert the new region.
+                /*if (insertIndex <= cr.y)
+                {
+                    cr.y++;
+                    selectionChanged = true;
+                }
+                else if (insertIndex < cr.bottom)
+                {
+                    var newCR:CellRect = 
+                        new CellRect(insertIndex + 1, cr.x, 
+                            cr.bottom - insertIndex, cr.width, 
+                            cr.isAdd);
+                    
+                    cr.height = insertIndex - cr.y;
+                    
+                    // insert newCR just after cr
+                    cellRegions.splice(++crIndex, 0, newCR);                    
+                    _selectionLength = -1;      // recalculate
+                    selectionChanged = true;
+                }*/
+            }
+        }
+        
+        return selectionChanged;
+    }
+
+    /**
+     *  @private
+     *  The item has been moved from the oldLocation to location.
+     */
+    private function dataProviderCollectionMove(event:CollectionEvent):Boolean
+    {
+        var selectionChanged:Boolean = false;
+        
+        const oldRowIndex:int = event.oldLocation;
+        var newRowIndex:int = event.location;
+        
+        selectionChanged = handleRowRemove(oldRowIndex);
+        
+        // If the row is removed before the newly added item
+        // then change index to account for this.
+        if (newRowIndex > oldRowIndex)
+            newRowIndex--;
+
+        return handleRowAdd(newRowIndex) || selectionChanged;
+    }
+
+    /**
+     *  @private
+     *  The sort or filter on the collection changed.
+     */
+    private function dataProviderCollectionRefresh(event:CollectionEvent):Boolean
+    {       
+        return handleRefreshAndReset(event);
+    }
+      
+    /**
+     *  @private
+     *  If preserving the selection and the selected item is in the new view, 
+     *  keep the item selected.  Otherwise, clear the selection (or maintain one
+     *  if requireSelection is true).
+     */
+    private function handleRefreshAndReset(event:CollectionEvent):Boolean
+    {
+        // Is the selectedItem still in the collection?
+        if (selectedItem)
+        {
+            const view:ICollectionView = event.currentTarget as ICollectionView;       
+            if (view && view.contains(selectedItem))
+            {
+                // Selection is in view so move it to the new row location.
+                const newRowIndex:int = grid.dataProvider.getItemIndex(selectedItem);
+                if (selectionMode == GridSelectionMode.SINGLE_ROW)
+                {
+                    internalSetCellRegion(newRowIndex);
+                }
+                else
+                {
+                    var oldSelectedCell:CellPosition = allCells()[0];
+                    internalSetCellRegion(newRowIndex, oldSelectedCell.columnIndex);
+                }
+                return true;
+            }
+        }
+        
+        // Not preserving selection or selection not in current view so remove 
+        // selection.
+        var selectionChanged:Boolean = removeSelection();
+        return ensureRequiredSelection() || selectionChanged;
+    }
+    
+    /**
+     *  @private
+     *  An item has been removed from the collection.
+     */
+    private function dataProviderCollectionRemove(event:CollectionEvent):Boolean
+    {
+        if (getGridDataProviderLength() == 0)
+            return removeSelection();
+
+        var selectionChanged:Boolean = handleRowRemove(event.location, event.items.length);         
+        return ensureRequiredSelection() || selectionChanged;
+    }
+     
+    /**
+     *  @private
+     */
+    private function handleRowRemove(removeIndex:int, removeCount:int=1):Boolean
+    {
+        var selectionChanged:Boolean = false;
+        
+        for (var cnt:int = 0; cnt < removeCount; cnt++)
+        {
+            var crIndex:int = 0
+            while (crIndex < cellRegions.length)
+            {
+                var cr:CellRect = cellRegions[crIndex];
+                
+                // Handle the cases where the remove is before the cell region
+                // or in the cell region.
+                /*if (removeIndex < cr.y)
+                {
+                    cr.y--;
+                    selectionChanged = true;
+                }
+                else if (removeIndex >= cr.y && removeIndex < cr.bottom)
+                {
+                    _selectionLength = -1;  // recalculate 
+                    selectionChanged = true;
+                    cr.height--;
+                    if (cr.height == 0)
+                    {
+                        cellRegions.splice(crIndex, 1);
+                        continue;
+                    }
+                }*/
+                crIndex++;
+            }
+        }
+        
+        return selectionChanged;
+    }
+        
+    /**
+     *  @private
+     *  The item has been replaced.
+     */
+    private function dataProviderCollectionReplace(event:CollectionEvent):Boolean
+    {
+        // Nothing to do here unless we're saving the data items to preserve
+        // the selection.
+        return false;
+    }
+    
+    /**
+     *  @private
+     *  The data source changed or all the items were removed from the data
+     *  source.  If there is a preserved selected item and it is in the new
+     *  data source the selection will be maintained.
+     */
+    private function dataProviderCollectionReset(event:CollectionEvent):Boolean
+    {        
+        return handleRefreshAndReset(event);
+    }
+
+    /**
+     *  @private
+     *  One or more items in the collection have been updated.
+     */
+    private function dataProviderCollectionUpdate(event:CollectionEvent):Boolean
+    {
+        // Nothing to do.
+        return false;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Columns Collection methods
+    //
+    //-------------------------------------------------------------------------- 
+    
+    /**
+     *  @private
+     *  Called when the grid's columns dispatches a 
+     *  <code>CollectionEvent.COLLECTION_CHANGE</code> event.  It handles
+     *  each of the events defined in <code>CollectionEventKind</code>.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function columnsCollectionChanged(event:CollectionEvent):Boolean
+    {
+        var selectionChanged:Boolean = false;
+
+        inCollectionHandler = true;
+        
+        switch (event.kind)
+        {
+            case CollectionEventKind.ADD: 
+            {
+                selectionChanged = columnsCollectionAdd(event);
+                break;
+            }
+                
+            case CollectionEventKind.MOVE:
+            {
+                selectionChanged = columnsCollectionMove(event);
+                break;
+            }
+                                
+            case CollectionEventKind.REMOVE:
+            {
+                selectionChanged = columnsCollectionRemove(event);
+                break;
+            }
+                
+            case CollectionEventKind.REPLACE:
+            case CollectionEventKind.UPDATE:
+            {
+                break;
+            }
+                
+            case CollectionEventKind.REFRESH:
+            {
+                selectionChanged = columnsCollectionRefresh(event);
+                break;                
+            }
+            case CollectionEventKind.RESET:
+            {
+                selectionChanged = columnsCollectionReset(event);
+                break;                
+           }
+        }
+        
+        inCollectionHandler = false;
+        
+        return selectionChanged;
+    }
+
+    /**
+     *  @private
+     *  Add a column to the columns collection.
+     */
+    private function columnsCollectionAdd(event:CollectionEvent):Boolean
+    {
+        // If no selectionMode or a row-based selectionMode, nothing to do.
+        if (!isCellSelectionMode())
+            return false;
+        
+        var selectionChanged:Boolean = handleColumnAdd(event.location, event.items.length);
+        
+        return ensureRequiredSelection() || selectionChanged;
+    }
+
+    /**
+     *  @private
+     */
+    private function handleColumnAdd(insertIndex:int, insertCount:int=1):Boolean
+    {
+        var selectionChanged:Boolean = false;
+
+        for (var cnt:int = 0; cnt < insertCount; cnt++)
+        {
+            for (var crIndex:int = 0; crIndex < cellRegions.length; crIndex++)
+            {
+                var cr:CellRect = cellRegions[crIndex];
+                
+                // If the insert is to the left of the region or at the 
+                // first column of the region, move the region to the right a
+                // column.  If the insert is in the region (but not the first
+                // column), split the region into two and insert the new region.
+                /*if (insertIndex <= cr.x)
+                {
+                    cr.x++;
+                    selectionChanged = true;
+                }
+                else if (insertIndex < cr.x)
+                {
+                    var newCR:CellRect = 
+                        new CellRect(cr.y, insertIndex + 1,
+                            cr.height, cr.right - insertIndex, 
+                            cr.isAdd);
+                    
+                    cr.width = insertIndex - cr.x;
+                    
+                    // insert newCR just after cr
+                    cellRegions.splice(++crIndex, 0, newCR);
+                    _selectionLength = -1;  // recalculate 
+                    selectionChanged = true;
+                }*/
+            }
+        }
+        
+        return selectionChanged;
+    }
+
+    /**
+     *  @private
+     *  The column has been moved from the oldLocation to location in the 
+     *  columns collection.
+     */
+    private function columnsCollectionMove(event:CollectionEvent):Boolean
+    {
+        // If no selectionMode or a row-based selectionMode, nothing to do.
+        if (!isCellSelectionMode())
+            return false;
+
+        const oldColumnIndex:int = event.oldLocation;
+        var newColumnIndex:int = event.location;
+        
+        var selectionChanged:Boolean = handleColumnRemove(oldColumnIndex);
+        
+        // If the column is removed before the newly added column
+        // then change index to account for this.
+        if (newColumnIndex > oldColumnIndex)
+            newColumnIndex--;
+        
+        return handleColumnAdd(newColumnIndex) || selectionChanged;
+    }   
+
+    /**
+     *  @private
+     *  A column has been removed from the columns collection.
+     */
+    private function columnsCollectionRemove(event:CollectionEvent):Boolean
+    {
+        // If no selectionMode or a row-based selectionMode, nothing to do.
+        if (!isCellSelectionMode())
+            return false;
+
+        if (getGridColumnsLength() == 0)
+            return removeSelection();
+        
+        var selectionChanged:Boolean = handleColumnRemove(event.location, event.items.length);         
+        return ensureRequiredSelection() || selectionChanged;
+    }
+    
+    /**
+     *  @private
+     */
+    private function handleColumnRemove(removeIndex:int, removeCount:int=1):Boolean
+    {
+        var selectionChanged:Boolean = false;
+        
+        for (var cnt:int = 0; cnt < removeCount; cnt++)
+        {
+            var crIndex:int = 0
+            while (crIndex < cellRegions.length)
+            {
+                var cr:CellRect = cellRegions[crIndex];
+                
+                // Handle the cases where the remove is before the cell region
+                // or in the cell region.
+                /*if (removeIndex < cr.x)
+                {
+                    cr.x--;
+                    selectionChanged = true;
+                }
+                else if (removeIndex >= cr.x && removeIndex < cr.right)
+                {
+                    _selectionLength = -1;  // recalculate
+                    selectionChanged = true;
+                    cr.width--;
+                    if (cr.width == 0)
+                    {
+                        cellRegions.splice(crIndex, 1);
+                        continue;
+                    }
+                }*/
+                crIndex++;
+            }
+        }  
+        
+        return selectionChanged;
+    }
+
+    /**
+     *  @private
+     *  The sort or filter on the collection changed. For columns, this is
+     *  the same as a "reset" event.
+     */
+    private function columnsCollectionRefresh(event:CollectionEvent):Boolean
+    {
+        return columnsCollectionReset(event);
+    }
+
+    /**
+     *  @private
+     *  The columns changed.  If the selectionMode is cell-based, don't preserve 
+     *  the selection.
+     */
+    private function columnsCollectionReset(event:CollectionEvent):Boolean
+    {
+        // If no selectionMode or a row-based selectionMode, nothing to do.
+        if (!isCellSelectionMode())
+            return false;
+
+        var selectionChanged:Boolean = removeSelection();        
+        return ensureRequiredSelection() || selectionChanged;
+    }
+}
+}
+
+// import flash.geom.Rectangle;
+import org.apache.royale.geom.Rectangle;
+/**
+ * @private
+ * A CellRect is a rectangle with one additional, isAdd property.
+ * A CellRect for a row is represented with columnIndex=0 and columnCount=1.
+ * 
+ * Mappings between Rectangle and selection cell regions:
+ *     y = rowIndex
+ *     x = columnIndex
+ *     height = rowCount
+ *     width = columnCount
+ */
+internal class CellRect extends Rectangle
+{
+    private var _isAdd:Boolean = false;
+	public function get isAdd():Boolean
+	{
+		return _isAdd;
+	}
+	
+	public function set isAdd(value:Boolean):void
+	{
+		_isAdd = value;
+	}                                         
+    // For a row, columnIndex=0 and columnCount=1.
+    public function CellRect(rowIndex:int, columnIndex:int, 
+                               rowCount:uint, columnCount:uint, isAdd:Boolean)
+    {
+        super(columnIndex, rowIndex, columnCount, rowCount);
+        this.isAdd = isAdd;
+    }
+    
+    public function containsCell(cellRowIndex:int, cellColumnIndex:int):Boolean
+    {
+        return contains(cellColumnIndex, cellRowIndex);
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSelectionMode.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSelectionMode.as
new file mode 100644
index 000000000..074b72be8
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSelectionMode.as
@@ -0,0 +1,122 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+
+/**
+ *  The GridSelectionMode class defines the valid constant values for the 
+ *  <code>selectionMode</code> property of the Spark DataGrid and Grid controls.
+ *  
+ *  <p>Use the constants in ActionsScript, as the following example shows: </p>
+ *  <pre>
+ *    myDG.selectionMode = GridSelectionMode.MULTIPLE_CELLS;
+ *  </pre>
+ *
+ *  <p>In MXML, use the String value of the constants, 
+ *  as the following example shows:</p>
+ *  <pre>
+ *    &lt;s:DataGrid id="myGrid" width="350" height="150"
+ *        selectionMode="multipleCells"&gt; 
+ *        ...
+ *    &lt;/s:DataGrid&gt; 
+ *  </pre>
+ * 
+ *  @see spark.components.DataGrid#selectionMode
+ *  @see spark.components.Grid#selectionMode
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5
+ */
+public final class GridSelectionMode
+{
+    
+    /**
+     *  Constructor.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function GridSelectionMode()
+    {
+        super();
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Class constants
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Specifies that no selection is allowed.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public static const NONE:String = "none";
+
+    /**
+     *  Specifies that one row can be selected.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public static const SINGLE_ROW:String = "singleRow";
+
+    /**
+     *  Specifies that one or more rows can be selected.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public static const MULTIPLE_ROWS:String = "multipleRows";
+
+    /**
+     *  Specifies that one cell can be selected.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public static const SINGLE_CELL:String = "singleCell";
+
+    /**
+     *  Specifies that one or more cells can be selected.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public static const MULTIPLE_CELLS:String = "multipleCells";
+    
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSortFieldComplex.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSortFieldComplex.as
new file mode 100644
index 000000000..a8f54f269
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSortFieldComplex.as
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses {
+
+    import spark.collections.ComplexSortField;
+    import mx.utils.ObjectUtil;
+
+    [ExcludeClass]
+
+    /**
+     *  A subclass of SortField used by DataGrid and GridColumn to keep track
+     *  of complex dataFields when trying to reverse the sort.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public class GridSortFieldComplex extends ComplexSortField {
+        private var _column:GridColumn;
+
+        /**
+         *  Constructor.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 10
+         *  @playerversion AIR 2.5
+         *  @productversion Flex 4.5
+         */
+
+        public function GridSortFieldComplex(column:GridColumn, name:String = null, descending:Boolean = false, numeric:Object = null, sortCompareType:String = null, customCompareFunction:Function = null)
+        {
+            _column = column;
+            super(name, descending, numeric, sortCompareType, customCompareFunction);
+        }
+
+
+        override protected function getSortFieldValue(obj:Object):*
+        {
+            var unformattedValue:* = ObjectUtil.getValue(obj, nameParts);
+            return column && column.formatter ? column.formatter.format(unformattedValue) : unformattedValue;
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        //  Properties
+        //
+        //--------------------------------------------------------------------------
+
+        public function get column():GridColumn
+        {
+            return _column;
+        }
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSortFieldSimple.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSortFieldSimple.as
new file mode 100644
index 000000000..72290b510
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridSortFieldSimple.as
@@ -0,0 +1,45 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses {
+    import mx.utils.ObjectUtil;
+
+    import spark.collections.SortField;
+
+    public class GridSortFieldSimple extends SortField {
+        private var _column:GridColumn;
+
+        public function GridSortFieldSimple(column:GridColumn, name:String = null, descending:Boolean = false, numeric:Object = null, sortCompareType:String = null, customCompareFunction:Function = null)
+        {
+            _column = column;
+            super(name, descending, numeric, sortCompareType, customCompareFunction);
+        }
+
+        public function get column():GridColumn
+        {
+            return _column;
+        }
+
+        override protected function getSortFieldValue(obj:Object):*
+        {
+            var unformattedValue:* = ObjectUtil.getValue(obj, [name]);
+            return column && column.formatter ? column.formatter.format(unformattedValue) : unformattedValue;
+        }
+    }
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridView.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridView.as
new file mode 100644
index 000000000..38207363b
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/GridView.as
@@ -0,0 +1,170 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+/*
+import flash.events.Event;
+import flash.events.MouseEvent;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+*/
+	
+import org.apache.royale.events.Event;
+import mx.events.MouseEvent;
+import org.apache.royale.geom.Point;
+import org.apache.royale.geom.Rectangle;
+
+import mx.collections.IList;
+import mx.core.LayoutDirection;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+import mx.events.PropertyChangeEvent;
+
+import spark.collections.SubListView;
+import spark.components.Grid;
+import spark.components.Group;
+
+use namespace mx_internal;
+
+/**
+ *  This class is internal to the DataGrid implementation.
+ * 
+ *  A Grid element (child) that displays a rectangular region within the Grid.   
+ *  The GridView's region is defined by four GridViewLayout properties: viewRowIndex and 
+ *  viewColumnIndex - the origin of the region, viewRowCount and viewColumnCount - the size 
+ *  of the region.  The GridView contains GridLayers which contain all of the Grid's visual
+ *  elements, the renderers, indicators, separators, etc.
+ * 
+ *  GridViews are created automatically by the Grid class, based on the values of 
+ *  the lockedRowCount and lockedColumnCount Grid properties.
+ */
+public class GridView extends Group
+{
+    private static const zeroPoint:Point = new Point(0, 0);
+    
+    /**
+     *  Creates a GridView group with its layout set to a private GridView specific value.
+     */
+    public function GridView()
+    {
+        super();
+        // layout = new GridViewLayout();
+        // layout.clipAndEnableScrolling = true;
+    }
+    
+    /**
+     *  Return this GridView's GridViewLayout.
+     */
+	/*
+    public function get gridViewLayout():GridViewLayout
+    {
+        return layout as GridViewLayout;
+    }    
+    */
+    /**
+     *  True if this GridView's bounds contain the event.
+     * 
+     *  Currently this method does not account for the possibility that this GridView has been
+     *  rotated or scaled.
+     */
+    public function containsMouseEvent(event:MouseEvent):Boolean
+    {
+        const eventStageX:Number = event.stageX;
+        const eventStageY:Number = event.stageY;
+        const origin:Point = null; //localToGlobal(zeroPoint);
+
+        origin.x += horizontalScrollPosition;
+       /* if (layoutDirection == LayoutDirection.RTL)
+            origin.x -= width;*/
+
+        origin.y += verticalScrollPosition;
+        
+        return (eventStageX >= origin.x) && (eventStageY >= origin.y) && 
+            (eventStageX < (origin.x + width)) && (eventStageY < (origin.y + height));
+    }
+    
+    /**
+     *  Returns the view-relative index of the next GridColumn.visible==true column
+     *  after index.
+     *  Returns -1 if there are no more visible columns.
+     *  To find the first GridColumn.visible==true column index, use
+     *  getNextVisibleColumnIndex(-1).
+     */
+    public function getNextVisibleColumnIndex(index:int=-1):int
+    {
+        if (index < -1)
+            return -1;
+        /*
+        const columnsView:SubListView = this.gridViewLayout.columnsView;
+        const columnsLength:int = (columnsView) ? columnsView.length : 0;
+        
+        for (var i:int = index + 1; i < columnsLength; i++)
+        {
+            var column:GridColumn = columnsView.getItemAt(i) as GridColumn;
+            if (column && column.visible)
+                return i;
+        }
+		*/        
+        return -1;
+    }
+    
+    /**
+     *  Returns the view-relative index of the previous GridColumn.visible==true column
+     *  before index.
+     *  Returns -1 if there are no more visible columns.
+     *  To find the last GridColumn.visible==true column index, use
+     *  getPreviousVisibleColumnIndex(columns.length).
+     */
+    public function getPreviousVisibleColumnIndex(index:int):int
+    {
+        /*const columnsView:SubListView = this.gridViewLayout.columnsView;
+        if (!columnsView || index > columnsView.length)
+            return -1;
+        
+        for (var i:int = index - 1; i >= 0; i--)
+        {
+            var column:GridColumn = columnsView.getItemAt(i) as GridColumn;
+            if (column && column.visible)
+                return i;
+        }*/
+        
+        return -1;
+    }    
+    
+    /**
+     *  @private 
+     */
+    override protected function dispatchPropertyChangeEvent(property:String, oldValue:*, newValue:*):void    
+    {
+        switch(property) 
+        {
+            case "contentWidth": 
+            case "contentHeight":
+                const grid:Grid = parent as Grid;
+                if (grid)
+                {
+                    const pce:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(grid, property, null, null);
+                    grid.dispatchEvent(pce);
+                }
+                break;
+        }
+    }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/IDataGridElement.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/IDataGridElement.as
new file mode 100644
index 000000000..4006172c1
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/IDataGridElement.as
@@ -0,0 +1,58 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+import mx.core.IInvalidating;
+import mx.core.IVisualElement;
+import mx.managers.ILayoutManagerClient;
+
+// import spark.components.DataGrid;
+import mx.controls.DataGrid;
+
+/**
+ *  Visual elements of the Spark DataGrid control that must 
+ *  remain in sync with the grid's layout and scroll
+ *  position must implement this interface.   
+ *  When the DataGrid control's <code>grid</code> skin part is added, 
+ *  it sets the <code>IDataGridElement.dataGrid</code> property. 
+ *  The IDataGridElements object can respond by adding event listeners 
+ *  for scroll position changes.  
+ *  When the DataGrid control is changed in a way that affects 
+ *  its row or column layout, all IDataGridElements object are invalidated.
+ * 
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5 
+ */
+public interface IDataGridElement extends IVisualElement, ILayoutManagerClient, IInvalidating
+{
+    /**
+     *  The DataGrid control associated with this element.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get dataGrid():DataGrid;
+    function set dataGrid(value:DataGrid):void;        
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/IGridItemRenderer.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/IGridItemRenderer.as
new file mode 100644
index 000000000..0676801c3
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/gridClasses/IGridItemRenderer.as
@@ -0,0 +1,260 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.gridClasses
+{
+import mx.core.IDataRenderer;
+import mx.core.IVisualElement;
+
+import spark.components.Grid;
+    
+/**
+ *  The IGridItemRenderer interface must be implemented by DataGrid item renderers.  The
+ *  DataGrid uses this API to provide the item renderer with the information needed to 
+ *  render one grid or header <i>cell</i>.  
+ *
+ *  <p>All of the renderer's properties are set during the execution of its parent's 
+ *  <code>updateDisplayList()</code> method.  After the properties have been set, the 
+ *  item renderer's <code>prepare()</code> method is called.  
+ *  An IGridItemRenderer implementation should override the <code>prepare()</code> method 
+ *  to make any final adjustments to its properties or any aspect of its visual elements.
+ *  Typically, the <code>prepare()</code> is used to configure the renderer's visual
+ *  elements based on the <code>data</code> property.</p>
+ * 
+ *  <p>When an item renderer is no longer needed, either because it's going to be added 
+ *  to an internal reusable renderer "free" list, or because it's never going to be 
+ *  used again, the IGridItemRenderer <code>discard()</code> method is called.</p> 
+ * 
+ *  @see spark.components.DataGrid
+ *  @see spark.components.Grid
+ * 
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5 
+ */
+public interface IGridItemRenderer extends IDataRenderer, IVisualElement
+{
+    /**
+     *  The Grid associated with this item renderer, typically just the value of
+     *  <code>column.grid</code>.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get grid():Grid;
+    
+    /**
+     *  The zero-based index of the row of the cell being rendered.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get rowIndex():int;
+    function set rowIndex(value:int):void;
+    
+    /**
+     *  This property is set to <code>true</code> when one of two input gestures occurs within a 
+     *  grid cell:  either the mouse button or the touch screen is pressed.   
+     *  The <code>down</code> property is reset to <code>false</code> when 
+     *  the mouse button goes up, the user lifts off 
+     *  the touch screen, or the mouse/touch is dragged out of the grid cell.   
+     * 
+     *  <p>Unlike a List item renderer, grid item renderers do not have exclusive
+     *  responsibility for displaying the down indicator.  The Grid itself
+     *  renders the down indicator for the selected row or cell. 
+     *  The item renderer can also change its visual properties to emphasize
+     *  that it's being pressed.</p>   
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get down():Boolean;
+    function set down(value:Boolean):void;
+    
+    /**
+     *  Contains <code>true</code> if the item renderer is being dragged, 
+     *  typically as part of a drag and drop operation.
+     *  Currently, drag and drop is not supported by the Spark DataGrid control.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get dragging():Boolean;
+    function set dragging(value:Boolean):void;
+    
+    /**
+     *  Contains <code>true</code> if the item renderer is under the mouse and 
+     *  the Grid's selectionMode is <code>GridSelectionMode.SINGLE_CELL</code> or
+     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, or if the mouse is within the 
+     *  row the item renderer belongs to and the Grid's selectionMode is 
+     *  <code>GridSelectionMode.SINGLE_ROW</code> or 
+     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>.
+     * 
+     *  <p>Unlike a List item renderer, grid item renderers do not have exclusive
+     *  responsibility for displaying something to indicate that the renderer 
+     *  or its row is under the mouse.  The Grid itself automatically displays the
+     *  hoverIndicator skin part for the hovered row or cell.  Grid item renderers 
+     *  can also change their properties to emphasize that they're hovered.</p>
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get hovered():Boolean;
+    function set hovered(value:Boolean):void;
+    
+    /**
+     *  The String to display in the item renderer.  
+     * 
+     *  <p>The GridItemRenderer class automatically copies the 
+     *  value of this property to the <code>text</code> property 
+     *  of its <code>labelDisplay</code> element, if that element was specified. 
+     *  The Grid sets the <code>label</code> to the value returned by the column's 
+     *  <code>itemToLabel()</code> method.</p>
+     *
+     *  @see spark.components.gridClasses.GridItemRenderer
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get label():String;
+    function set label(value:String):void;
+    
+    /**
+     *  Contains <code>true</code> if the item renderer's cell is part 
+     *  of the current selection.
+     * 
+     *  <p> Unlike a List item renderer, 
+     *  grid item renderers do not have exclusive responsibility for displaying 
+     *  something to indicate that they're part of the selection.  The Grid 
+     *  itself automatically displays the selectionIndicator skin part for the 
+     *  selected rows or cells.  The item renderer can also change its visual properties 
+     *  to emphasize that it's part of the selection.</p>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get selected():Boolean;
+    function set selected(value:Boolean):void;
+    
+    /**
+     *  Contains <code>true</code> if the item renderer's cell is indicated by the caret.
+     * 
+     *  <p> Unlike a List item renderer, grid item renderers do not have exclusive 
+     *  responsibility for displaying something to indicate their cell or row has
+     *  the caret.  The Grid itself automatically displays the caretIndicator skin part for the 
+     *  caret row or cell.  The item renderer can also change its visual properties 
+     *  to emphasize that it has the caret.</p>
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    function get showsCaret():Boolean;
+    function set showsCaret(value:Boolean):void;    
+    
+    /**
+     *  The GridColumn object representing the column associated with this item renderer.  
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5 
+     */
+    // function get column():GridColumn;
+    // function set column(value:GridColumn):void;
+    
+    /**
+     *  The column index for this item renderer's cell.  
+     *  This is the same value as <code>column.columnIndex</code>.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5 
+     */
+    function get columnIndex():int;    
+    
+    /**
+     *  Called from the item renderer parent's <code>updateDisplayList()</code> method 
+     *  after all of the renderer's properties have been set.  
+     *  The <code>hasBeenRecycled</code> parameter is <code>false</code>
+     *  if this renderer has not been used before, meaning it was not recycled.  
+     *  This method is called when a renderer is about to become visible 
+     *  and each time it's redisplayed because of a change in a renderer
+     *  property, or because a redisplay was explicitly requested. 
+     * 
+     *  <p>This method can be used to configure all of a renderer's visual 
+     *  elements and properties.
+     *  Using this method can be more efficient than binding <code>data</code>
+     *  properties to visual element properties.  
+     *  Note: Because the <code>prepare()</code> method is called frequently, 
+     *  make sure that it is coded efficiently.</p>
+     *
+     *  <p>The <code>prepare()</code> method may be called many times 
+     *  before the <code>discard()</code> method is called.</p>
+     * 
+     *  <p>This method is not intended to be called directly.
+     *  It is called by the DataGrid implementation.</p>
+     * 
+     *  @param hasBeenRecycled  <code>true</code> if this renderer is being reused.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5 
+     */
+    function prepare(hasBeenRecycled:Boolean):void;
+        
+    /**
+     *  Called from the item renderer parent's <code>updateDisplayList()</code> method 
+     *  when it has been determined that this renderer will no longer be visible.   
+     *  If the <code>willBeRecycled</code> parameter is <code>true</code>, 
+     *  then the owner adds this renderer to its internal free list for reuse.  
+     *  Implementations can use this method to clear any renderer properties that are no longer needed.
+     * 
+     *  <p>This method is not intended to be called directly.
+     *  It is called by the DataGrid implementation.</p>
+     * 
+     *  @param willBeRecycled <code>true</code> if this renderer is going to be added 
+     *  to the owner's internal free list for reuse.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5  
+     */
+    function discard(willBeRecycled:Boolean):void;
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/GroupBase.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/GroupBase.as
index 51aa21ed5..f58cd50ce 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/GroupBase.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/GroupBase.as
@@ -33,6 +33,8 @@ package spark.components.supportClasses
 //import flash.geom.Rectangle;
 
 //import mx.core.ILayoutElement;
+import org.apache.royale.geom.Point;
+	
 import mx.core.IUIComponent;
 import mx.core.IVisualElement;
 import mx.core.UIComponent;
@@ -50,8 +52,8 @@ import org.apache.royale.core.ILayoutParent;
 import org.apache.royale.core.ValuesManager;
 import org.apache.royale.events.Event;
 import org.apache.royale.utils.MXMLDataInterpreter;
-import org.apache.royale.utils.loadBeadFromValuesManager;
-
+import org.apache.royale.utils.loadBeadFromValuesManager;
+
 //import spark.utils.FTETextUtil;
 //import spark.utils.MaskUtil;
 
@@ -1464,8 +1466,9 @@ public class GroupBase extends UIComponent implements ILayoutParent
     /**
      *  @private 
      */ 
-    /* override public function globalToLocal(point:Point):Point
+    override public function globalToLocal(point:Point):Point
     {
+		/*
         if (resizeMode == ResizeMode.SCALE && _layoutFeatures != null)
         {
             // If resize mode is scale, then globalToLocal shouldn't account for 
@@ -1474,14 +1477,14 @@ public class GroupBase extends UIComponent implements ILayoutParent
             var sY:Number = _layoutFeatures.stretchY;
             _layoutFeatures.stretchX = 1;
             _layoutFeatures.stretchY = 1;
-            applyComputedMatrix();
+            //applyComputedMatrix();
             
             var p:Point = super.globalToLocal(point);
             
             // Restore stretch
             _layoutFeatures.stretchX = sX;
             _layoutFeatures.stretchY = sY;
-            applyComputedMatrix();
+            //applyComputedMatrix();
             
             return p;
         }
@@ -1489,7 +1492,9 @@ public class GroupBase extends UIComponent implements ILayoutParent
         {
             return super.globalToLocal(point);    
         }
-    } */
+		*/
+		return null;
+    }
     
     /**
      *  @private 
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/IDataProviderEnhance.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/IDataProviderEnhance.as
new file mode 100644
index 000000000..ae3918a62
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/IDataProviderEnhance.as
@@ -0,0 +1,162 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.supportClasses
+{
+
+    // import flash.events.IEventDispatcher;
+	import org.apache.royale.events.IEventDispatcher;
+    import mx.collections.IList;
+    import spark.components.supportClasses.RegExPatterns;
+
+
+    /**
+    *  Adds functionality to list driven components.
+    *
+    *  @langversion 3.0
+    *  @playerversion Flash 11.1
+    *  @playerversion AIR 3.4
+    *  @productversion Flex 4.10
+    */
+    public interface IDataProviderEnhance extends IEventDispatcher
+    {
+        //--------------------------------------------------------------------------------
+        //
+        //  Variables
+        //
+        //--------------------------------------------------------------------------------
+
+
+        //--------------------------------------------------------------------------------
+        //
+        //  Getters / Setters
+        //
+        //--------------------------------------------------------------------------------
+
+        /**
+        *  Returns if the selectedIndex is equal to the first row.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        function get isFirstRow():Boolean;
+
+
+        /**
+        *  Returns if the selectedIndex is equal to the last row.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        function get isLastRow():Boolean;
+
+
+        //--------------------------------------------------------------------------------
+        //
+        //  Methods
+        //
+        //--------------------------------------------------------------------------------
+
+        /**
+        *  This will search through a dataprovider checking the given field and for the given value and return the index for the match.
+        *  It can start the find from a given startingIndex;
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        function findRowIndex(field:String, value:String, startingIndex:int = 0, patternType:String = RegExPatterns.EXACT):int;
+
+
+        /**
+        *  This will search through a dataprovider checking the given field and for the given values and return an array of indexes that matched.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        function findRowIndices(field:String, values:Array, patternType:String = RegExPatterns.EXACT):Array;
+
+
+        /**
+        *  Changes the selectedIndex to the first row of the dataProvider.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        function moveIndexFirstRow():void;
+
+
+        /**
+        *  Changes the selectedIndex to the last row of the dataProvider.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        function moveIndexLastRow():void;
+
+
+        /**
+        *  Changes the selectedIndex to the next row of the dataProvider.  If there isn't a current selectedIndex, it silently returns.
+        *  If the selectedIndex is on the first row, it does not wrap around.  However the <code>isFirstRow</code> property returns true.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        function moveIndexNextRow():void;
+
+
+        /**
+        *  Changes the selectedIndex to the previous row of the dataProvider.  If there isn't a current selectedIndex, it silently returns.
+        *  If the selectedIndex is on the last row, it does not wrap around.  However the <code>isLastRow</code> property returns true.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        function moveIndexPreviousRow():void;
+
+
+        /**
+        *  This will search through a dataprovider checking the given field and will set the selectedIndex to a matching value.
+        *  It can start the search from the startingIndex;
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        *
+        */
+        function moveIndexFindRow(field:String, value:String, startingIndex:int = 0, patternType:String = RegExPatterns.EXACT):Boolean;
+
+    }
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/RegExPatterns.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/RegExPatterns.as
new file mode 100644
index 000000000..5a3a429e0
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/RegExPatterns.as
@@ -0,0 +1,221 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components.supportClasses
+{
+    /**
+    *  This provides a means to standardize certain common regex patterns and functionality.
+    *  
+    *  <p>Use the constants in ActionsScript, as the following example shows: </p>
+    *  <pre>
+    *    createRegExp("my search value", RegExPatterns.CONTAINS):RegExp
+    *  </pre>
+    *  
+    *  @langversion 3.0
+    *  @playerversion Flash 11.1
+    *  @playerversion AIR 3.4
+    *  @productversion Flex 4.10
+    */
+    public final class RegExPatterns
+    {
+        /**
+        *  Constructor.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public function RegExPatterns()
+        {
+        }
+
+
+        //--------------------------------------------------------------------------------
+        //
+        //  Static Const Variables
+        //
+        //--------------------------------------------------------------------------------
+
+        /**
+        *  Specifies the use of a regex pattern matching the end with a given value.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const CONTAINS:String = "contains";
+
+
+        /**
+        *  Specifies the use of a regex pattern matching the end with a given value.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const ENDS_WITH:String = "endsWith";
+
+
+        /**
+        *  Specifies the use of a regex pattern matching exacly to a given value.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const EXACT:String = "exact";
+
+
+        /**
+        *  Specifies the use of a regex pattern match that does not contain a given value.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const NOT:String = "not";
+
+
+        /**
+        *  Specifies the use of a regex pattern match that specifies must have at least 1 character matching.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const NOT_EMPTY:String = "notEmpty";
+
+
+        /**
+        *  Specifies the use of a regex pattern matching the beginging with a given value.
+        * 
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        public static const STARTS_WITH:String = "startsWith";
+
+
+        //--------------------------------------------------------------------------------
+        //
+        //  Static Methods
+        //
+        //--------------------------------------------------------------------------------
+
+        /**
+        *  Creates a new RegEx pattern based on a given value and a selected pattern Type.
+        *
+        *  @param patternValue Is the value that will be assembled into the RegEx type.
+        *  @param patternType Is the type of regen pattern matching to be performed.
+        *
+        *  @return Returns a <code>RegExp</code> with a formatted RegEx pattern.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        static public function createRegExp(patternValue:String, patternType:String = CONTAINS):RegExp
+        {
+            return new RegExp(createPatternString(patternValue, patternType), "i");
+        }
+
+
+        /**
+        *  Creates a new string based RegEx pattern based on a given value and a selected pattern Type.
+        *
+        *  @param patternValue Is the value that will be assembled into the RegEx type.
+        *  @param patternType Is the type of regen pattern matching to be performed.
+        *
+        *  @return Returns a string with a formatted RegEx pattern.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 11.1
+        *  @playerversion AIR 3.4
+        *  @productversion Flex 4.10
+        */
+        static public function createPatternString(patternValue:String, patternType:String = CONTAINS):String
+        {
+            var combinedPattern:String = "";
+
+            switch (patternType)
+            {
+                case ENDS_WITH:
+                {
+                    combinedPattern = "" + patternValue + "$";
+
+                    break;
+                }
+
+
+                case EXACT:
+                {
+                    combinedPattern = "^" + patternValue + "$";
+
+                    break;
+                }
+
+
+                case NOT:
+                {
+                    combinedPattern = "^((?!" + patternValue + ").)*$";
+
+                    break;
+                }
+
+
+                case NOT_EMPTY:
+                {
+                    combinedPattern = "^." + patternValue + "{1,}$";
+
+                    break;
+                }
+
+
+                case STARTS_WITH:
+                {
+                    combinedPattern = "^" + patternValue + "";
+
+                    break;
+                }
+
+
+                //Default pattern will be contains to catch all invalid patternTypes.
+                case CONTAINS:
+                default:
+                {
+                    combinedPattern = "" + patternValue + "";
+
+                    break;
+                }
+            }
+
+
+            return combinedPattern;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/events/GridCaretEvent.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/events/GridCaretEvent.as
new file mode 100644
index 000000000..4cb0ea19f
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/events/GridCaretEvent.as
@@ -0,0 +1,306 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.events
+{
+
+// import flash.events.Event;
+import org.apache.royale.events.Event;
+
+/**
+ *  The GridCaretEvent class represents events that are dispatched when 
+ *  the caret changes in a Spark DataGrid control as the result of 
+ *  user interaction.
+ *
+ *  @see spark.components.DataGrid
+ *  @see spark.components.Grid
+ *  @see spark.components.gridClasses.GridSelectionMode
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5
+ */
+public class GridCaretEvent extends Event
+{
+    // include "../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class constants
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  The <code>GridSelectionEvent.CARET_CHANGE</code> constant defines 
+     *  the value of the <code>type</code> property of the event object for a 
+     *  <code>caretChange</code> event, which indicates that the current 
+     *  caret position has just been changed.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>newColumnIndex</code></td><td>The zero-based column 
+     *       index of the caret position after it was changed.  It is -1 if
+     *       the <code>selectionMode</code> is row-based.</td></tr>
+     *     <tr><td><code>newRowIndex</code></td><td>The zero-based row index 
+     *       of the caret position after it was changed.</td></tr>
+     *     <tr><td><code>oldColumnIndex</code></td><td>The zero-based column 
+     *       index of the caret position before it was changed.  It is -1 if
+     *       the <code>selectionMode</code> is row-based.</td></tr>
+     *     <tr><td><code>oldRowIndex</code></td><td>The zero-based row index 
+     *       of the caret position before it was changed.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *       it is not always the Object listening for the event. 
+     *       Use the <code>currentTarget</code> property to always access the 
+     *       Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdCaretEvent.CARET_CHANGE</td></tr>
+     *  </table>
+     *   
+     *  @eventType caretChange
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public static const CARET_CHANGE:String = "caretChange";
+        
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  @param type The event type; indicates the action that caused the event.
+     *
+     *  @param bubbles Specifies whether the event can bubble
+     *  up the display list hierarchy.
+     *
+     *  @param cancelable Specifies whether the behavior
+     *  associated with the event can be prevented.
+     *
+     *  @param oldColumnIndex The zero-based column index of the caret position
+     *  before the change.  If the <code>selectionMode</code> is either 
+     *  <code>SelectionMode.SINGLE_ROW</code> or 
+     *  <code>SelectionMode.MULTIPLE_ROWS</code>, this is -1.
+     * 
+     *  @param oldRowIndex The zero-based row index of the caret position before 
+     *  the change.
+     * 
+     *  @param newColumnIndex The zero-based column index of the caret position
+     *  after the change.  If the <code>selectionMode</code> is either 
+     *  <code>SelectionMode.SINGLE_ROW</code> or 
+     *  <code>SelectionMode.MULTIPLE_ROWS</code>, this is -1.
+     * 
+     *  @param newRowIndex The zero-based row index of the caret position after 
+     *  the change.
+     * 
+     *  @see spark.components.DataGrid#columns
+     *  @see spark.components.DataGrid#dataProvider
+     *  @spark.events.GridSelectionEventKind
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function GridCaretEvent(type:String, 
+                                       bubbles:Boolean = false,
+                                       cancelable:Boolean = false,
+                                       oldRowIndex:int = -1,
+                                       oldColumnIndex:int = -1,
+                                       newRowIndex:int = -1,
+                                       newColumnIndex:int = -1)
+     {
+        super(type, bubbles, cancelable);
+
+        this.oldRowIndex = oldRowIndex;
+        this.oldColumnIndex = oldColumnIndex;
+        this.newRowIndex = newRowIndex;
+        this.newColumnIndex = newColumnIndex;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Properties
+    //
+    //--------------------------------------------------------------------------
+       
+    
+    //----------------------------------
+    //  oldRowIndex
+    //----------------------------------
+
+    /**
+     *  The zero-based index of the row of the
+     *  caret position before it was changed.
+     * 
+     *  @default -1
+     * 
+     *  @see spark.components.DataGrid#dataProvider
+     *  @see spark.components.Grid#dataProvider
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    private var _oldRowIndex:int;
+	public function get oldRowIndex():int
+	{
+		return _oldRowIndex;
+	}
+	
+	public function set oldRowIndex(value:int):void
+	{
+		_oldRowIndex = value;
+	}
+    //----------------------------------
+    //  oldColumnIndex
+    //----------------------------------
+    
+    /**
+     *  The zero-based index of the column of the
+     *  caret position before it was changed.      
+     * 
+     *  <p>If the <code>selectionMode</code> is <code>SelectionMode.SINGLE_ROW</code> or 
+     *  <code>SelectionMode.MULTIPLE_ROWS</code>, this valueis -1 to indicate
+     *  it is not being used.</p>
+     *  
+     *  @see spark.components.DataGrid#columns
+     *  @see spark.components.Grid#columns
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    private var _oldColumnIndex:int;
+	public function get oldColumnIndex():int
+	{
+		return _oldColumnIndex;
+	}
+	
+	public function set oldColumnIndex(value:int):void
+	{
+		_oldColumnIndex = value;
+	}
+    //----------------------------------
+    //  newRowIndex
+    //----------------------------------
+    
+    /**
+     *  The zero-based index of the row of the
+     *  caret position after it was changed.
+     * 
+     *  @see spark.components.DataGrid#dataProvider
+     *  @see spark.components.Grid#dataProvider
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    private var _newRowIndex:int;
+	public function get newRowIndex():int
+	{
+		return _newRowIndex;
+	}
+	
+	public function set newRowIndex(value:int):void
+	{
+		_newRowIndex = value;
+	}
+    //----------------------------------
+    //  newColumnIndex
+    //----------------------------------
+    
+    /**
+     *  The zero-based index of the column of the
+     *  caret position after it was changed.  
+     * 
+     *  <p>If the <code>selectionMode</code> is <code>SelectionMode.SINGLE_ROW</code> or 
+     *  <code>SelectionMode.MULTIPLE_ROWS</code> this will be -1 to indicate
+     *  it is not being used.</p>
+     *  
+     *  @see spark.components.DataGrid#columns
+     *  @see spark.components.Grid#columns
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    private var _newColumnIndex:int;    
+	public function get newColumnIndex():int
+	{
+		return _newColumnIndex;
+	}
+	
+	public function set newColumnIndex(value:int):void
+	{
+		_newColumnIndex = value;
+	}
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: Object
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     */
+    /*override public function toString():String
+    {
+        return formatToString(
+            "GridCaretEvent", "type", 
+            "bubbles", "cancelable", "eventPhase",
+            "oldRowIndex","oldColumnIndex", 
+            "newRowIndex", "newColumnIndex");
+    }*/
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: Event
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    /*override public function clone():Event
+    {
+        return new GridCaretEvent(
+            type, bubbles, cancelable, 
+            oldRowIndex, oldColumnIndex, 
+            newRowIndex, newColumnIndex);
+    }*/
+}
+
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/events/GridEvent.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/events/GridEvent.as
new file mode 100644
index 000000000..17f8691ba
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/events/GridEvent.as
@@ -0,0 +1,896 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.events
+{
+// import flash.display.InteractiveObject;
+// import flash.events.Event;
+// import flash.events.MouseEvent;
+import org.apache.royale.events.Event;
+import org.apache.royale.events.MouseEvent;
+
+import spark.components.Grid;
+import spark.components.gridClasses.GridColumn;
+import spark.components.gridClasses.IDataGridElement;
+import spark.components.gridClasses.IGridItemRenderer;
+
+/**
+ *  The GridEvent class extends the MouseEvent class to includes additional 
+ *  grid specific information based on the event's location relative to a grid cell.
+ *  This information includes the following:
+ *
+ *  <ul>
+ *    <li>The row and column index of the cell.</li>
+ *    <li>The GridColumn object of the cell.</li>
+ *    <li>The data provider item that corresponds to the row of the cell.</li>
+ *    <li>The item renderer.</li>  
+ *  </ul>
+ * 
+ *  <p>Grid events have a one-to-one correspondence with mouse events.  
+ *  They are dispatched in response to mouse events that have "bubbled" 
+ *  from some Grid descendant to the Grid itself.   
+ *  One significant difference is that event listeners for grid events 
+ *  are guaranteed to see an entire down-drag-up mouse gesture, 
+ *  even if the drag and up parts of the gesture do not occur over the grid.   
+ *  The <code>gridMouseDrag</code> event corresponds to a 
+ *  mouse move event with the button held down.</p> 
+ * 
+ *  @see spark.components.DataGrid
+ *  @see spark.components.Grid
+ *  @see spark.components.gridClasses.GridSelectionMode
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5
+ */
+public class GridEvent extends MouseEvent
+{
+    // include "../core/Version.as";    
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Class constants
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>gridMouseDown</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.GRID_MOUSE_DOWN</td></tr>
+     *  </table>
+     *
+     *  @eventType gridMouseDown
+     * 
+     *  @see flash.display.InteractiveObject#event:mouseDown
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public static const GRID_MOUSE_DOWN:String = "gridMouseDown";
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>gridMouseDrag</code> GridEvent.  
+     *  This event is only dispatched when a listener has handled a <code>mouseDown</code> event, 
+     *  and then only while the mouse moves with the button held down.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.GRID_MOUSE_DRAG</td></tr>
+     *  </table>
+     *
+     *  @eventType gridMouseDrag
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public static const GRID_MOUSE_DRAG:String = "gridMouseDrag";        
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>gridMouseUp</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.GRID_MOUSE_UP</td></tr>
+     *  </table>
+     *
+     *  @eventType gridMouseUp
+     * 
+     *  @see flash.display.InteractiveObject#event:mouseUp
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public static const GRID_MOUSE_UP:String = "gridMouseUp";
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>gridClick</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.GRID_CLICK</td></tr>
+     *  </table>
+     *
+     *  @eventType gridClick
+     * 
+     *  @see flash.display.InteractiveObject#event:click
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public static const GRID_CLICK:String = "gridClick";
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>gridDoubleClick</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.GRID_DOUBLE_CLICK</td></tr>
+     *  </table>
+     *
+     *  @eventType gridDoubleClick
+     * 
+     *  @see flash.display.InteractiveObject#event:doubleClick
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public static const GRID_DOUBLE_CLICK:String = "gridDoubleClick";     
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>gridRollOver</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.GRID_ROLL_OVER</td></tr>
+     *  </table>
+     *
+     *  @eventType gridRollOver
+     * 
+     *  @see flash.display.InteractiveObject#event:rollOver
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public static const GRID_ROLL_OVER:String = "gridRollOver";
+
+    /**
+     *  The value of the <code>type</code> property for a <code>gridRollOut</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.GRID_ROLL_OUT</td></tr>
+     *  </table>
+     *
+     *  @eventType gridRollOut
+     * 
+     *  @see flash.display.InteractiveObject#event:rollOut
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */    
+    public static const GRID_ROLL_OUT:String = "gridRollOut";
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>separatorMouseDrag</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.SEPARATOR_MOUSE_DRAG</td></tr>
+     *  </table>
+     *
+     *  @eventType separatorMouseDrag
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */  
+    public static const SEPARATOR_MOUSE_DRAG:String = "separatorMouseDrag";
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>separatorClick</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.SEPARATOR_CLICK</td></tr>
+     *  </table>
+     *
+     *  @eventType separatorClick
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */      
+    public static const SEPARATOR_CLICK:String = "separatorClick";
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>separatorDoubleClick</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.SEPARATOR_DOUBLE_CLICK</td></tr>
+     *  </table>
+     *
+     *  @eventType separatorDoubleClick
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */      
+    public static const SEPARATOR_DOUBLE_CLICK:String = "separatorDoubleClick";    
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>separatorMouseDown</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>
+     *     <tr><td><code>type</code></td><td>GirdEvent.SEPARATOR_MOUSE_DOWN</td></tr>
+     *  </table>
+     *
+     *  @eventType separatorMouseDown
+     * 
+     *  @see flash.display.InteractiveObject#event:rollOut
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */  
+    public static const SEPARATOR_MOUSE_DOWN:String = "separatorMouseDown";
+    
+    /**
+     *  The value of the <code>type</code> property for a <code>separatorMouseUp</code> GridEvent.
+     *
+     *  <p>The properties of the event object have the following values:</p>
+     *  <table class="innertable">
+     *     <tr><th>Property</th><th>Value</th></tr>
+     *     <tr><td><code>bubbles</code></td><td>false</td></tr>
+     *     <tr><td><code>cancelable</code></td><td>false</td></tr>
+     *     <tr><td><code>currentTarget</code></td><td>The Object that defines the 
+     *       event listener that handles the event. For example, if you use 
+     *       <code>myButton.addEventListener()</code> to register an event listener, 
+     *       myButton is the value of the <code>currentTarget</code>. </td></tr>
+     *     <tr><td><code>column</code></td><td>The column where the event occurred, 
+     *        or null if the event did not occur over a column.</td></tr>
+     *     <tr><td><code>columnIndex</code></td><td>The index of the column where 
+     *        the event occurred, or -1 if the event did not occur over a grid column.</td></tr>
+     *     <tr><td><code>grid</code></td><td>The Grid associated with this event.</td></tr>
+     *     <tr><td><code>item</code></td><td>The data provider item for this row, 
+     *        or null if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>itemRenderer</code></td><td>The The item renderer that displayed 
+     *       this cell, or null if the event did not occur over a visible cell.</td></tr>
+     *     <tr><td><code>rowIndex</code></td><td>The index of the row where the event occurred, 
+     *        or -1 if the event did not occur over a grid row.</td></tr>
+     *     <tr><td><code>target</code></td><td>The Object that dispatched the event; 
+     *        it is not always the Object listening for the event. 
+     *        Use the <code>currentTarget</code> property to always access the 
+     *        Object listening for the event.</td></tr>

  (This diff was longer than 20,000 lines, and has been truncated...)


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services