mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-21 20:24:59 +00:00
feature: supports display tags in a tree (#350)
This commit is contained in:
parent
f59af0afcf
commit
de2f70b8ea
11 changed files with 652 additions and 113 deletions
141
src/ViewModels/TagCollection.cs
Normal file
141
src/ViewModels/TagCollection.cs
Normal file
|
@ -0,0 +1,141 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia.Collections;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class TagTreeNode : ObservableObject
|
||||
{
|
||||
public string FullPath { get; set; }
|
||||
public int Depth { get; private set; } = 0;
|
||||
public Models.Tag Tag { get; private set; } = null;
|
||||
public List<TagTreeNode> Children { get; private set; } = [];
|
||||
|
||||
public bool IsFolder
|
||||
{
|
||||
get => Tag == null;
|
||||
}
|
||||
|
||||
public bool IsFiltered
|
||||
{
|
||||
get => Tag?.IsFiltered ?? false;
|
||||
set
|
||||
{
|
||||
if (Tag != null)
|
||||
Tag.IsFiltered = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
set => SetProperty(ref _isExpanded, value);
|
||||
}
|
||||
|
||||
public TagTreeNode(Models.Tag t, int depth)
|
||||
{
|
||||
FullPath = t.Name;
|
||||
Depth = depth;
|
||||
Tag = t;
|
||||
IsExpanded = false;
|
||||
}
|
||||
|
||||
public TagTreeNode(string path, bool isExpanded, int depth)
|
||||
{
|
||||
FullPath = path;
|
||||
Depth = depth;
|
||||
IsExpanded = isExpanded;
|
||||
}
|
||||
|
||||
public static List<TagTreeNode> Build(IList<Models.Tag> tags, HashSet<string> expaneded)
|
||||
{
|
||||
var nodes = new List<TagTreeNode>();
|
||||
var folders = new Dictionary<string, TagTreeNode>();
|
||||
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
var sepIdx = tag.Name.IndexOf('/', StringComparison.Ordinal);
|
||||
if (sepIdx == -1)
|
||||
{
|
||||
nodes.Add(new TagTreeNode(tag, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
TagTreeNode lastFolder = null;
|
||||
int depth = 0;
|
||||
|
||||
while (sepIdx != -1)
|
||||
{
|
||||
var folder = tag.Name.Substring(0, sepIdx);
|
||||
if (folders.TryGetValue(folder, out var value))
|
||||
{
|
||||
lastFolder = value;
|
||||
}
|
||||
else if (lastFolder == null)
|
||||
{
|
||||
lastFolder = new TagTreeNode(folder, expaneded.Contains(folder), depth);
|
||||
folders.Add(folder, lastFolder);
|
||||
InsertFolder(nodes, lastFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
var cur = new TagTreeNode(folder, expaneded.Contains(folder), depth);
|
||||
folders.Add(folder, cur);
|
||||
InsertFolder(lastFolder.Children, cur);
|
||||
lastFolder = cur;
|
||||
}
|
||||
|
||||
depth++;
|
||||
sepIdx = tag.Name.IndexOf('/', sepIdx + 1);
|
||||
}
|
||||
|
||||
lastFolder?.Children.Add(new TagTreeNode(tag, depth));
|
||||
}
|
||||
}
|
||||
|
||||
folders.Clear();
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private static void InsertFolder(List<TagTreeNode> collection, TagTreeNode subFolder)
|
||||
{
|
||||
for (int i = 0; i < collection.Count; i++)
|
||||
{
|
||||
if (!collection[i].IsFolder)
|
||||
{
|
||||
collection.Insert(i, subFolder);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
collection.Add(subFolder);
|
||||
}
|
||||
|
||||
private bool _isExpanded = true;
|
||||
}
|
||||
|
||||
public class TagCollectionAsList
|
||||
{
|
||||
public AvaloniaList<Models.Tag> Tags
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = [];
|
||||
}
|
||||
|
||||
public class TagCollectionAsTree
|
||||
{
|
||||
public List<TagTreeNode> Tree
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = [];
|
||||
|
||||
public AvaloniaList<TagTreeNode> Rows
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = [];
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue