From 96fbd6c531313dc0ab9fc3eeb7265a693b58e75f Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 15 Feb 2020 23:55:21 +0100 Subject: [PATCH] Don't only select leaf nodes from SelectRange. Related issues: https://github.com/microsoft/microsoft-ui-xaml/issues/1969 https://github.com/microsoft/microsoft-ui-xaml/issues/1984 --- src/Avalonia.Controls/SelectionModel.cs | 6 +- .../SelectionModelTests.cs | 81 ++++++++++++++----- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/src/Avalonia.Controls/SelectionModel.cs b/src/Avalonia.Controls/SelectionModel.cs index a2b080efc4..d41593b4eb 100644 --- a/src/Avalonia.Controls/SelectionModel.cs +++ b/src/Avalonia.Controls/SelectionModel.cs @@ -759,11 +759,7 @@ namespace Avalonia.Controls winrtEnd, info => { - if (info.Node.DataCount == 0) - { - // Select only leaf nodes - info.ParentNode!.Select(info.Path.GetAt(info.Path.GetSize() - 1), select); - } + info.ParentNode!.Select(info.Path.GetAt(info.Path.GetSize() - 1), select); }); } diff --git a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs index bbba360a44..0769df5b48 100644 --- a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs @@ -305,16 +305,19 @@ namespace Avalonia.Controls.UnitTests ValidateSelection(selectionModel, new List() { + Path(1, 0), + Path(1, 1), + Path(1, 0, 1), Path(1, 0, 1, 0), Path(1, 0, 1, 1), Path(1, 0, 1, 2), Path(1, 0, 1, 3), - Path(1, 0, 1), + Path(1, 1, 0), + Path(1, 1, 1), Path(1, 1, 0, 0), Path(1, 1, 0, 1), Path(1, 1, 0, 2), Path(1, 1, 0, 3), - Path(1, 1, 0), Path(1, 1, 1, 0), }, new List() @@ -324,8 +327,7 @@ namespace Avalonia.Controls.UnitTests Path(1, 0), Path(1, 1), Path(1, 1, 1), - }, - 2 /* selectedInnerNodes */); + }); ClearSelection(selectionModel); ValidateSelection(selectionModel, new List() { }); @@ -337,16 +339,20 @@ namespace Avalonia.Controls.UnitTests ValidateSelection(selectionModel, new List() { - Path(0, 0, 0, 2), - Path(0, 0, 0, 3), - Path(0, 0, 1, 0), - Path(0, 0, 1, 1), - Path(0, 0, 1, 2), - Path(0, 0, 1, 3), - Path(0, 0, 1), - Path(0, 1, 0, 0), - Path(0, 1, 0, 1), - Path(0, 1, 0, 2), + Path(0, 0), + Path(0, 1), + Path(0, 0, 0), + Path(0, 0, 1), + Path(0, 0, 0, 2), + Path(0, 0, 0, 3), + Path(0, 0, 1, 0), + Path(0, 0, 1, 1), + Path(0, 0, 1, 2), + Path(0, 0, 1, 3), + Path(0, 1, 0), + Path(0, 1, 0, 0), + Path(0, 1, 0, 1), + Path(0, 1, 0, 2), }, new List() { @@ -356,8 +362,7 @@ namespace Avalonia.Controls.UnitTests Path(0, 0, 0), Path(0, 1), Path(0, 1, 0), - }, - 1 /* selectedInnerNodes */); + }); startPath = Path(0, 1, 0, 2); SetAnchorIndex(selectionModel, startPath); @@ -853,10 +858,11 @@ namespace Avalonia.Controls.UnitTests ValidateSelection(selectionModel, new List() { + Path(0), + Path(1), Path(0, 0), Path(0, 1), Path(0, 2), - Path(0), Path(1, 0), Path(1, 1) }, @@ -864,8 +870,7 @@ namespace Avalonia.Controls.UnitTests { Path(), Path(1) - }, - 1 /* selectedInnerNodes */); + }); } [Fact] @@ -1271,7 +1276,7 @@ namespace Avalonia.Controls.UnitTests target.SelectionChanged += (s, e) => { Assert.Empty(e.DeselectedIndices); - Assert.Equal(new object[] { 0, 1, 2 }, e.DeselectedItems); + Assert.Equal(new object[] { new AvaloniaList { 0, 1, 2 }, 0, 1, 2 }, e.DeselectedItems); Assert.Empty(e.SelectedIndices); Assert.Empty(e.SelectedItems); ++raised; @@ -1371,6 +1376,38 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(0, GetSubscriberCount(toRemove)); } + [Fact] + public void SelectRange_Behaves_The_Same_As_Multiple_Selects() + { + var data = new[] { 1, 2, 3 }; + var target = new SelectionModel { Source = data }; + + target.Select(1); + + Assert.Equal(new[] { IndexPath.CreateFrom(1) }, target.SelectedIndices); + + target.ClearSelection(); + target.SelectRange(new IndexPath(1), new IndexPath(1)); + + Assert.Equal(new[] { IndexPath.CreateFrom(1) }, target.SelectedIndices); + } + + [Fact] + public void SelectRange_Behaves_The_Same_As_Multiple_Selects_Nested() + { + var data = CreateNestedData(3, 2, 2); + var target = new SelectionModel { Source = data }; + + target.Select(1); + + Assert.Equal(new[] { IndexPath.CreateFrom(1) }, target.SelectedIndices); + + target.ClearSelection(); + target.SelectRange(new IndexPath(1), new IndexPath(1)); + + Assert.Equal(new[] { IndexPath.CreateFrom(1) }, target.SelectedIndices); + } + [Fact] public void Should_Not_Treat_Strings_As_Nested_Selections() { @@ -2005,7 +2042,7 @@ namespace Avalonia.Controls.UnitTests foreach (var index in allIndices) { bool? isSelected = selectionModel.IsSelectedAt(index); - if (Contains(expectedSelected, index)) + if (Contains(expectedSelected, index) && !Contains(expectedPartialSelected, index)) { Assert.True(isSelected.Value, index + " is Selected"); } @@ -2037,7 +2074,7 @@ namespace Avalonia.Controls.UnitTests if (expectedSelected.Count > 0) { _output.WriteLine("SelectedIndex is " + selectionModel.SelectedIndex); - Assert.Equal(0, selectionModel.SelectedIndex.CompareTo(expectedSelected[0])); + Assert.Equal(expectedSelected[0], selectionModel.SelectedIndex); if (selectionModel.Source != null) { Assert.Equal(selectionModel.SelectedItem, GetData(selectionModel, expectedSelected[0]));