From ef0c904e91c0b6efb9e459f0b319c833ba0bce45 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 16 Jul 2024 17:00:08 +0800 Subject: [PATCH] ux: improve change list selection --- src/Models/Watcher.cs | 2 +- src/ViewModels/ChangeCollection.cs | 3 + src/ViewModels/WorkingCopy.cs | 4 + src/Views/ChangeCollectionView.axaml | 3 + src/Views/ChangeCollectionView.axaml.cs | 208 ++++++++++++++---------- 5 files changed, 132 insertions(+), 88 deletions(-) diff --git a/src/Models/Watcher.cs b/src/Models/Watcher.cs index 2a1c4cc6..f8aacecb 100644 --- a/src/Models/Watcher.cs +++ b/src/Models/Watcher.cs @@ -164,7 +164,7 @@ namespace SourceGit.Models private void OnRepositoryChanged(object o, FileSystemEventArgs e) { - if (string.IsNullOrEmpty(e.Name)) + if (string.IsNullOrEmpty(e.Name) || e.Name.EndsWith(".lock", StringComparison.Ordinal)) return; var name = e.Name.Replace("\\", "/"); diff --git a/src/ViewModels/ChangeCollection.cs b/src/ViewModels/ChangeCollection.cs index 76fca0e6..5de9f4fd 100644 --- a/src/ViewModels/ChangeCollection.cs +++ b/src/ViewModels/ChangeCollection.cs @@ -8,15 +8,18 @@ namespace SourceGit.ViewModels { public List Tree { get; set; } = new List(); public AvaloniaList Rows { get; set; } = new AvaloniaList(); + public AvaloniaList SelectedRows { get; set; } = new AvaloniaList(); } public class ChangeCollectionAsGrid { public AvaloniaList Changes { get; set; } = new AvaloniaList(); + public AvaloniaList SelectedChanges { get; set; } = new AvaloniaList(); } public class ChangeCollectionAsList { public AvaloniaList Changes { get; set; } = new AvaloniaList(); + public AvaloniaList SelectedChanges { get; set; } = new AvaloniaList(); } } diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 76031808..2980c46a 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -301,11 +301,13 @@ namespace SourceGit.ViewModels public void StageSelected() { StageChanges(_selectedUnstaged); + SelectedUnstaged = []; } public void StageAll() { StageChanges(_unstaged); + SelectedUnstaged = []; } public async void StageChanges(List changes) @@ -337,11 +339,13 @@ namespace SourceGit.ViewModels public void UnstageSelected() { UnstageChanges(_selectedStaged); + SelectedStaged = []; } public void UnstageAll() { UnstageChanges(_staged); + SelectedStaged = []; } public async void UnstageChanges(List changes) diff --git a/src/Views/ChangeCollectionView.axaml b/src/Views/ChangeCollectionView.axaml index 664b9be8..1b365ff7 100644 --- a/src/Views/ChangeCollectionView.axaml +++ b/src/Views/ChangeCollectionView.axaml @@ -31,6 +31,7 @@ @@ -65,6 +66,7 @@ @@ -93,6 +95,7 @@ diff --git a/src/Views/ChangeCollectionView.axaml.cs b/src/Views/ChangeCollectionView.axaml.cs index d59e191a..d77bf62a 100644 --- a/src/Views/ChangeCollectionView.axaml.cs +++ b/src/Views/ChangeCollectionView.axaml.cs @@ -6,6 +6,7 @@ using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Interactivity; +using Avalonia.Threading; using Avalonia.VisualTree; namespace SourceGit.Views @@ -101,7 +102,7 @@ namespace SourceGit.Views public void ToggleNodeIsExpanded(ViewModels.ChangeTreeNode node) { - if (_displayContext is ViewModels.ChangeCollectionAsTree tree) + if (Content is ViewModels.ChangeCollectionAsTree tree) { node.IsExpanded = !node.IsExpanded; @@ -136,92 +137,12 @@ namespace SourceGit.Views { base.OnPropertyChanged(change); - if (change.Property == ViewModeProperty || change.Property == ChangesProperty) - { - _disableSelectionChangingEvent = change.Property == ChangesProperty; - var changes = Changes; - if (changes == null || changes.Count == 0) - { - Content = null; - _displayContext = null; - _disableSelectionChangingEvent = false; - return; - } - - if (ViewMode == Models.ChangeViewMode.Tree) - { - HashSet oldFolded = new HashSet(); - if (_displayContext is ViewModels.ChangeCollectionAsTree oldTree) - { - foreach (var row in oldTree.Rows) - { - if (row.IsFolder && !row.IsExpanded) - oldFolded.Add(row.FullPath); - } - } - - var tree = new ViewModels.ChangeCollectionAsTree(); - tree.Tree = ViewModels.ChangeTreeNode.Build(changes, oldFolded); - - var rows = new List(); - MakeTreeRows(rows, tree.Tree); - tree.Rows.AddRange(rows); - _displayContext = tree; - } - else if (ViewMode == Models.ChangeViewMode.Grid) - { - var grid = new ViewModels.ChangeCollectionAsGrid(); - grid.Changes.AddRange(changes); - _displayContext = grid; - } - else - { - var list = new ViewModels.ChangeCollectionAsList(); - list.Changes.AddRange(changes); - _displayContext = list; - } - - Content = _displayContext; - _disableSelectionChangingEvent = false; - } + if (change.Property == ViewModeProperty) + UpdateDataSource(false); + else if (change.Property == ChangesProperty) + UpdateDataSource(true); else if (change.Property == SelectedChangesProperty) - { - if (_disableSelectionChangingEvent) - return; - - var list = this.FindDescendantOfType(); - if (list == null) - return; - - _disableSelectionChangingEvent = true; - - var selected = SelectedChanges; - if (selected == null || selected.Count == 0) - { - list.SelectedItem = null; - } - else if (_displayContext is ViewModels.ChangeCollectionAsTree tree) - { - var sets = new HashSet(); - foreach (var c in selected) - sets.Add(c); - - var nodes = new List(); - foreach (var row in tree.Rows) - { - if (row.Change != null && sets.Contains(row.Change)) - nodes.Add(row); - } - - list.SelectedItems = nodes; - } - else - { - list.SelectedItems = selected; - } - - _disableSelectionChangingEvent = false; - } + UpdateSelection(); } private void OnRowDoubleTapped(object sender, TappedEventArgs e) @@ -283,6 +204,120 @@ namespace SourceGit.Views } } + private void UpdateDataSource(bool disableEvents) + { + _disableSelectionChangingEvent = disableEvents; + + var changes = Changes; + if (changes == null || changes.Count == 0) + { + Content = null; + _disableSelectionChangingEvent = false; + return; + } + + var selected = SelectedChanges ?? []; + if (ViewMode == Models.ChangeViewMode.Tree) + { + HashSet oldFolded = new HashSet(); + if (Content is ViewModels.ChangeCollectionAsTree oldTree) + { + foreach (var row in oldTree.Rows) + { + if (row.IsFolder && !row.IsExpanded) + oldFolded.Add(row.FullPath); + } + } + + var tree = new ViewModels.ChangeCollectionAsTree(); + tree.Tree = ViewModels.ChangeTreeNode.Build(changes, oldFolded); + + var rows = new List(); + MakeTreeRows(rows, tree.Tree); + tree.Rows.AddRange(rows); + + if (selected.Count > 0) + { + var sets = new HashSet(); + foreach (var c in selected) + sets.Add(c); + + var nodes = new List(); + foreach (var row in tree.Rows) + { + if (row.Change != null && sets.Contains(row.Change)) + nodes.Add(row); + } + + tree.SelectedRows.AddRange(nodes); + } + + Content = tree; + } + else if (ViewMode == Models.ChangeViewMode.Grid) + { + var grid = new ViewModels.ChangeCollectionAsGrid(); + grid.Changes.AddRange(changes); + if (selected.Count > 0) + grid.SelectedChanges.AddRange(selected); + Content = grid; + } + else + { + var list = new ViewModels.ChangeCollectionAsList(); + list.Changes.AddRange(changes); + if (selected.Count > 0) + list.SelectedChanges.AddRange(selected); + Content = list; + } + + _disableSelectionChangingEvent = false; + } + + private void UpdateSelection() + { + if (_disableSelectionChangingEvent) + return; + + _disableSelectionChangingEvent = true; + + var selected = SelectedChanges ?? []; + if (Content is ViewModels.ChangeCollectionAsTree tree) + { + tree.SelectedRows.Clear(); + + if (selected.Count > 0) + { + var sets = new HashSet(); + foreach (var c in selected) + sets.Add(c); + + var nodes = new List(); + foreach (var row in tree.Rows) + { + if (row.Change != null && sets.Contains(row.Change)) + nodes.Add(row); + } + + tree.SelectedRows.AddRange(nodes); + } + } + else if (Content is ViewModels.ChangeCollectionAsGrid grid) + { + grid.SelectedChanges.Clear(); + if (selected.Count > 0) + grid.SelectedChanges.AddRange(selected); + } + else if (Content is ViewModels.ChangeCollectionAsList list) + { + list.SelectedChanges.Clear(); + if (selected.Count > 0) + list.SelectedChanges.AddRange(selected); + } + + _disableSelectionChangingEvent = false; + } + private void CollectChangesInNode(List outs, ViewModels.ChangeTreeNode node) { if (node.IsFolder) @@ -324,6 +359,5 @@ namespace SourceGit.Views } private bool _disableSelectionChangingEvent = false; - private object _displayContext = null; } }