From c8f0bec40d0d98c1e4b0036ef76e644b9d1877ff Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 5 Feb 2020 14:02:27 +0100 Subject: [PATCH] Added ISelectionModel. --- src/Avalonia.Controls/ISelectionModel.cs | 47 ++++++++++++++++++++++++ src/Avalonia.Controls/SelectionModel.cs | 21 +++++------ 2 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 src/Avalonia.Controls/ISelectionModel.cs diff --git a/src/Avalonia.Controls/ISelectionModel.cs b/src/Avalonia.Controls/ISelectionModel.cs new file mode 100644 index 0000000000..aed21315bb --- /dev/null +++ b/src/Avalonia.Controls/ISelectionModel.cs @@ -0,0 +1,47 @@ +// This source file is adapted from the WinUI project. +// (https://github.com/microsoft/microsoft-ui-xaml) +// +// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation. + +using System; +using System.Collections.Generic; + +namespace Avalonia.Controls +{ + public interface ISelectionModel + { + IndexPath AnchorIndex { get; set; } + IndexPath SelectedIndex { get; set; } + IReadOnlyList SelectedIndices { get; } + object SelectedItem { get; } + IReadOnlyList SelectedItems { get; } + bool SingleSelect { get; set; } + object Source { get; set; } + + event EventHandler ChildrenRequested; + event EventHandler SelectionChanged; + + void ClearSelection(); + void Deselect(int index); + void Deselect(int groupIndex, int itemIndex); + void DeselectAt(IndexPath index); + void DeselectRange(IndexPath start, IndexPath end); + void DeselectRangeFromAnchor(int index); + void DeselectRangeFromAnchor(int endGroupIndex, int endItemIndex); + void DeselectRangeFromAnchorTo(IndexPath index); + void Dispose(); + bool? IsSelected(int index); + bool? IsSelected(int groupIndex, int itemIndex); + bool? IsSelectedAt(IndexPath index); + void Select(int index); + void Select(int groupIndex, int itemIndex); + void SelectAll(); + void SelectAt(IndexPath index); + void SelectRange(IndexPath start, IndexPath end); + void SelectRangeFromAnchor(int index); + void SelectRangeFromAnchor(int endGroupIndex, int endItemIndex); + void SelectRangeFromAnchorTo(IndexPath index); + void SetAnchorIndex(int index); + void SetAnchorIndex(int groupIndex, int index); + } +} diff --git a/src/Avalonia.Controls/SelectionModel.cs b/src/Avalonia.Controls/SelectionModel.cs index a501946365..ce8e53c994 100644 --- a/src/Avalonia.Controls/SelectionModel.cs +++ b/src/Avalonia.Controls/SelectionModel.cs @@ -12,7 +12,7 @@ using Avalonia.Controls.Utils; namespace Avalonia.Controls { - public class SelectionModel : INotifyPropertyChanged, IDisposable + public class SelectionModel : ISelectionModel, INotifyPropertyChanged, IDisposable { private readonly SelectionNode _rootNode; private bool _singleSelect; @@ -72,7 +72,6 @@ namespace Avalonia.Controls } } - public IndexPath AnchorIndex { get @@ -184,7 +183,7 @@ namespace Avalonia.Controls // the selected item at a particular index. This avoid having to create the storage and copying // needed in a dumb vector. This also allows us to expose a tree of selected nodes into an // easier to consume flat vector view of objects. - var selectedItems = new SelectedItems ( + var selectedItems = new SelectedItems( selectedInfos, (infos, index) => { @@ -284,7 +283,7 @@ namespace Avalonia.Controls _selectedIndicesCached = indices; } - return _selectedIndicesCached; + return _selectedIndicesCached; } } @@ -455,7 +454,7 @@ namespace Avalonia.Controls PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } - public void OnSelectionInvalidatedDueToCollectionChange() + internal void OnSelectionInvalidatedDueToCollectionChange() { OnSelectionChanged(); } @@ -535,7 +534,7 @@ namespace Avalonia.Controls RaisePropertyChanged(nameof(SelectedIndex)); RaisePropertyChanged(nameof(SelectedIndices)); - + if (_rootNode.Source != null) { RaisePropertyChanged(nameof(SelectedItem)); @@ -551,7 +550,7 @@ namespace Avalonia.Controls } var selected = _rootNode.Select(index, select); - + if (selected) { AnchorIndex = new IndexPath(index); @@ -569,7 +568,7 @@ namespace Avalonia.Controls var childNode = _rootNode.GetAt(groupIndex, realizeChild: true); var selected = childNode!.Select(itemIndex, select); - + if (selected) { AnchorIndex = new IndexPath(groupIndex, itemIndex); @@ -581,7 +580,7 @@ namespace Avalonia.Controls private void SelectWithPathImpl(IndexPath index, bool select, bool raiseSelectionChanged) { bool selected = false; - + if (_singleSelect) { ClearSelection(resetAnchor: true, raiseSelectionChanged: false); @@ -615,7 +614,7 @@ namespace Avalonia.Controls { int anchorIndex = 0; var anchor = AnchorIndex; - + if (anchor != null) { anchorIndex = anchor.GetAt(0); @@ -634,7 +633,7 @@ namespace Avalonia.Controls var startGroupIndex = 0; var startItemIndex = 0; var anchorIndex = AnchorIndex; - + if (anchorIndex != null) { startGroupIndex = anchorIndex.GetAt(0);