2024-05-28 06:19:53 -07:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
using Avalonia;
|
2024-07-12 02:14:52 -07:00
|
|
|
using Avalonia.Collections;
|
2024-05-28 06:19:53 -07:00
|
|
|
using Avalonia.Controls;
|
2024-07-12 02:14:52 -07:00
|
|
|
using Avalonia.Controls.Primitives;
|
|
|
|
using Avalonia.Input;
|
2024-05-28 06:19:53 -07:00
|
|
|
using Avalonia.Interactivity;
|
2024-07-12 02:14:52 -07:00
|
|
|
using Avalonia.VisualTree;
|
|
|
|
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
2024-05-28 06:19:53 -07:00
|
|
|
|
|
|
|
namespace SourceGit.Views
|
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
public class ChangeTreeNode : ObservableObject
|
2024-06-07 01:32:06 -07:00
|
|
|
{
|
|
|
|
public string FullPath { get; set; } = string.Empty;
|
2024-07-12 02:14:52 -07:00
|
|
|
public int Depth { get; private set; } = 0;
|
2024-06-07 01:32:06 -07:00
|
|
|
public Models.Change Change { get; set; } = null;
|
|
|
|
public List<ChangeTreeNode> Children { get; set; } = new List<ChangeTreeNode>();
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
public bool IsFolder
|
|
|
|
{
|
|
|
|
get => Change == null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool IsExpanded
|
|
|
|
{
|
|
|
|
get => _isExpanded;
|
|
|
|
set => SetProperty(ref _isExpanded, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChangeTreeNode(Models.Change c, int depth)
|
|
|
|
{
|
|
|
|
FullPath = c.Path;
|
|
|
|
Depth = depth;
|
|
|
|
Change = c;
|
|
|
|
IsExpanded = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChangeTreeNode(string path, bool isExpanded, int depth)
|
|
|
|
{
|
|
|
|
FullPath = path;
|
|
|
|
Depth = depth;
|
|
|
|
IsExpanded = isExpanded;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static List<ChangeTreeNode> Build(IList<Models.Change> changes, HashSet<string> folded)
|
2024-06-07 01:32:06 -07:00
|
|
|
{
|
|
|
|
var nodes = new List<ChangeTreeNode>();
|
|
|
|
var folders = new Dictionary<string, ChangeTreeNode>();
|
|
|
|
|
|
|
|
foreach (var c in changes)
|
|
|
|
{
|
|
|
|
var sepIdx = c.Path.IndexOf('/', StringComparison.Ordinal);
|
|
|
|
if (sepIdx == -1)
|
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
nodes.Add(new ChangeTreeNode(c, 0));
|
2024-06-07 01:32:06 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ChangeTreeNode lastFolder = null;
|
|
|
|
var start = 0;
|
2024-07-12 02:14:52 -07:00
|
|
|
var depth = 0;
|
2024-06-07 01:32:06 -07:00
|
|
|
|
|
|
|
while (sepIdx != -1)
|
|
|
|
{
|
|
|
|
var folder = c.Path.Substring(0, sepIdx);
|
|
|
|
if (folders.TryGetValue(folder, out var value))
|
|
|
|
{
|
|
|
|
lastFolder = value;
|
|
|
|
}
|
|
|
|
else if (lastFolder == null)
|
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
lastFolder = new ChangeTreeNode(folder, !folded.Contains(folder), depth);
|
2024-06-07 01:32:06 -07:00
|
|
|
folders.Add(folder, lastFolder);
|
|
|
|
InsertFolder(nodes, lastFolder);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
var cur = new ChangeTreeNode(folder, !folded.Contains(folder), depth);
|
2024-06-07 01:32:06 -07:00
|
|
|
folders.Add(folder, cur);
|
|
|
|
InsertFolder(lastFolder.Children, cur);
|
|
|
|
lastFolder = cur;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = sepIdx + 1;
|
2024-07-12 02:14:52 -07:00
|
|
|
depth++;
|
2024-06-07 01:32:06 -07:00
|
|
|
sepIdx = c.Path.IndexOf('/', start);
|
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
lastFolder.Children.Add(new ChangeTreeNode(c, depth));
|
2024-06-07 01:32:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
Sort(nodes);
|
|
|
|
|
2024-06-07 01:32:06 -07:00
|
|
|
folders.Clear();
|
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void InsertFolder(List<ChangeTreeNode> collection, ChangeTreeNode subFolder)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < collection.Count; i++)
|
|
|
|
{
|
|
|
|
if (!collection[i].IsFolder)
|
|
|
|
{
|
|
|
|
collection.Insert(i, subFolder);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
collection.Add(subFolder);
|
|
|
|
}
|
2024-07-12 02:14:52 -07:00
|
|
|
|
|
|
|
private static void Sort(List<ChangeTreeNode> nodes)
|
|
|
|
{
|
|
|
|
foreach (var node in nodes)
|
|
|
|
{
|
|
|
|
if (node.IsFolder)
|
|
|
|
Sort(node.Children);
|
|
|
|
}
|
|
|
|
|
|
|
|
nodes.Sort((l, r) =>
|
|
|
|
{
|
|
|
|
if (l.IsFolder)
|
|
|
|
return r.IsFolder ? string.Compare(l.FullPath, r.FullPath, StringComparison.Ordinal) : -1;
|
|
|
|
return r.IsFolder ? 1 : string.Compare(l.FullPath, r.FullPath, StringComparison.Ordinal);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool _isExpanded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public class ChangeCollectionAsTree
|
|
|
|
{
|
|
|
|
public List<ChangeTreeNode> Tree { get; set; } = new List<ChangeTreeNode>();
|
|
|
|
public AvaloniaList<ChangeTreeNode> Rows { get; set; } = new AvaloniaList<ChangeTreeNode>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public class ChangeCollectionAsGrid
|
|
|
|
{
|
|
|
|
public AvaloniaList<Models.Change> Changes { get; set; } = new AvaloniaList<Models.Change>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public class ChangeCollectionAsList
|
|
|
|
{
|
|
|
|
public AvaloniaList<Models.Change> Changes { get; set; } = new AvaloniaList<Models.Change>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public class ChangeTreeNodeToggleButton : ToggleButton
|
|
|
|
{
|
|
|
|
protected override Type StyleKeyOverride => typeof(ToggleButton);
|
|
|
|
|
|
|
|
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
|
|
|
{
|
|
|
|
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed &&
|
|
|
|
DataContext is ChangeTreeNode { IsFolder: true } node)
|
|
|
|
{
|
|
|
|
var tree = this.FindAncestorOfType<ChangeCollectionView>();
|
|
|
|
tree.ToggleNodeIsExpanded(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class ChangeCollectionContainer : ListBox
|
|
|
|
{
|
|
|
|
protected override Type StyleKeyOverride => typeof(ListBox);
|
|
|
|
|
|
|
|
protected override void OnKeyDown(KeyEventArgs e)
|
|
|
|
{
|
|
|
|
if (e.Key != Key.Space)
|
|
|
|
base.OnKeyDown(e);
|
|
|
|
}
|
2024-06-07 01:32:06 -07:00
|
|
|
}
|
|
|
|
|
2024-05-28 06:19:53 -07:00
|
|
|
public partial class ChangeCollectionView : UserControl
|
|
|
|
{
|
|
|
|
public static readonly StyledProperty<bool> IsWorkingCopyChangeProperty =
|
2024-05-31 21:13:57 -07:00
|
|
|
AvaloniaProperty.Register<ChangeCollectionView, bool>(nameof(IsWorkingCopyChange), false);
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-05-31 21:13:57 -07:00
|
|
|
public bool IsWorkingCopyChange
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
|
|
|
get => GetValue(IsWorkingCopyChangeProperty);
|
|
|
|
set => SetValue(IsWorkingCopyChangeProperty, value);
|
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
public static readonly StyledProperty<SelectionMode> SelectionModeProperty =
|
|
|
|
AvaloniaProperty.Register<ChangeCollectionView, SelectionMode>(nameof(SelectionMode), SelectionMode.Single);
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
public SelectionMode SelectionMode
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
get => GetValue(SelectionModeProperty);
|
|
|
|
set => SetValue(SelectionModeProperty, value);
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public static readonly StyledProperty<Models.ChangeViewMode> ViewModeProperty =
|
|
|
|
AvaloniaProperty.Register<ChangeCollectionView, Models.ChangeViewMode>(nameof(ViewMode), Models.ChangeViewMode.Tree);
|
|
|
|
|
|
|
|
public Models.ChangeViewMode ViewMode
|
|
|
|
{
|
|
|
|
get => GetValue(ViewModeProperty);
|
|
|
|
set => SetValue(ViewModeProperty, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static readonly StyledProperty<List<Models.Change>> ChangesProperty =
|
|
|
|
AvaloniaProperty.Register<ChangeCollectionView, List<Models.Change>>(nameof(Changes), null);
|
|
|
|
|
|
|
|
public List<Models.Change> Changes
|
|
|
|
{
|
|
|
|
get => GetValue(ChangesProperty);
|
|
|
|
set => SetValue(ChangesProperty, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static readonly StyledProperty<List<Models.Change>> SelectedChangesProperty =
|
|
|
|
AvaloniaProperty.Register<ChangeCollectionView, List<Models.Change>>(nameof(SelectedChanges), null);
|
|
|
|
|
|
|
|
public List<Models.Change> SelectedChanges
|
|
|
|
{
|
|
|
|
get => GetValue(SelectedChangesProperty);
|
|
|
|
set => SetValue(SelectedChangesProperty, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static readonly RoutedEvent<RoutedEventArgs> ChangeDoubleTappedEvent =
|
|
|
|
RoutedEvent.Register<ChangeCollectionView, RoutedEventArgs>(nameof(ChangeDoubleTapped), RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
|
|
|
|
|
|
|
|
public event EventHandler<RoutedEventArgs> ChangeDoubleTapped
|
|
|
|
{
|
|
|
|
add { AddHandler(ChangeDoubleTappedEvent, value); }
|
|
|
|
remove { RemoveHandler(ChangeDoubleTappedEvent, value); }
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChangeCollectionView()
|
|
|
|
{
|
|
|
|
InitializeComponent();
|
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
public void ToggleNodeIsExpanded(ChangeTreeNode node)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
if (_displayContext is ChangeCollectionAsTree tree)
|
|
|
|
{
|
|
|
|
node.IsExpanded = !node.IsExpanded;
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
var depth = node.Depth;
|
|
|
|
var idx = tree.Rows.IndexOf(node);
|
|
|
|
if (idx == -1)
|
|
|
|
return;
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
if (node.IsExpanded)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
var subrows = new List<ChangeTreeNode>();
|
|
|
|
MakeTreeRows(subrows, node.Children);
|
|
|
|
tree.Rows.InsertRange(idx + 1, subrows);
|
|
|
|
}
|
|
|
|
else
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
var removeCount = 0;
|
|
|
|
for (int i = idx + 1; i < tree.Rows.Count; i++)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
var row = tree.Rows[i];
|
|
|
|
if (row.Depth <= depth)
|
|
|
|
break;
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
removeCount++;
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
2024-07-12 02:14:52 -07:00
|
|
|
tree.Rows.RemoveRange(idx + 1, removeCount);
|
|
|
|
}
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
2024-07-12 02:14:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
|
|
{
|
|
|
|
base.OnPropertyChanged(change);
|
|
|
|
|
|
|
|
if (change.Property == ViewModeProperty || change.Property == ChangesProperty)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
_disableSelectionChangingEvent = change.Property == ChangesProperty;
|
|
|
|
var changes = Changes;
|
|
|
|
if (changes == null || changes.Count == 0)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
Content = null;
|
|
|
|
_displayContext = null;
|
|
|
|
_disableSelectionChangingEvent = false;
|
|
|
|
return;
|
|
|
|
}
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
if (ViewMode == Models.ChangeViewMode.Tree)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
HashSet<string> oldFolded = new HashSet<string>();
|
|
|
|
if (_displayContext is ChangeCollectionAsTree oldTree)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
foreach (var row in oldTree.Rows)
|
|
|
|
{
|
|
|
|
if (row.IsFolder && !row.IsExpanded)
|
|
|
|
oldFolded.Add(row.FullPath);
|
|
|
|
}
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
var tree = new ChangeCollectionAsTree();
|
|
|
|
tree.Tree = ChangeTreeNode.Build(changes, oldFolded);
|
|
|
|
|
|
|
|
var rows = new List<ChangeTreeNode>();
|
|
|
|
MakeTreeRows(rows, tree.Tree);
|
|
|
|
tree.Rows.AddRange(rows);
|
|
|
|
_displayContext = tree;
|
|
|
|
}
|
|
|
|
else if (ViewMode == Models.ChangeViewMode.Grid)
|
|
|
|
{
|
|
|
|
var grid = new ChangeCollectionAsGrid();
|
|
|
|
grid.Changes.AddRange(changes);
|
|
|
|
_displayContext = grid;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var list = new ChangeCollectionAsList();
|
|
|
|
list.Changes.AddRange(changes);
|
|
|
|
_displayContext = list;
|
|
|
|
}
|
|
|
|
|
|
|
|
Content = _displayContext;
|
|
|
|
_disableSelectionChangingEvent = false;
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
2024-07-12 02:14:52 -07:00
|
|
|
else if (change.Property == SelectedChangesProperty)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
if (_disableSelectionChangingEvent)
|
|
|
|
return;
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
var list = this.FindDescendantOfType<ChangeCollectionContainer>();
|
|
|
|
if (list == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_disableSelectionChangingEvent = true;
|
|
|
|
|
|
|
|
var selected = SelectedChanges;
|
|
|
|
if (selected == null || selected.Count == 0)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
list.SelectedItem = null;
|
|
|
|
}
|
|
|
|
else if (_displayContext is ChangeCollectionAsTree tree)
|
|
|
|
{
|
|
|
|
var sets = new HashSet<Models.Change>();
|
|
|
|
foreach (var c in selected)
|
|
|
|
sets.Add(c);
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
var nodes = new List<ChangeTreeNode>();
|
|
|
|
foreach (var row in tree.Rows)
|
|
|
|
{
|
|
|
|
if (row.Change != null && sets.Contains(row.Change))
|
|
|
|
nodes.Add(row);
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
list.SelectedItems = nodes;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
list.SelectedItems = selected;
|
|
|
|
}
|
|
|
|
|
|
|
|
_disableSelectionChangingEvent = false;
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
private void OnRowDoubleTapped(object sender, TappedEventArgs e)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
var grid = sender as Grid;
|
|
|
|
if (grid.DataContext is ChangeTreeNode node)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
if (node.IsFolder)
|
|
|
|
{
|
|
|
|
var posX = e.GetPosition(this).X;
|
|
|
|
if (posX < node.Depth * 16 + 16)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ToggleNodeIsExpanded(node);
|
|
|
|
}
|
2024-05-28 06:19:53 -07:00
|
|
|
else
|
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
RaiseEvent(new RoutedEventArgs(ChangeDoubleTappedEvent));
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
2024-07-12 02:14:52 -07:00
|
|
|
}
|
|
|
|
else if (grid.DataContext is Models.Change)
|
|
|
|
{
|
|
|
|
RaiseEvent(new RoutedEventArgs(ChangeDoubleTappedEvent));
|
|
|
|
}
|
|
|
|
}
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
private void OnRowSelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
|
{
|
|
|
|
if (_disableSelectionChangingEvent)
|
|
|
|
return;
|
2024-05-28 06:19:53 -07:00
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
_disableSelectionChangingEvent = true;
|
|
|
|
var selected = new List<Models.Change>();
|
|
|
|
var list = sender as ListBox;
|
|
|
|
foreach (var item in list.SelectedItems)
|
|
|
|
{
|
|
|
|
if (item is Models.Change c)
|
|
|
|
selected.Add(c);
|
|
|
|
else if (item is ChangeTreeNode node)
|
|
|
|
CollectChangesInNode(selected, node);
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
2024-07-12 02:14:52 -07:00
|
|
|
TrySetSelected(selected);
|
|
|
|
_disableSelectionChangingEvent = false;
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
private void MakeTreeRows(List<ChangeTreeNode> rows, List<ChangeTreeNode> nodes)
|
2024-06-01 23:06:27 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
foreach (var node in nodes)
|
2024-06-01 23:06:27 -07:00
|
|
|
{
|
2024-07-12 02:14:52 -07:00
|
|
|
rows.Add(node);
|
|
|
|
|
|
|
|
if (!node.IsExpanded || !node.IsFolder)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
MakeTreeRows(rows, node.Children);
|
|
|
|
}
|
2024-06-01 23:06:27 -07:00
|
|
|
}
|
|
|
|
|
2024-06-07 01:32:06 -07:00
|
|
|
private void CollectChangesInNode(List<Models.Change> outs, ChangeTreeNode node)
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
|
|
|
if (node.IsFolder)
|
|
|
|
{
|
|
|
|
foreach (var child in node.Children)
|
|
|
|
CollectChangesInNode(outs, child);
|
|
|
|
}
|
2024-06-07 01:32:06 -07:00
|
|
|
else if (!outs.Contains(node.Change))
|
2024-05-28 06:19:53 -07:00
|
|
|
{
|
2024-06-07 01:32:06 -07:00
|
|
|
outs.Add(node.Change);
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-05 18:53:26 -07:00
|
|
|
private void TrySetSelected(List<Models.Change> changes)
|
|
|
|
{
|
|
|
|
var old = SelectedChanges;
|
|
|
|
if (old == null && changes.Count == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (old != null && old.Count == changes.Count)
|
|
|
|
{
|
|
|
|
bool allEquals = true;
|
|
|
|
foreach (var c in old)
|
|
|
|
{
|
|
|
|
if (!changes.Contains(c))
|
|
|
|
{
|
|
|
|
allEquals = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (allEquals)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
_disableSelectionChangingEvent = true;
|
2024-06-05 18:53:26 -07:00
|
|
|
SetCurrentValue(SelectedChangesProperty, changes);
|
2024-07-12 02:14:52 -07:00
|
|
|
_disableSelectionChangingEvent = false;
|
2024-06-05 18:53:26 -07:00
|
|
|
}
|
|
|
|
|
2024-07-12 02:14:52 -07:00
|
|
|
private bool _disableSelectionChangingEvent = false;
|
|
|
|
private object _displayContext = null;
|
2024-05-28 06:19:53 -07:00
|
|
|
}
|
|
|
|
}
|