FLEX-34854 First unit test and implementation of watching for changes in complex fields. Also, ComplexSortField now caters for the case when the field name is null.
NOTES -Changes are monitored for the objects which existed in the collection before the sort was applied, not for the new ones. This is to follow. -The watching functionality will be externalized from ListCollectionView in the following commits. Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/cf657841 Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/cf657841 Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/cf657841 Branch: refs/heads/develop Commit: cf657841d06dfcbf0e5e16a469c8507d4d2dee81 Parents: 0470173 Author: Mihai Chira <[email protected]> Authored: Mon Jun 8 16:28:28 2015 +0200 Committer: Mihai Chira <[email protected]> Committed: Mon Jun 8 16:28:28 2015 +0200 ---------------------------------------------------------------------- .../src/mx/collections/ComplexSortField.as | 11 ++- .../src/mx/collections/IComplexSortField.as | 24 +++++++ .../src/mx/collections/ListCollectionView.as | 72 +++++++++++++++++++- .../framework/tests/FLEX_34854_Tests.as | 22 ++++++ 4 files changed, 125 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/cf657841/frameworks/projects/framework/src/mx/collections/ComplexSortField.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/framework/src/mx/collections/ComplexSortField.as b/frameworks/projects/framework/src/mx/collections/ComplexSortField.as index 1bc5f6d..eb29649 100644 --- a/frameworks/projects/framework/src/mx/collections/ComplexSortField.as +++ b/frameworks/projects/framework/src/mx/collections/ComplexSortField.as @@ -20,7 +20,7 @@ package mx.collections { import mx.utils.ObjectUtil; - public class ComplexSortField extends SortField + public class ComplexSortField extends SortField implements IComplexSortField { private var _nameParts:Array; @@ -30,12 +30,17 @@ package mx.collections { numeric:Object = null) { super(name, caseInsensitive, descending, numeric); - _nameParts = name.split("."); + _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]); + return object && nameParts && nameParts.length && object.hasOwnProperty(nameParts[0]); } override protected function getSortFieldValue(obj:Object):* http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/cf657841/frameworks/projects/framework/src/mx/collections/IComplexSortField.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/framework/src/mx/collections/IComplexSortField.as b/frameworks/projects/framework/src/mx/collections/IComplexSortField.as new file mode 100644 index 0000000..dffb216 --- /dev/null +++ b/frameworks/projects/framework/src/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; + } +} http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/cf657841/frameworks/projects/framework/src/mx/collections/ListCollectionView.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/framework/src/mx/collections/ListCollectionView.as b/frameworks/projects/framework/src/mx/collections/ListCollectionView.as index 307749a..f322139 100644 --- a/frameworks/projects/framework/src/mx/collections/ListCollectionView.as +++ b/frameworks/projects/framework/src/mx/collections/ListCollectionView.as @@ -26,6 +26,8 @@ package mx.collections import flash.utils.flash_proxy; import flash.utils.getQualifiedClassName; + import mx.binding.utils.BindingUtils; + import mx.binding.utils.ChangeWatcher; import mx.collections.errors.CollectionViewError; import mx.collections.errors.ItemPendingError; import mx.collections.errors.SortError; @@ -98,6 +100,8 @@ public class ListCollectionView extends Proxy // //-------------------------------------------------------------------------- + private var _complexFieldWatchers:Vector.<ChangeWatcher> = new Vector.<ChangeWatcher>(); + /** * @private * Internal event dispatcher. @@ -373,11 +377,59 @@ public class ListCollectionView extends Proxy */ public function set sort(s:ISort):void { + if(_sort && _sort != s) + stopWatchingForComplexFieldChanges(); + _sort = s; - + + if(_sort && _sort.fields) + startWatchingForComplexFieldChanges(_sort.fields); + dispatchEvent(new Event("sortChanged")); } + private function stopWatchingForComplexFieldChanges():void + { + for each(var watcher:ChangeWatcher in _complexFieldWatchers) + { + watcher.unwatch(); + } + + _complexFieldWatchers.length = 0; + } + + private function startWatchingForComplexFieldChanges(fields:Array):void + { + for(var i:int = 0; i < fields.length; i++) + { + var sortField:IComplexSortField = fields[i] as IComplexSortField; + if(sortField && sortField.nameParts) + { + for(var j:int = 0; j < this.length; j++) + { + var item:Object = this.getItemAt(j); + if(item) + { + var watcher:ChangeWatcher = BindingUtils.bindSetter(function(value:Object):void {}, item, sortField.nameParts); + if(watcher) + { + watcher.setHandler(new Closure(item, complexValueChanged).callFunctionOnObject); + _complexFieldWatchers.push(watcher); + } + } + } + } + } + } + + private function complexValueChanged(item:Object):void + { + if(filterFunction != null || sort) + { + moveItemInView(item); + } + } + //-------------------------------------------------------------------------- // // ICollectionView Methods @@ -1837,6 +1889,7 @@ public class ListCollectionView extends Proxy } +import flash.events.Event; import flash.events.EventDispatcher; import mx.collections.*; @@ -2701,3 +2754,20 @@ class ListCollectionViewBookmark extends CursorBookmark return view.getBookmarkIndex(this); } } + +class Closure +{ + private var _object:Object; + private var _function:Function; + + public function Closure(cachedObject:Object, cachedFunction:Function) + { + _object = cachedObject; + _function = cachedFunction; + } + + public function callFunctionOnObject(event:Event):void + { + _function.apply(null, [_object]); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/cf657841/frameworks/projects/framework/tests/FLEX_34854_Tests.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/framework/tests/FLEX_34854_Tests.as b/frameworks/projects/framework/tests/FLEX_34854_Tests.as index 7acce5e..e60fe22 100644 --- a/frameworks/projects/framework/tests/FLEX_34854_Tests.as +++ b/frameworks/projects/framework/tests/FLEX_34854_Tests.as @@ -55,6 +55,28 @@ package { _sut.refresh(); //values: Object1, Object2, Object3, Object4 //when + const first:ListCollectionView_FLEX_34854_VO = _sut.getItemAt(0) as ListCollectionView_FLEX_34854_VO; + first.address.street = "Street9"; //this should immediately place the newItem at the end + + //then + const newItemIndex:int = _sut.getItemIndex(first); + assertEquals("the new item should have been placed at the end of the list as soon as its address's street name was changed", _sut.length - 1, newItemIndex); + } + + [Test] + public function test_adding_and_changing_complex_sort_field_value_places_it_correctly_according_to_collection_sort():void + { + //given + var from1To4:IList = generateVOs(5); + from1To4.removeItemAt(0); + _sut.addAll(from1To4); + + const sortByNameAscending:Sort = new Sort(); + sortByNameAscending.fields = [new ComplexSortField("address.street", false, false, false)]; + _sut.sort = sortByNameAscending; + _sut.refresh(); //values: Object1, Object2, Object3, Object4 + + //when const newItem:ListCollectionView_FLEX_34854_VO = generateOneObject(5); _sut.addItem(newItem); //values: Object1, Object2, Object3, Object4, Object5 newItem.address.street = "Street0"; //this should immediately place the newItem at position 0
