2024-07-14 00:55:15 -07:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
|
|
|
|
|
namespace SourceGit.ViewModels
|
|
|
|
{
|
|
|
|
public class ChangeTreeNode : ObservableObject
|
|
|
|
{
|
2024-07-14 09:30:31 -07:00
|
|
|
public string FullPath { get; set; }
|
2024-07-14 00:55:15 -07:00
|
|
|
public int Depth { get; private set; } = 0;
|
|
|
|
public Models.Change Change { get; set; } = null;
|
|
|
|
public List<ChangeTreeNode> Children { get; set; } = new List<ChangeTreeNode>();
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
nodes.Add(new ChangeTreeNode(c, 0));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ChangeTreeNode lastFolder = null;
|
2024-07-14 09:30:31 -07:00
|
|
|
int depth = 0;
|
2024-07-14 00:55:15 -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)
|
|
|
|
{
|
|
|
|
lastFolder = new ChangeTreeNode(folder, !folded.Contains(folder), depth);
|
|
|
|
folders.Add(folder, lastFolder);
|
|
|
|
InsertFolder(nodes, lastFolder);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var cur = new ChangeTreeNode(folder, !folded.Contains(folder), depth);
|
|
|
|
folders.Add(folder, cur);
|
|
|
|
InsertFolder(lastFolder.Children, cur);
|
|
|
|
lastFolder = cur;
|
|
|
|
}
|
|
|
|
|
|
|
|
depth++;
|
2024-07-14 09:30:31 -07:00
|
|
|
sepIdx = c.Path.IndexOf('/', sepIdx + 1);
|
2024-07-14 00:55:15 -07:00
|
|
|
}
|
|
|
|
|
2024-07-14 09:30:31 -07:00
|
|
|
lastFolder?.Children.Add(new ChangeTreeNode(c, depth));
|
2024-07-14 00:55:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Sort(nodes);
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void Sort(List<ChangeTreeNode> nodes)
|
|
|
|
{
|
|
|
|
foreach (var node in nodes)
|
|
|
|
{
|
|
|
|
if (node.IsFolder)
|
|
|
|
Sort(node.Children);
|
|
|
|
}
|
|
|
|
|
|
|
|
nodes.Sort((l, r) =>
|
|
|
|
{
|
2024-10-24 00:11:10 -07:00
|
|
|
if (l.IsFolder == r.IsFolder)
|
|
|
|
return Models.NumericSort.Compare(l.FullPath, r.FullPath);
|
2024-10-24 02:00:03 -07:00
|
|
|
return l.IsFolder ? -1 : 1;
|
2024-07-14 00:55:15 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool _isExpanded = true;
|
|
|
|
}
|
|
|
|
}
|