incubator-flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fri...@apache.org
Subject svn commit: r1234229 [2/4] - in /incubator/flex/whiteboard/frishy: ./ FastGroupingCollection/ FastGroupingCollection/.settings/ FastGroupingCollection/libs/ FastGroupingCollection/src/ FastGroupingCollection/src/com/ FastGroupingCollection/src/com/fris...
Date Sat, 21 Jan 2012 01:33:28 GMT
Added: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/ConfigurableCollectionTests.mxml
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/frishy/FastGroupingCollection/src/ConfigurableCollectionTests.mxml?rev=1234229&view=auto
==============================================================================
--- incubator/flex/whiteboard/frishy/FastGroupingCollection/src/ConfigurableCollectionTests.mxml (added)
+++ incubator/flex/whiteboard/frishy/FastGroupingCollection/src/ConfigurableCollectionTests.mxml Sat Jan 21 01:33:26 2012
@@ -0,0 +1,504 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+               xmlns:s="library://ns.adobe.com/flex/spark" 
+               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
+               applicationComplete="application1_applicationCompleteHandler(event)">
+    <fx:Script>
+        <![CDATA[
+            import flash.utils.getTimer;
+            
+            import mx.collections.ArrayCollection;
+            import mx.collections.ArrayList;
+            import mx.collections.Grouping;
+            import mx.collections.GroupingCollection;
+            import mx.collections.GroupingCollection2;
+            import mx.collections.GroupingField;
+            import mx.collections.HierarchicalCollectionView;
+            import mx.collections.ICollectionView;
+            import mx.collections.IList;
+            import mx.collections.Sort;
+            import mx.collections.SortField;
+            import mx.events.FlexEvent;
+            
+            protected function application1_applicationCompleteHandler(event:FlexEvent):void
+            {
+                
+            }
+            
+            public var collectionTests:CollectionTest = new CollectionTest();
+            public var testResultsAdd:Array;
+            public var testResultsUpdate:Array;
+            
+            public static const NUM_ITERATIONS_PER_SECOND:int = 4;
+            
+            private static const NON_BINDABLE_OBJECT:int = 0;
+            private static const PROPERTY_CHANGE_BINDABLE_OBJECT:int = 1;
+            private static const SINGLE_VERSION_EVENT_BINDABLE_OBJECT:int = 2;
+            private static const UNIQUE_EVENT_BINDABLE_OBJECT:int = 3;
+            
+            private static const ARRAY_TYPE:int = 0;
+            private static const VECTOR_TYPE:int = 1;
+            private static const ARRAY_LIST_TYPE:int = 2;
+            private static const ARRAY_COLLECTION_TYPE:int = 3;
+            private static const ARRAY_COLLECTION_FILTER_TYPE:int = 4;
+            private static const ARRAY_COLLECTION_SORT_TYPE:int = 5;
+            private static const ARRAY_COLLECTION_FILTER_SORT_TYPE:int = 6;
+            
+            private static const WRAPPING_COLLECTION_NONE:int = 0;
+            private static const WRAPPING_COLLECTION_GC2_NO_GROUPING:int = 1;
+            private static const WRAPPING_COLLECTION_GC2_WITH_GROUPING:int = 2;
+            private static const WRAPPING_COLLECTION_HCV_NO_GROUPING:int = 3;
+            private static const WRAPPING_COLLECTION_HCV_WITH_GROUPING:int = 4;
+            
+            public function get numItemsToInitializeWith():int
+            {
+                return seedItemAmountInput.value;
+            }
+            
+            public function get fillSeedItems():Boolean
+            {
+                return fillSeedItemsInput.selected;
+            }
+            
+            public function get numIterations():int
+            {
+                return numSecondsInput.value * NUM_ITERATIONS_PER_SECOND;
+            }
+            
+            public function get numItemsToAddPerSecond():int
+            {
+                return numItemsToAddPerSecondInput.value;
+            }
+            
+            public function get fillObjectsInitially():Boolean
+            {
+                return fillObjectsInitiallyCheckBox.selected;
+            }
+            
+            public function get numItemsToUpdatePerSecond():int
+            {
+                return numItemsToUpdatePerSecondInput.value;
+            }
+            
+            public function get numPropertiesPerUpdate():int
+            {
+                return numPropsToUpdatePerObjectUpdateInput.value;
+            }
+            
+            public function runTest():void
+            {
+                
+                collectionTests.addEventListener(CollectionTest.TEST_COMPLETE, testCompleteHandler);
+                
+                switch (collectionToUseDropDownList.selectedIndex)
+                {
+                    case ARRAY_TYPE:
+                        startArrayTest();
+                        break;
+                    case VECTOR_TYPE:
+                        startVectorTest();
+                        break;
+                    case ARRAY_LIST_TYPE:
+                    case ARRAY_COLLECTION_TYPE:
+                    case ARRAY_COLLECTION_FILTER_TYPE:
+                    case ARRAY_COLLECTION_SORT_TYPE:
+                    case ARRAY_COLLECTION_FILTER_SORT_TYPE:
+                        startCollectionTest();
+                        break;
+                }
+            }
+            
+            private function startArrayTest():void
+            {
+                var myArray:Array = [];
+                
+                if (numItemsToInitializeWith > 0)
+                {
+                    switch (objectToUseDropDownList.selectedIndex)
+                    {
+                        case NON_BINDABLE_OBJECT:
+                            collectionTests.fillArrayNonBindable(myArray, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case PROPERTY_CHANGE_BINDABLE_OBJECT:
+                            collectionTests.fillArrayPropertyChangeBindable(myArray, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case UNIQUE_EVENT_BINDABLE_OBJECT:
+                            collectionTests.fillArrayUniqueEventBindable(myArray, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case SINGLE_VERSION_EVENT_BINDABLE_OBJECT:
+                            collectionTests.fillArraySingleVersionEventBindable(myArray, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                    }
+                }
+                
+                if (numItemsToAddPerSecond > 0)
+                {
+                    switch (objectToUseDropDownList.selectedIndex)
+                    {
+                        case NON_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsNonBindableArray(myArray, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case PROPERTY_CHANGE_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsPropertyChangeBindableArray(myArray, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case UNIQUE_EVENT_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsUniqueEventBindableArray(myArray, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case SINGLE_VERSION_EVENT_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsSingleVersionEventBindableArray(myArray, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                    }
+                }
+                
+                if (numItemsToUpdatePerSecond > 0)
+                {
+                    testResultsUpdate = collectionTests.startRandomPropertyUpdatesArray(myArray, numIterations, numItemsToUpdatePerSecond, numPropertiesPerUpdate);
+                }
+            }
+            
+            private function startVectorTest():void
+            {
+                var myVector:Vector.<Object> = new Vector.<Object>();
+                
+                if (numItemsToInitializeWith > 0)
+                {
+                    switch (objectToUseDropDownList.selectedIndex)
+                    {
+                        case NON_BINDABLE_OBJECT:
+                            collectionTests.fillVectorNonBindable(myVector, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case PROPERTY_CHANGE_BINDABLE_OBJECT:
+                            collectionTests.fillVectorPropertyChangeBindable(myVector, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case UNIQUE_EVENT_BINDABLE_OBJECT:
+                            collectionTests.fillVectorUniqueEventBindable(myVector, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case SINGLE_VERSION_EVENT_BINDABLE_OBJECT:
+                            collectionTests.fillVectorSingleVersionEventBindable(myVector, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                    }
+                }
+                
+                if (numItemsToAddPerSecond > 0)
+                {
+                    switch (objectToUseDropDownList.selectedIndex)
+                    {
+                        case NON_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsNonBindableVector(myVector, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case PROPERTY_CHANGE_BINDABLE_OBJECT: 
+                            testResultsAdd = collectionTests.startRandomAdditionsPropertyChangeBindableVector(myVector, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case UNIQUE_EVENT_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsUniqueEventBindableVector(myVector, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case SINGLE_VERSION_EVENT_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsSingleVersionEventBindableVector(myVector, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                    }
+                }
+                
+                if (numItemsToUpdatePerSecond > 0)
+                {
+                    testResultsUpdate = collectionTests.startRandomPropertyUpdatesVector(myVector, numIterations, numItemsToUpdatePerSecond, numPropertiesPerUpdate);
+                }
+            }
+            
+            private function startCollectionTest():void
+            {
+                var myList:IList = createCollectionObject();
+                
+                collectionWrapper = wrapInOtherCollectionIfNeeded(myList);
+                
+                applySortAndFilterIfNeeded(collectionWrapper, myList);
+                
+                if (numItemsToInitializeWith > 0)
+                {
+                    switch (objectToUseDropDownList.selectedIndex)
+                    {
+                        case NON_BINDABLE_OBJECT:
+                            collectionTests.fillCollectionNonBindable(myList, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case PROPERTY_CHANGE_BINDABLE_OBJECT:
+                            collectionTests.fillCollectionPropertyChangeBindable(myList, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case UNIQUE_EVENT_BINDABLE_OBJECT:
+                            collectionTests.fillCollectionUniqueEventBindable(myList, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case SINGLE_VERSION_EVENT_BINDABLE_OBJECT:
+                            collectionTests.fillCollectionSingleVersionEventBindable(myList, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                    }
+                }
+                
+                if (numItemsToAddPerSecond > 0)
+                {
+                    switch (objectToUseDropDownList.selectedIndex)
+                    {
+                        case NON_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsNonBindableCollection(myList, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case PROPERTY_CHANGE_BINDABLE_OBJECT: 
+                            testResultsAdd = collectionTests.startRandomAdditionsPropertyChangeBindableCollection(myList, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case UNIQUE_EVENT_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsUniqueEventBindableCollection(myList, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case SINGLE_VERSION_EVENT_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsSingleVersionEventBindableCollection(myList, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                    }
+                }
+                
+                if (numItemsToUpdatePerSecond > 0)
+                {
+                    testResultsUpdate = collectionTests.startRandomPropertyUpdatesCollection(myList, numIterations, numItemsToUpdatePerSecond, numPropertiesPerUpdate);
+                }
+            }
+            
+            private function createCollectionObject():IList
+            {
+                if (collectionToUseDropDownList.selectedIndex == ARRAY_LIST_TYPE)
+                    return new ArrayList();
+                else
+                    return new ArrayCollection();
+            }
+            
+            private function applySortAndFilterIfNeeded(
+                collectionWrapper:Object, 
+                underlyingCollection:IList):void
+            {
+                var collectionForFilterAndSort:ICollectionView = collectionWrapper as ICollectionView;
+                if (!collectionForFilterAndSort)
+                    collectionForFilterAndSort = underlyingCollection as ICollectionView;
+                
+                if (collectionToUseDropDownList.selectedIndex == ARRAY_COLLECTION_FILTER_TYPE ||
+                    collectionToUseDropDownList.selectedIndex == ARRAY_COLLECTION_FILTER_SORT_TYPE)
+                {
+                    collectionForFilterAndSort.filterFunction = testFilterFunction;
+                }
+                
+                if (collectionToUseDropDownList.selectedIndex == ARRAY_COLLECTION_SORT_TYPE ||
+                    collectionToUseDropDownList.selectedIndex == ARRAY_COLLECTION_FILTER_SORT_TYPE)
+                {
+                    collectionForFilterAndSort.sort = getTestSort();
+                }
+                
+                if (collectionToUseDropDownList.selectedIndex != ARRAY_COLLECTION_TYPE)
+                {
+                    collectionForFilterAndSort.refresh();
+                }
+            }
+            
+            private function wrapInOtherCollectionIfNeeded(myList:IList):Object
+            {
+                var gc2:GroupingCollection2;
+                var hcv:HierarchicalCollectionView;
+                
+                switch (wrappingCollectionToUseDropDownList.selectedIndex)
+                {
+                    case WRAPPING_COLLECTION_NONE:
+                        return myList;
+                    case WRAPPING_COLLECTION_HCV_NO_GROUPING:
+                        gc2 = new GroupingCollection2();
+                        gc2.source = myList;
+                        gc2.refresh();
+                        hcv = new HierarchicalCollectionView(gc2);
+                        return hcv;
+                    case WRAPPING_COLLECTION_HCV_WITH_GROUPING:
+                        gc2 = new GroupingCollection2();
+                        gc2.grouping = getTestGrouping();
+                        gc2.source = myList;
+                        gc2.refresh();
+                        hcv = new HierarchicalCollectionView(gc2);
+                        return hcv;
+                }
+                
+                return null;
+            }
+            
+            // just to make sure we hold a reference to these things..
+            private var collectionWrapper:Object;
+            
+            private function getTestGrouping():Grouping
+            {
+                var grouping:Grouping = new Grouping();
+                var gf:GroupingField = new GroupingField("property3");
+                gf.groupingFunction = testGroupingFunction;
+                grouping.fields = [gf];
+                
+                return grouping;
+            }
+            
+            [Bindable]
+            private var numGroupsForGroupingCollection:int = 10;
+            
+            private function testGroupingFunction(item:Object, field:GroupingField):String
+            {
+                var myNumber:Number = item[field.name] as Number;
+                var groupId:Number = Math.floor(myNumber * numGroupsForGroupingCollection);
+                return groupId.toString();
+            }
+            
+            private function testCompleteHandler(event:Event):void
+            {
+                // if haven't finished both tests, wait for next event
+                if (numItemsToAddPerSecond > 0 
+                    && numItemsToUpdatePerSecond > 0 
+                    && testResultsAdd.length != testResultsUpdate.length)
+                {
+                    return;
+                }
+                
+                var totalTime:int = 0;
+                var len:int = testResultsAdd ? testResultsAdd.length : 0;
+                for (var i:int = 0; i < len; i++)
+                {
+                    totalTime += testResultsAdd[i];
+                }
+                
+                len = testResultsUpdate ? testResultsUpdate.length : 0;
+                for (i = 0; i < len; i++)
+                {
+                    totalTime += testResultsUpdate[i];
+                }
+                
+                testResultsAdd = testResultsUpdate = null;
+                
+                resultLabel.text += ": " + totalTime;
+                collectionTests.removeEventListener(CollectionTest.TEST_COMPLETE, testCompleteHandler);
+            }
+            
+            [Bindable]
+            public var valToTestForGreaterThanInFilterFunction:Number = 0.8;
+            
+            public function testFilterFunction(item:Object):Boolean
+            {
+                return item.property0 > valToTestForGreaterThanInFilterFunction;
+            }
+            
+            public function getTestSort():Sort
+            {
+                var sort:Sort = new Sort();
+                sort.fields = [new SortField("property1")];
+                return sort;
+            }
+            
+            private function formatIntTo3Digits(value:int):String
+            {
+                if (value >= 100)
+                    return "" + value;
+                else if (value >= 10)
+                    return "0" + value;
+                else
+                    return "00" + value;
+            }
+            
+            private function formatIntTo5Digits(value:int):String
+            {
+                if (value >= 10000)
+                    return "" + value;
+                if (value >= 1000)
+                    return "0" + value;
+                if (value >= 100)
+                    return "00" + value;
+                else if (value >= 10)
+                    return "000" + value;
+                else
+                    return "0000" + value;
+            }
+            
+        ]]>
+    </fx:Script>
+    <fx:Declarations>
+        <!-- Place non-visual elements (e.g., services, value objects) here -->
+        <s:NumberFormatter id="decimalFormatterPrecision2" trailingZeros="true" leadingZero="true" fractionalDigits="2" />
+    </fx:Declarations>
+    <s:layout>
+        <s:VerticalLayout />
+    </s:layout>
+    
+    <s:FormItem label="Object to use">
+        <s:DropDownList id="objectToUseDropDownList" requireSelection="true" width="200">
+            <s:ArrayList>
+                <fx:String>NonBindableObject</fx:String>
+                <fx:String>PropertyChangeBindableObject</fx:String>
+                <fx:String>SingleVersionEventBindableObject</fx:String>
+                <fx:String>UniqueEventBindableObject</fx:String>
+            </s:ArrayList>
+        </s:DropDownList>
+    </s:FormItem>
+    
+    <s:HGroup>
+        <s:FormItem label="Collection to use">
+            <s:DropDownList id="collectionToUseDropDownList" requireSelection="true" width="200">
+                <s:ArrayList>
+                    <fx:String>Array</fx:String>
+                    <fx:String>Vector</fx:String>
+                    <fx:String>ArrayList</fx:String>
+                    <fx:String>ArrayCollection</fx:String>
+                    <fx:String>ArrayCollection + Filter</fx:String>
+                    <fx:String>ArrayCollection + Sort</fx:String>
+                    <fx:String>ArrayCollection + Filter + Sort</fx:String>
+                </s:ArrayList>
+            </s:DropDownList>
+        </s:FormItem>
+        <s:FormItem label="Wrapping Collection to use">
+            <s:DropDownList id="wrappingCollectionToUseDropDownList" requireSelection="true" width="200">
+                <s:ArrayList>
+                    <fx:String>None</fx:String>
+                    <fx:String>GroupingCollection2 no grouping</fx:String>
+                    <fx:String>GroupingCollection2 group by 1 field</fx:String>
+                    <fx:String>HCV wrapping GC2 no grouping</fx:String>
+                    <fx:String>HCV wrapping GC2 group by 1 field</fx:String>
+                </s:ArrayList>
+            </s:DropDownList>
+        </s:FormItem>
+    </s:HGroup>
+    
+    <s:HGroup>
+        <s:FormItem label="Seed with items ({formatIntTo5Digits(seedItemAmountInput.value)})" >
+            <s:NumericStepper id="seedItemAmountInput" minimum="10" maximum="1000000" value="100" stepSize="5"  />
+        </s:FormItem>
+        <s:FormItem label="Fill seed items">
+            <s:CheckBox id="fillSeedItemsInput" selected="false" />
+        </s:FormItem>
+    </s:HGroup>
+    
+    <s:FormItem label="Num Seconds ({formatIntTo3Digits(numSecondsInput.value)})" >
+        <s:NumericStepper id="numSecondsInput" minimum="5" maximum="300" value="20" snapInterval="5" stepSize="5" />
+    </s:FormItem>
+    
+    <s:HGroup>
+        <s:FormItem label="Num items to add per second ({formatIntTo3Digits(numItemsToAddPerSecondInput.value)})">
+            <s:NumericStepper id="numItemsToAddPerSecondInput" minimum="0" maximum="300" value="50" snapInterval="5" stepSize="5" />
+        </s:FormItem>
+        <s:FormItem label="Fill added objects initially">
+            <s:CheckBox id="fillObjectsInitiallyCheckBox" selected="false" />
+        </s:FormItem>
+    </s:HGroup>
+    
+    <s:HGroup>
+        <s:FormItem label="Num items to update per second ({formatIntTo3Digits(numItemsToUpdatePerSecondInput.value)})">
+            <s:NumericStepper id="numItemsToUpdatePerSecondInput" minimum="0" maximum="300" value="100" snapInterval="5" stepSize="5" />
+        </s:FormItem>
+        <s:FormItem label="Num props per update ({formatIntTo3Digits(numPropsToUpdatePerObjectUpdateInput.value)})">
+            <s:NumericStepper id="numPropsToUpdatePerObjectUpdateInput" minimum="0" maximum="30" value="10" snapInterval="5" stepSize="5" />
+        </s:FormItem> 
+    </s:HGroup>
+    
+    <s:HGroup>
+        <s:FormItem label="Value to test for greater than in filter function ({decimalFormatterPrecision2.format(valToTestForGreaterThanInFilterFunction)})">
+            <s:NumericStepper minimum="0" maximum="1" value="@{valToTestForGreaterThanInFilterFunction}" snapInterval="0.05" stepSize="0.05" />
+        </s:FormItem>
+        <s:FormItem label="Num groups to have if wrapping with a grouping collection ({formatIntTo3Digits(numGroupsForGroupingCollection)})">
+            <s:NumericStepper value="@{numGroupsForGroupingCollection}" minimum="1" maximum="200" snapInterval="1" stepSize="1" />
+        </s:FormItem>
+    </s:HGroup>
+    
+    
+    <s:HGroup>
+        <s:Button label="Run test" click="runTest()" />
+        <s:Label id="resultLabel" text="Result: " />
+    </s:HGroup>
+</s:Application>

Propchange: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/ConfigurableCollectionTests.mxml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/FastAdvancedDataGridTest.mxml
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/frishy/FastGroupingCollection/src/FastAdvancedDataGridTest.mxml?rev=1234229&view=auto
==============================================================================
--- incubator/flex/whiteboard/frishy/FastGroupingCollection/src/FastAdvancedDataGridTest.mxml (added)
+++ incubator/flex/whiteboard/frishy/FastGroupingCollection/src/FastAdvancedDataGridTest.mxml Sat Jan 21 01:33:26 2012
@@ -0,0 +1,516 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+               xmlns:s="library://ns.adobe.com/flex/spark" 
+               xmlns:mx="library://ns.adobe.com/flex/mx" 
+               xmlns:fastdatagridhelpers="fastdatagridhelpers.*"
+               minWidth="955" minHeight="600">
+    <fx:Script>
+        <![CDATA[
+            import com.frishy.collections.FastGroupingCollection;
+            
+            import flash.utils.getTimer;
+            
+            import mx.collections.ArrayCollection;
+            import mx.collections.ArrayList;
+            import mx.collections.Grouping;
+            import mx.collections.GroupingCollection;
+            import mx.collections.GroupingCollection2;
+            import mx.collections.GroupingField;
+            import mx.collections.HierarchicalCollectionView;
+            import mx.collections.ICollectionView;
+            import mx.collections.IList;
+            import mx.collections.Sort;
+            import mx.collections.SortField;
+            import mx.collections.SummaryField2;
+            import mx.collections.SummaryRow;
+            import mx.events.FlexEvent;
+            import mx.managers.LayoutManager;
+            
+            protected function application1_applicationCompleteHandler(event:FlexEvent):void
+            {
+                
+            }
+            
+            public var collectionTests:CollectionTest = new CollectionTest();
+            public var testResultsAdd:Array;
+            public var testResultsUpdate:Array;
+            
+            public static const NUM_ITERATIONS_PER_SECOND:int = 4;
+            
+            private static const NON_BINDABLE_OBJECT:int = 0;
+            private static const PROPERTY_CHANGE_BINDABLE_OBJECT:int = 1;
+            private static const SINGLE_VERSION_EVENT_BINDABLE_OBJECT:int = 2;
+            private static const UNIQUE_EVENT_BINDABLE_OBJECT:int = 3;
+            
+            private static const ARRAY_COLLECTION_TYPE:int = 0;
+            private static const ARRAY_COLLECTION_FILTER_TYPE:int = 1;
+            private static const ARRAY_COLLECTION_SORT_TYPE:int = 2;
+            private static const ARRAY_COLLECTION_FILTER_SORT_TYPE:int = 3;
+            
+            private static const WRAPPING_COLLECTION_NONE:int = 0;
+            private static const WRAPPING_COLLECTION_HCV_NO_GROUPING:int = 1;
+            private static const WRAPPING_COLLECTION_HCV_WITH_GROUPING:int = 2;
+            private static const WRAPPING_COLLECTION_HCV_FAST_NO_GROUPING:int = 3;
+            private static const WRAPPING_COLLECTION_HCV_FAST_WITH_GROUPING:int = 4;
+            
+            public function get numItemsToInitializeWith():int
+            {
+                return seedItemAmountInput.value;
+            }
+            
+            public function get fillSeedItems():Boolean
+            {
+                return fillSeedItemsInput.selected;
+            }
+            
+            public function get numIterations():int
+            {
+                return numSecondsInput.value * NUM_ITERATIONS_PER_SECOND;
+            }
+            
+            public function get numItemsToAddPerSecond():int
+            {
+                return numItemsToAddPerSecondInput.value;
+            }
+            
+            public function get addSummaryRows():Boolean
+            {
+                return addSummaryRowsCheckBox.selected;
+            }
+            
+            public function get fillObjectsInitially():Boolean
+            {
+                return fillObjectsInitiallyCheckBox.selected;
+            }
+            
+            public function get numItemsToUpdatePerSecond():int
+            {
+                return numItemsToUpdatePerSecondInput.value;
+            }
+            
+            public function get numPropertiesPerUpdate():int
+            {
+                return numPropsToUpdatePerObjectUpdateInput.value;
+            }
+            
+            public function runTest():void
+            {
+                
+                collectionTests.addEventListener(CollectionTest.TEST_COMPLETE, testCompleteHandler);
+                
+                switch (collectionToUseDropDownList.selectedIndex)
+                {
+                    case ARRAY_COLLECTION_TYPE:
+                    case ARRAY_COLLECTION_FILTER_TYPE:
+                    case ARRAY_COLLECTION_SORT_TYPE:
+                    case ARRAY_COLLECTION_FILTER_SORT_TYPE:
+                        startCollectionTest();
+                        break;
+                }
+            }
+            
+            private var validationTime:int;
+            private var layoutManagerStartTime:int;
+            private var renderTime:int;
+            private var initializationTime:int;
+            private var layoutManagerEndTime:int;
+            
+            private function layoutManager_layoutManagerStartHandler(event:Event):void
+            {
+                layoutManagerStartTime = getTimer();
+            }
+            
+            private function layoutManager_layoutManagerEndHandler(event:Event):void
+            {
+                layoutManagerEndTime = getTimer();
+                validationTime += (layoutManagerEndTime - layoutManagerStartTime);
+            }
+            
+            private function enterFrameHandler(event:Event):void
+            {
+                if (layoutManagerEndTime > 0)
+                {
+                    renderTime += (getTimer() - layoutManagerEndTime);
+                    layoutManagerEndTime = 0;
+                }
+            }
+            
+            private function startCollectionTest():void
+            {
+                validationTime = 0;
+                layoutManagerEndTime = 0;
+                layoutManagerStartTime = 0;
+                initializationTime = 0;
+                renderTime = 0;
+                
+                var myList:IList = createCollectionObject();
+                
+                initializationTime = getTimer();
+                
+                if (numItemsToInitializeWith > 0)
+                {
+                    switch (objectToUseDropDownList.selectedIndex)
+                    {
+                        case NON_BINDABLE_OBJECT:
+                            collectionTests.fillCollectionNonBindable(myList, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case PROPERTY_CHANGE_BINDABLE_OBJECT:
+                            collectionTests.fillCollectionPropertyChangeBindable(myList, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case UNIQUE_EVENT_BINDABLE_OBJECT:
+                            collectionTests.fillCollectionUniqueEventBindable(myList, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                        case SINGLE_VERSION_EVENT_BINDABLE_OBJECT:
+                            collectionTests.fillCollectionSingleVersionEventBindable(myList, numItemsToInitializeWith, fillSeedItems);
+                            break;
+                    }
+                }
+                
+                initializationTime = getTimer() - initializationTime;
+                
+                var collectionWrapper:Object = wrapInOtherCollectionIfNeeded(myList);
+                
+                applySortAndFilterIfNeeded(collectionWrapper, myList);
+                
+                adg.dataProvider = collectionWrapper;
+                
+                LayoutManager.getInstance().validateNow();
+                
+                LayoutManager.getInstance().addEventListener("layoutManagerStart", layoutManager_layoutManagerStartHandler);
+                LayoutManager.getInstance().addEventListener("updateComplete", layoutManager_layoutManagerEndHandler);
+                addEventListener(Event.ENTER_FRAME, enterFrameHandler);
+                
+                if (numItemsToAddPerSecond > 0)
+                {
+                    switch (objectToUseDropDownList.selectedIndex)
+                    {
+                        case NON_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsNonBindableCollection(myList, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case PROPERTY_CHANGE_BINDABLE_OBJECT: 
+                            testResultsAdd = collectionTests.startRandomAdditionsPropertyChangeBindableCollection(myList, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case UNIQUE_EVENT_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsUniqueEventBindableCollection(myList, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                        case SINGLE_VERSION_EVENT_BINDABLE_OBJECT:
+                            testResultsAdd = collectionTests.startRandomAdditionsSingleVersionEventBindableCollection(myList, numIterations, numItemsToAddPerSecond, fillObjectsInitially);
+                            break;
+                    }
+                }
+                
+                if (numItemsToUpdatePerSecond > 0)
+                {
+                    testResultsUpdate = collectionTests.startRandomPropertyUpdatesCollection(myList, numIterations, numItemsToUpdatePerSecond, numPropertiesPerUpdate);
+                }
+            }
+            
+            private function createCollectionObject():IList
+            {
+                return new ArrayCollection();
+            }
+            
+            private function applySortAndFilterIfNeeded(
+                collectionWrapper:Object, 
+                underlyingCollection:IList):void
+            {
+                var collectionForFilterAndSort:ICollectionView = collectionWrapper as ICollectionView;
+                if (!collectionForFilterAndSort)
+                    collectionForFilterAndSort = underlyingCollection as ICollectionView;
+                
+                if (collectionToUseDropDownList.selectedIndex == ARRAY_COLLECTION_FILTER_TYPE ||
+                    collectionToUseDropDownList.selectedIndex == ARRAY_COLLECTION_FILTER_SORT_TYPE)
+                {
+                    collectionForFilterAndSort.filterFunction = testFilterFunction;
+                }
+                
+                if (collectionToUseDropDownList.selectedIndex == ARRAY_COLLECTION_SORT_TYPE ||
+                    collectionToUseDropDownList.selectedIndex == ARRAY_COLLECTION_FILTER_SORT_TYPE)
+                {
+                    collectionForFilterAndSort.sort = getTestSort();
+                }
+                
+                if (collectionToUseDropDownList.selectedIndex != ARRAY_COLLECTION_TYPE)
+                {
+                    collectionForFilterAndSort.refresh();
+                }
+            }
+            
+            private function wrapInOtherCollectionIfNeeded(myList:IList):Object
+            {
+                var gc2:GroupingCollection2;
+                var fgc:FastGroupingCollection;
+                var hcv:HierarchicalCollectionView;
+                
+                switch (wrappingCollectionToUseDropDownList.selectedIndex)
+                {
+                    case WRAPPING_COLLECTION_NONE:
+                        return myList;
+                    case WRAPPING_COLLECTION_HCV_NO_GROUPING:
+                        gc2 = new GroupingCollection2();
+                        gc2.source = myList;
+                        gc2.refresh();
+                        hcv = new HierarchicalCollectionView(gc2);
+                        return hcv;
+                    case WRAPPING_COLLECTION_HCV_WITH_GROUPING:
+                        gc2 = new GroupingCollection2();
+                        gc2.grouping = getTestGrouping();
+                        gc2.source = myList;
+                        gc2.refresh();
+                        hcv = new HierarchicalCollectionView(gc2);
+                        return hcv;
+                    case WRAPPING_COLLECTION_HCV_FAST_NO_GROUPING:
+                        fgc = new FastGroupingCollection();
+                        fgc.source = myList;
+                        hcv = new HierarchicalCollectionView(fgc);
+                        return hcv;
+                    case WRAPPING_COLLECTION_HCV_FAST_WITH_GROUPING:
+                        fgc = new FastGroupingCollection();
+                        fgc.grouping = getTestGrouping();
+                        fgc.source = myList;
+                        hcv = new HierarchicalCollectionView(fgc);
+                        return hcv;
+                }
+                
+                return null;
+            }
+            
+            private function getTestGrouping():Grouping
+            {
+                var grouping:Grouping = new Grouping();
+                var gf:GroupingField = new GroupingField("property3");
+                gf.groupingFunction = testGroupingFunction;
+                grouping.fields = [gf];
+                
+                if (addSummaryRows)
+                {
+                    var sr:SummaryRow = new SummaryRow();
+                    var sf:SummaryField2 = new SummaryField2();
+                    sf.dataField = "property9";
+                    sf.summaryOperation = "SUM";
+                    var sf2:SummaryField2 = new SummaryField2();
+                    sf2.summaryOperation = "AVG";
+                    sf2.dataField = "property6";
+                    sr.fields = [sf, sf2];
+                    gf.summaries = [sr];
+                }
+                
+                return grouping;
+            }
+            
+            [Bindable]
+            private var numGroupsForGroupingCollection:int = 10;
+            
+            private function testGroupingFunction(item:Object, field:GroupingField):String
+            {
+                var myNumber:Number = item[field.name] as Number;
+                var groupId:Number = Math.floor(myNumber * numGroupsForGroupingCollection);
+                return groupId.toString();
+            }
+            
+            private function testCompleteHandler(event:Event):void
+            {
+                // if haven't finished both tests, wait for next event
+                if (numItemsToAddPerSecond > 0 
+                    && numItemsToUpdatePerSecond > 0 
+                    && testResultsAdd.length != testResultsUpdate.length)
+                {
+                    return;
+                }
+                
+                var collectionTime:int = 0;
+                var len:int = testResultsAdd ? testResultsAdd.length : 0;
+                for (var i:int = 0; i < len; i++)
+                {
+                    collectionTime += testResultsAdd[i];
+                }
+                
+                len = testResultsUpdate ? testResultsUpdate.length : 0;
+                for (i = 0; i < len; i++)
+                {
+                    collectionTime += testResultsUpdate[i];
+                }
+                
+                testResultsAdd = testResultsUpdate = null;
+                
+                var totalTime:Number = initializationTime + collectionTime + validationTime; // ignore renderTime since not 100% accurate unless frameRate is skipping
+                resultLabel.text += ": (" + initializationTime + ", " + collectionTime + ", " + validationTime + ", " + totalTime + ") ";
+                
+                collectionTests.removeEventListener(CollectionTest.TEST_COMPLETE, testCompleteHandler);
+                LayoutManager.getInstance().removeEventListener("layoutManagerStart", layoutManager_layoutManagerStartHandler);
+                LayoutManager.getInstance().removeEventListener("updateComplete", layoutManager_layoutManagerEndHandler);
+                removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
+                
+            }
+            
+            [Bindable]
+            public var valToTestForGreaterThanInFilterFunction:Number = 0.8;
+            
+            public function testFilterFunction(item:Object):Boolean
+            {
+                if ("property0" in item)
+                    return item.property0 > valToTestForGreaterThanInFilterFunction;
+                else
+                    return true; // for groups
+            }
+            
+            public function getTestSort():Sort
+            {
+                var sort:Sort = new Sort();
+                sort.fields = [new SortField("property1")];
+                return sort;
+            }
+            
+            private function formatIntTo3Digits(value:int):String
+            {
+                if (value >= 100)
+                    return "" + value;
+                else if (value >= 10)
+                    return "0" + value;
+                else
+                    return "00" + value;
+            }
+            
+            private function formatIntTo5Digits(value:int):String
+            {
+                if (value >= 10000)
+                    return "" + value;
+                if (value >= 1000)
+                    return "0" + value;
+                if (value >= 100)
+                    return "00" + value;
+                else if (value >= 10)
+                    return "000" + value;
+                else
+                    return "0000" + value;
+            }
+            
+        ]]>
+    </fx:Script>
+    <fx:Declarations>
+        <!-- Place non-visual elements (e.g., services, value objects) here -->
+        <s:NumberFormatter id="decimalFormatterPrecision2" trailingZeros="true" leadingZero="true" fractionalDigits="2" />
+    </fx:Declarations>
+    <s:layout>
+        <s:VerticalLayout />
+    </s:layout>
+    
+    <s:FormItem label="Object to use">
+        <s:DropDownList id="objectToUseDropDownList" requireSelection="true" width="200" selectedIndex="1">
+            <s:ArrayList>
+                <fx:String>NonBindableObject</fx:String>
+                <fx:String>PropertyChangeBindableObject</fx:String>
+                <fx:String>SingleVersionEventBindableObject</fx:String>
+                <fx:String>UniqueEventBindableObject</fx:String>
+            </s:ArrayList>
+        </s:DropDownList>
+    </s:FormItem>
+    
+    <s:HGroup>
+        <s:FormItem label="Collection to use">
+            <s:DropDownList id="collectionToUseDropDownList" requireSelection="true" width="200" selectedIndex="0">
+                <s:ArrayList>
+                    <fx:String>ArrayCollection</fx:String>
+                    <fx:String>ArrayCollection + Filter</fx:String>
+                    <fx:String>ArrayCollection + Sort</fx:String>
+                    <fx:String>ArrayCollection + Filter + Sort</fx:String>
+                </s:ArrayList>
+            </s:DropDownList>
+        </s:FormItem>
+        <s:FormItem label="Wrapping Collection to use">
+            <s:DropDownList id="wrappingCollectionToUseDropDownList" requireSelection="true" width="200" selectedIndex="4">
+                <s:ArrayList>
+                    <fx:String>None</fx:String>
+                    <fx:String>HCV wrapping GC2 no grouping</fx:String>
+                    <fx:String>HCV wrapping GC2 group by 1 field</fx:String>
+                    <fx:String>HCV wrapping FGC no grouping</fx:String>
+                    <fx:String>HCV wrapping FGC group by 1 field</fx:String>
+                </s:ArrayList>
+            </s:DropDownList>
+        </s:FormItem>
+        <s:FormItem label="SummaryRows?">
+            <s:CheckBox id="addSummaryRowsCheckBox" />
+        </s:FormItem>
+    </s:HGroup>
+    
+    <s:HGroup>
+        <s:FormItem label="Seed with items ({formatIntTo5Digits(seedItemAmountInput.value)})" >
+            <s:NumericStepper id="seedItemAmountInput" minimum="0" maximum="1000000" value="100" stepSize="5"  />
+        </s:FormItem>
+        <s:FormItem label="Fill seed items">
+            <s:CheckBox id="fillSeedItemsInput" selected="true" />
+        </s:FormItem>
+    </s:HGroup>
+    
+    <s:FormItem label="Num Seconds ({formatIntTo3Digits(numSecondsInput.value)})" >
+        <s:NumericStepper id="numSecondsInput" minimum="1" maximum="300" value="20" snapInterval="1" stepSize="5" />
+    </s:FormItem>
+    
+    <s:HGroup>
+        <s:FormItem label="Num items to add per second ({formatIntTo3Digits(numItemsToAddPerSecondInput.value)})">
+            <s:NumericStepper id="numItemsToAddPerSecondInput" minimum="0" maximum="300" value="50" snapInterval="1" stepSize="5" />
+        </s:FormItem>
+        <s:FormItem label="Fill added objects initially">
+            <s:CheckBox id="fillObjectsInitiallyCheckBox" selected="true" />
+        </s:FormItem>
+    </s:HGroup>
+    
+    <s:HGroup>
+        <s:FormItem label="Num items to update per second ({formatIntTo3Digits(numItemsToUpdatePerSecondInput.value)})">
+            <s:NumericStepper id="numItemsToUpdatePerSecondInput" minimum="0" maximum="300" value="50" snapInterval="1" stepSize="5" />
+        </s:FormItem>
+        <s:FormItem label="Num props per update ({formatIntTo3Digits(numPropsToUpdatePerObjectUpdateInput.value)})">
+            <s:NumericStepper id="numPropsToUpdatePerObjectUpdateInput" minimum="0" maximum="30" value="10" snapInterval="1" stepSize="5" />
+        </s:FormItem> 
+    </s:HGroup>
+    
+    <s:HGroup>
+        <s:FormItem label="Value to test for greater than in filter function ({decimalFormatterPrecision2.format(valToTestForGreaterThanInFilterFunction)})">
+            <s:NumericStepper minimum="0" maximum="1" value="@{valToTestForGreaterThanInFilterFunction}" snapInterval="0.05" stepSize="0.05" />
+        </s:FormItem>
+        <s:FormItem label="Num groups to have if wrapping with a grouping collection ({formatIntTo3Digits(numGroupsForGroupingCollection)})">
+            <s:NumericStepper value="@{numGroupsForGroupingCollection}" minimum="1" maximum="200" snapInterval="1" stepSize="1" />
+        </s:FormItem>
+    </s:HGroup>
+    
+    <s:HGroup>
+        <s:Button label="Run test" click="runTest()" />
+        <s:Label id="resultLabel" text="Result: " />
+    </s:HGroup>
+    
+    <fastdatagridhelpers:FastAdvancedDataGrid id="adg" height="600" width="1200" 
+                                horizontalScrollPolicy="on" displayItemsExpanded="true">
+        <fastdatagridhelpers:columns>
+            <mx:AdvancedDataGridColumn dataField="property3" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property0" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property1" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property2" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property4" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property5" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property6" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property7" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property8" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property9" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property10" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property11" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property13" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property12" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property14" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property15" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property16" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property17" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property18" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property19" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property20" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property21" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property22" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property23" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property24" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property25" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property26" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property27" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property28" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property29" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+        </fastdatagridhelpers:columns>
+    </fastdatagridhelpers:FastAdvancedDataGrid>
+</s:Application>

Propchange: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/FastAdvancedDataGridTest.mxml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestFGC.mxml
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestFGC.mxml?rev=1234229&view=auto
==============================================================================
--- incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestFGC.mxml (added)
+++ incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestFGC.mxml Sat Jan 21 01:33:26 2012
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+               xmlns:s="library://ns.adobe.com/flex/spark" 
+               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" 
+               xmlns:fastdatagridhelpers="fastdatagridhelpers.*">
+    
+    <fx:Script>
+        <![CDATA[
+            import com.frishy.collections.FastGroupingCollection;
+            
+            import model.NestedPropertyObject;
+            import model.PropertyChangeBindableObject;
+            import model.UniqueEventBindableObject;
+            
+            import mx.collections.ArrayCollection;
+            import mx.collections.Grouping;
+            import mx.collections.GroupingField;
+            import mx.collections.SummaryField2;
+            import mx.collections.SummaryRow;
+            import mx.events.FlexEvent;
+            
+            private var ac:ArrayCollection;
+            private var fgc:FastGroupingCollection;
+            
+            protected function addRandomItem():void
+            {
+                var item:NestedPropertyObject = new NestedPropertyObject();
+                
+                if (Math.random() < 0.5)
+                {
+                    var item2:Object = new PropertyChangeBindableObject();
+                    item.propertyChangeBindableObject = item2 as PropertyChangeBindableObject;
+                }
+                else
+                {
+                    item2 = new UniqueEventBindableObject();
+                    item.uniqueEventBindableObject = item2 as UniqueEventBindableObject;
+                }
+                
+                if (Math.random() < 0.5)
+                    item2.fillAllProperties();
+                
+                ac.addItem(item);
+            }
+            
+            protected function removeRandomItem():void
+            {
+                if (ac.length == 0)
+                    return;
+                
+                var indexToRemove:int = Math.floor(ac.length * Math.random());
+                ac.removeItemAt(indexToRemove);
+            }
+            
+            protected function changeRandomItem():void
+            {
+                if (ac.length == 0)
+                    return;
+                
+                var indexToChange:int = Math.floor(ac.length * Math.random());
+                //var item:PropertyChangeBindableObject = PropertyChangeBindableObject(ac.getItemAt(indexToChange));
+                
+                var item:NestedPropertyObject = NestedPropertyObject(ac.getItemAt(indexToChange));
+                
+                if (Math.random() < 0.5)
+                {
+                    if (item.propertyChangeBindableObject && Math.random() < 0.5)
+                    {
+                        item2 = item.propertyChangeBindableObject;
+                    }
+                    else
+                    {
+                        var item2:Object = new PropertyChangeBindableObject();
+                        item.propertyChangeBindableObject = item2 as PropertyChangeBindableObject;
+                    }
+                }
+                else
+                {
+                    if (item.uniqueEventBindableObject && Math.random() < 0.5)
+                    {
+                        item2 = item.uniqueEventBindableObject;
+                    }
+                    else
+                    {
+                        item2 = new UniqueEventBindableObject();
+                        item.uniqueEventBindableObject = item2 as UniqueEventBindableObject;
+                    }
+                }
+                
+                if (Math.random() < 0.5)
+                    item2.fillAllProperties();
+                else
+                    item2.property3 = Math.random();
+                
+                //item.property3 = Math.random();
+            }
+            
+            protected function adg_preinitializeHandler(event:FlexEvent):void
+            {
+                ac = new ArrayCollection();
+                fgc = new FastGroupingCollection();
+                fgc.source = ac;
+                fgc.grouping = getTestGrouping();
+                
+                adg.dataProvider = fgc;
+            }
+            
+            private static const NUM_GROUPS:int = 3;
+            
+            private function testGroupingFunction(item:Object, field:GroupingField):String
+            {
+                var myNumber:Number = item[field.name] as Number;
+                var groupId:Number = Math.floor(myNumber * NUM_GROUPS);
+                return groupId.toString();
+            }
+            
+            private function getTestGrouping():Grouping
+            {
+                var grouping:Grouping = new Grouping();
+                var gf:GroupingField = new GroupingField("uniqueEventBindableObject.property3");
+//                gf.groupingFunction = testGroupingFunction;
+                
+                var sr:SummaryRow = new SummaryRow();
+                var sf:SummaryField2 = new SummaryField2();
+                sf.dataField = "uniqueEventBindableObject.property9";
+                sf.summaryOperation = "SUM";
+                var sf2:SummaryField2 = new SummaryField2();
+                sf2.summaryOperation = "AVG";
+                sf2.dataField = "propertyChangeBindableObject.property6";
+                sr.fields = [sf, sf2];
+//                gf.summaries = [sr];
+                
+                var gf2:GroupingField = new GroupingField("propertyChangeBindableObject.property6");
+//                gf2.groupingFunction = testGroupingFunction;
+                grouping.fields = [gf, gf2];
+                
+                return grouping;
+            }
+            
+        ]]>
+    </fx:Script>
+    
+    <fx:Declarations>
+        <!-- Place non-visual elements (e.g., services, value objects) here -->
+    </fx:Declarations>
+    
+    <s:layout>
+        <s:VerticalLayout />
+    </s:layout>
+    
+    <s:Button label="add random item" click="addRandomItem()" />
+    
+    <s:Button label="remove random item" click="removeRandomItem()" />
+    
+    <s:Button label="change random item" click="changeRandomItem()" />
+    
+    <fastdatagridhelpers:FastAdvancedDataGrid id="adg" height="600" width="1200" 
+                                              horizontalScrollPolicy="on" displayItemsExpanded="true"
+                                              preinitialize="adg_preinitializeHandler(event)">
+        <fastdatagridhelpers:columns>
+            <mx:AdvancedDataGridColumn dataField="uniqueEventBindableObject.property3" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="propertyChangeBindableObject.property0" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="uniqueEventBindableObject.property1" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="propertyChangeBindableObject.property2" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="uniqueEventBindableObject.property4" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="propertyChangeBindableObject.property5" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="uniqueEventBindableObject.property6" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="propertyChangeBindableObject.property7" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="uniqueEventBindableObject.property8" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="propertyChangeBindableObject.property9" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <!--<mx:AdvancedDataGridColumn dataField="property10" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property11" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property13" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property12" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property14" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property15" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property16" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property17" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property18" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property19" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property20" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property21" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property22" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property23" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property24" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property25" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property26" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property27" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property28" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property29" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" /> -->
+        </fastdatagridhelpers:columns>
+    </fastdatagridhelpers:FastAdvancedDataGrid>
+</s:Application>

Propchange: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestFGC.mxml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestGC2.mxml
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestGC2.mxml?rev=1234229&view=auto
==============================================================================
--- incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestGC2.mxml (added)
+++ incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestGC2.mxml Sat Jan 21 01:33:26 2012
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+               xmlns:s="library://ns.adobe.com/flex/spark" 
+               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" 
+               xmlns:fastdatagridhelpers="fastdatagridhelpers.*">
+    
+    <fx:Script>
+        <![CDATA[
+            import com.frishy.collections.FastGroupingCollection;
+            
+            import model.PropertyChangeBindableObject;
+            
+            import mx.collections.ArrayCollection;
+            import mx.collections.Grouping;
+            import mx.collections.GroupingCollection2;
+            import mx.collections.GroupingField;
+            import mx.collections.SummaryField2;
+            import mx.collections.SummaryRow;
+            import mx.events.FlexEvent;
+            
+            private var ac:ArrayCollection;
+            private var gc2:GroupingCollection2;
+            
+            protected function addRandomItem():void
+            {
+                var item:PropertyChangeBindableObject = new PropertyChangeBindableObject();
+                item.fillAllProperties();
+                ac.addItem(item);
+            }
+            
+            protected function removeRandomItem():void
+            {
+                if (ac.length == 0)
+                    return;
+                
+                var indexToRemove:int = Math.floor(ac.length * Math.random());
+                ac.removeItemAt(indexToRemove);
+            }
+            
+            protected function adg_preinitializeHandler(event:FlexEvent):void
+            {
+                ac = new ArrayCollection();
+                
+                addRandomItem();
+                addRandomItem();
+                addRandomItem();
+                
+                gc2 = new GroupingCollection2();
+                gc2.source = ac;
+                gc2.grouping = getTestGrouping();
+                gc2.refresh();
+                
+                adg.dataProvider = gc2;
+            }
+            
+            private static const NUM_GROUPS:int = 3;
+            
+            private function testGroupingFunction(item:Object, field:GroupingField):String
+            {
+                var myNumber:Number = item[field.name] as Number;
+                var groupId:Number = Math.floor(myNumber * NUM_GROUPS);
+                return groupId.toString();
+            }
+            
+            private function getTestGrouping():Grouping
+            {
+                var grouping:Grouping = new Grouping();
+                var gf:GroupingField = new GroupingField("property3");
+                gf.groupingFunction = testGroupingFunction;
+                
+                var sr:SummaryRow = new SummaryRow();
+                var sf:SummaryField2 = new SummaryField2();
+                sf.dataField = "property9";
+                sf.summaryOperation = "SUM";
+                var sf2:SummaryField2 = new SummaryField2();
+                sf2.summaryOperation = "AVG";
+                sf2.dataField = "property6";
+                sr.fields = [sf, sf2];
+                gf.summaries = [sr];
+                
+                var gf2:GroupingField = new GroupingField("property6");
+                gf2.groupingFunction = testGroupingFunction;
+                grouping.fields = [gf, gf2];
+                
+                return grouping;
+            }
+            
+        ]]>
+    </fx:Script>
+    
+    <fx:Declarations>
+        <!-- Place non-visual elements (e.g., services, value objects) here -->
+    </fx:Declarations>
+    
+    <s:layout>
+        <s:VerticalLayout />
+    </s:layout>
+    
+    <s:Button label="add random item" click="addRandomItem()" />
+    
+    <s:Button label="remove random item" click="removeRandomItem()" />
+    
+    <fastdatagridhelpers:FastAdvancedDataGrid id="adg" height="600" width="1200" 
+                                              horizontalScrollPolicy="on" displayItemsExpanded="true"
+                                              preinitialize="adg_preinitializeHandler(event)">
+        <fastdatagridhelpers:columns>
+            <mx:AdvancedDataGridColumn dataField="property3" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property0" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property1" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property2" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property4" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property5" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property6" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property7" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property8" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property9" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property10" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property11" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property13" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property12" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property14" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property15" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property16" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property17" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property18" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property19" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property20" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property21" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property22" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property23" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property24" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property25" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property26" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property27" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property28" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+            <mx:AdvancedDataGridColumn dataField="property29" width="80" itemRenderer="fastdatagridhelpers.ChangeWatcherAdvancedDataGridItemRenderer" />
+        </fastdatagridhelpers:columns>
+    </fastdatagridhelpers:FastAdvancedDataGrid>
+</s:Application>

Propchange: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/TestGC2.mxml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/com/frishy/collections/CollectionUtil.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/frishy/FastGroupingCollection/src/com/frishy/collections/CollectionUtil.as?rev=1234229&view=auto
==============================================================================
--- incubator/flex/whiteboard/frishy/FastGroupingCollection/src/com/frishy/collections/CollectionUtil.as (added)
+++ incubator/flex/whiteboard/frishy/FastGroupingCollection/src/com/frishy/collections/CollectionUtil.as Sat Jan 21 01:33:26 2012
@@ -0,0 +1,112 @@
+package com.frishy.collections
+{
+    import flash.xml.XMLNode;
+    
+    import mx.collections.ArrayCollection;
+    import mx.collections.ICollectionView;
+    import mx.collections.XMLListCollection;
+
+    /**
+     *  Utility helper class to perform some common operations that collection classes 
+     *  might need.
+     */
+    public class CollectionUtil
+    {
+        //--------------------------------------------------------------------------
+        //
+        //  Class Methods
+        //
+        //--------------------------------------------------------------------------
+     
+        /**
+         *  Helper method to convert an object into an ICollectionView
+         * 
+         *  @param value object to convert to a collection
+         *  @return a collection that represents the passed in value
+         */
+        public static function convertObjectToCollectionView(value:Object):ICollectionView
+        {
+            if (value == null)
+                return null;
+            
+            // rest is same as GroupingCollection2.getCollection()
+            
+            // handle strings and xml
+            if (typeof(value)=="string")
+                value = new XML(value);
+            else if (value is XMLNode)
+                value = new XML(XMLNode(value).toString());
+            else if (value is XMLList)
+                value = new XMLListCollection(value as XMLList);
+            
+            if (value is XML)
+            {
+                var xl:XMLList = new XMLList();
+                xl += value;
+                return new XMLListCollection(xl);
+            }
+                //if already a collection dont make new one
+            else if (value is ICollectionView)
+            {
+                return ICollectionView(value);
+            }
+            else if (value is Array)
+            {
+                return new ArrayCollection(value as Array);
+            }
+                //all other types get wrapped in an ArrayCollection
+            else if (value is Object)
+            {         
+                // convert to an array containing this one item
+                var tmp:Array = [];
+                tmp.push(value);
+                return new ArrayCollection(tmp);
+            }
+            else
+            {
+                return new ArrayCollection();
+            }
+        }
+        
+        /**
+         *  Grabs a property from an object.  This property may be a nested property.
+         *  
+         *  <p>Because it supports nested properties, it doesn't just do data[dataField].</p>
+         * 
+         *  @param data the object to grab the value from
+         *  @param dataField the data field property to use.  This may be a nested data field, 
+         *                   like "foo.bar"
+         * 
+         *  @return the appropriate property value from the data object.
+         */
+        public static function getDataFieldValue(data:Object, dataField:String):Object
+        {
+            try 
+            {
+                var isComplexDataField:Boolean = (dataField.indexOf(".") >= 0);
+                if (isComplexDataField)
+                {
+                    var pathElements:Array = dataField.split(".");
+                    var currentItemData:Object = data;
+                    
+                    for each (var pathElement:String in pathElements)
+                    {
+                        currentItemData = currentItemData[pathElement];
+                    }
+                    
+                    if (currentItemData != null)
+                        return currentItemData.toString();
+                }
+                else if (data.hasOwnProperty(dataField))
+                {
+                    return data[dataField];
+                }
+            }
+            catch(ignored:Error)
+            {
+            }
+            
+            return null;
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/flex/whiteboard/frishy/FastGroupingCollection/src/com/frishy/collections/CollectionUtil.as
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message