diff options
author | Eric Maupin <me@ermau.com> | 2019-02-26 22:02:26 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-26 22:02:26 +0300 |
commit | 94afbbdb281b229ee35f6d119c856dc84a7aeea8 (patch) | |
tree | f8d6bfa22ae212047176ffbfdfd9b924c5c3e414 | |
parent | 5e9aefc24f558f731c327b48febb7c76b53317d3 (diff) | |
parent | 4a2adca8b44173dc9c141b25d40c87fc7b36d75b (diff) |
Merge pull request #538 from xamarin/ermau-type-selector-fixes
Object editor / type selector fixes
4 files changed, 113 insertions, 11 deletions
diff --git a/Xamarin.PropertyEditing.Tests/ObjectPropertyViewModelTests.cs b/Xamarin.PropertyEditing.Tests/ObjectPropertyViewModelTests.cs index ef3e438..cedf835 100644 --- a/Xamarin.PropertyEditing.Tests/ObjectPropertyViewModelTests.cs +++ b/Xamarin.PropertyEditing.Tests/ObjectPropertyViewModelTests.cs @@ -256,6 +256,41 @@ namespace Xamarin.PropertyEditing.Tests Assert.That (vm.ValueType, Is.Null); } + [Test] + public void ReturnedNullTypeCancels () + { + object value = new object (); + var p = CreatePropertyMock ("prop"); + var childsubInfo = GetTypeInfo (typeof (SubChildClass)); + var editor = new MockObjectEditor (new[] { p.Object }, new Dictionary<IPropertyInfo, IReadOnlyList<ITypeInfo>> { + { + p.Object, + new[] { + GetTypeInfo (typeof(ChildClass)), + childsubInfo + } + } + }); + + var providerMock = CreateProviderMock (value, new MockObjectEditor { Target = value }); + var vm = new ObjectPropertyViewModel (new TargetPlatform (providerMock.Object), p.Object, new[] { editor }); + + var tcs = new TaskCompletionSource<ITypeInfo> (); + bool requested = false; + vm.TypeRequested += (sender, args) => { + requested = true; + args.SelectedType = tcs.Task; + }; + + Assume.That (vm.CreateInstanceCommand.CanExecute (childsubInfo), Is.True); + vm.CreateInstanceCommand.Execute (null); + Assume.That (requested, Is.True); + + tcs.SetResult (null); + + providerMock.Verify (ep => ep.CreateObjectAsync (null), Times.Never); + } + private TestContext syncContext; private Mock<IEditorProvider> CreateProviderMock (object value, IObjectEditor editor) diff --git a/Xamarin.PropertyEditing.Tests/SimpleCollectionViewTests.cs b/Xamarin.PropertyEditing.Tests/SimpleCollectionViewTests.cs index 1a54640..cb13ad8 100644 --- a/Xamarin.PropertyEditing.Tests/SimpleCollectionViewTests.cs +++ b/Xamarin.PropertyEditing.Tests/SimpleCollectionViewTests.cs @@ -756,6 +756,50 @@ namespace Xamarin.PropertyEditing.Tests Assert.Throws<ArgumentOutOfRangeException> (() => view[2].ToString(), "this[] didn't throw out of range on filtered out item"); } + [Test] + [Description ("Covers #522, empty parents now unfiltered by their own filter shouldn't be added")] + public void ParentFilterChangesOnEmpty () + { + var parents = new ObservableCollection<TestNode> { + new TestNode ("A") { + Children = new List<TestNode> { + new TestNode ("A child") + } + }, + new TestNode ("Baz") { + Children = new List<TestNode> { + new TestNode ("Baz child") + } + }, + new TestNode ("Bar") { + Children = new List<TestNode> { + new TestNode ("Bar child") + } + }, + }; + + var view = new SimpleCollectionView (parents, new SimpleCollectionViewOptions { + DisplaySelector = TestNodeDisplaySelector, + ChildrenSelector = TestNodeChildrenSelector, + ChildOptions = new SimpleCollectionViewOptions { + DisplaySelector = TestNodeDisplaySelector + } + }); + + Assume.That (view.Count, Is.EqualTo (3)); + + view.Options.Filter = o => ((TestNode) o).Key != "Bar"; + Assume.That (view.Count, Is.EqualTo (2)); + + view.Options.ChildOptions.Filter = o => ((TestNode) o).Key.StartsWith ("A"); + Assume.That (view.Count, Is.EqualTo (1)); + + view.Options.Filter = null; + + Assert.That (((KeyValuePair<string, SimpleCollectionView>) view[0]).Key, Is.EqualTo (parents[0].Key)); + Assert.That (view.Count, Is.EqualTo (1)); + } + private IEnumerable TestNodeChildrenSelector (object o) { return ((TestNode)o).Children; diff --git a/Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs b/Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs index f31b992..5f0f65c 100644 --- a/Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs +++ b/Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs @@ -164,7 +164,9 @@ namespace Xamarin.PropertyEditing.ViewModels try { selectedType = await args.SelectedType; - } catch (OperationCanceledException) { + if (selectedType == null) + return; + } catch (OperationCanceledException) { return; } } diff --git a/Xamarin.PropertyEditing/ViewModels/SimpleCollectionView.cs b/Xamarin.PropertyEditing/ViewModels/SimpleCollectionView.cs index de6435f..3339bf2 100644 --- a/Xamarin.PropertyEditing/ViewModels/SimpleCollectionView.cs +++ b/Xamarin.PropertyEditing/ViewModels/SimpleCollectionView.cs @@ -127,8 +127,6 @@ namespace Xamarin.PropertyEditing.ViewModels public bool HasChildElements => (this.filtered.Count > 0); - public bool IsFiltering => Options?.Filter != null; - public bool Contains (object value) { return IndexOf (value) != -1; @@ -289,7 +287,11 @@ namespace Xamarin.PropertyEditing.ViewModels private bool MatchesFilter (Element element) { - if (!IsFiltering) + if (!GetIsFiltering()) + return true; + if (element.ChildrenView != null && !element.ChildrenView.HasChildElements) + return false; + if (Options.Filter == null) return true; return Options.Filter (element.Item); @@ -297,7 +299,7 @@ namespace Xamarin.PropertyEditing.ViewModels private void FilterCore (bool notify = true, bool isPureSubset = false) { - if (!IsFiltering) { + if (!GetIsFiltering()) { if (this.arranged.Count == this.filtered.Count) return; } @@ -312,8 +314,7 @@ namespace Xamarin.PropertyEditing.ViewModels var toRemove = new List<string>(); foreach (var kvp in this.filtered) { - var childView = kvp.Value.ChildrenView; - if ((childView != null && !childView.HasChildElements) || !MatchesFilter (kvp.Value)) { + if (!MatchesFilter (kvp.Value)) { toRemove.Add (kvp.Key); } } @@ -324,7 +325,7 @@ namespace Xamarin.PropertyEditing.ViewModels var toAdd = new List<string> (filteredOut.Count); foreach (string key in filteredOut) { Element e = this.arranged[key]; - if (!IsFiltering || Options.Filter (e.Item)) + if (MatchesFilter (e)) toAdd.Add (key); } toAdd.Sort (Comparer); @@ -435,8 +436,6 @@ namespace Xamarin.PropertyEditing.ViewModels this.arranged.Clear(); this.filtered.Clear(); - bool filtering = IsFiltering; - foreach (var sourceItem in this.source.Cast<object>().Select (o => new { Item = o, Key = GetKey (o) }).OrderBy (e => e.Key, Comparer)) { Element e = new Element { Item = sourceItem.Item @@ -453,7 +452,7 @@ namespace Xamarin.PropertyEditing.ViewModels e.ChildrenView = new SimpleCollectionView (children, Options.ChildOptions, this, sourceItem.Key, sourceItem.Item); } - if (!filtering || this.options.Filter (e.Item)) + if (MatchesFilter (e)) this.filtered.Add (sourceItem.Key, e); } @@ -499,5 +498,27 @@ namespace Xamarin.PropertyEditing.ViewModels } } } + + private bool GetIsFiltering () + { + // Generally our hierarchy is at max 3 levels deep, this can be cached if we find it problematic + SimpleCollectionView parent = this; + while (parent != null) { + if (parent.Options?.Filter != null) + return true; + + parent = parent.parent; + } + + SimpleCollectionViewOptions childOptions = Options.ChildOptions; + while (childOptions != null) { + if (childOptions.Filter != null) + return true; + + childOptions = childOptions.ChildOptions; + } + + return false; + } } } |