mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-22 12:45:00 +00:00
feature: new way to expand/collapse folder node in TreeDataGrid
This commit is contained in:
parent
f4d379e3b8
commit
55c9fae110
10 changed files with 58 additions and 73 deletions
185
src/Models/FileTreeNode.cs
Normal file
185
src/Models/FileTreeNode.cs
Normal file
|
@ -0,0 +1,185 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public class FileTreeNode
|
||||
{
|
||||
public string FullPath { get; set; } = string.Empty;
|
||||
public bool IsFolder { get; set; } = false;
|
||||
public bool IsExpanded { get; set; } = false;
|
||||
public object Backend { get; set; } = null;
|
||||
public List<FileTreeNode> Children { get; set; } = new List<FileTreeNode>();
|
||||
|
||||
public static List<FileTreeNode> Build(List<Change> changes, bool expanded)
|
||||
{
|
||||
var nodes = new List<FileTreeNode>();
|
||||
var folders = new Dictionary<string, FileTreeNode>();
|
||||
|
||||
foreach (var c in changes)
|
||||
{
|
||||
var sepIdx = c.Path.IndexOf('/', StringComparison.Ordinal);
|
||||
if (sepIdx == -1)
|
||||
{
|
||||
nodes.Add(new FileTreeNode()
|
||||
{
|
||||
FullPath = c.Path,
|
||||
Backend = c,
|
||||
IsFolder = false,
|
||||
IsExpanded = false
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
FileTreeNode lastFolder = null;
|
||||
var start = 0;
|
||||
|
||||
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 FileTreeNode()
|
||||
{
|
||||
FullPath = folder,
|
||||
Backend = null,
|
||||
IsFolder = true,
|
||||
IsExpanded = expanded
|
||||
};
|
||||
nodes.Add(lastFolder);
|
||||
folders.Add(folder, lastFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
var cur = new FileTreeNode()
|
||||
{
|
||||
FullPath = folder,
|
||||
Backend = null,
|
||||
IsFolder = true,
|
||||
IsExpanded = expanded
|
||||
};
|
||||
folders.Add(folder, cur);
|
||||
lastFolder.Children.Add(cur);
|
||||
lastFolder = cur;
|
||||
}
|
||||
|
||||
start = sepIdx + 1;
|
||||
sepIdx = c.Path.IndexOf('/', start);
|
||||
}
|
||||
|
||||
lastFolder.Children.Add(new FileTreeNode()
|
||||
{
|
||||
FullPath = c.Path,
|
||||
Backend = c,
|
||||
IsFolder = false,
|
||||
IsExpanded = false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
folders.Clear();
|
||||
Sort(nodes);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public static List<FileTreeNode> Build(List<Object> files, bool expanded)
|
||||
{
|
||||
var nodes = new List<FileTreeNode>();
|
||||
var folders = new Dictionary<string, FileTreeNode>();
|
||||
|
||||
foreach (var f in files)
|
||||
{
|
||||
var sepIdx = f.Path.IndexOf('/', StringComparison.Ordinal);
|
||||
if (sepIdx == -1)
|
||||
{
|
||||
nodes.Add(new FileTreeNode()
|
||||
{
|
||||
FullPath = f.Path,
|
||||
Backend = f,
|
||||
IsFolder = false,
|
||||
IsExpanded = false
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
FileTreeNode lastFolder = null;
|
||||
var start = 0;
|
||||
|
||||
while (sepIdx != -1)
|
||||
{
|
||||
var folder = f.Path.Substring(0, sepIdx);
|
||||
if (folders.TryGetValue(folder, out var value))
|
||||
{
|
||||
lastFolder = value;
|
||||
}
|
||||
else if (lastFolder == null)
|
||||
{
|
||||
lastFolder = new FileTreeNode()
|
||||
{
|
||||
FullPath = folder,
|
||||
Backend = null,
|
||||
IsFolder = true,
|
||||
IsExpanded = expanded
|
||||
};
|
||||
nodes.Add(lastFolder);
|
||||
folders.Add(folder, lastFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
var cur = new FileTreeNode()
|
||||
{
|
||||
FullPath = folder,
|
||||
Backend = null,
|
||||
IsFolder = true,
|
||||
IsExpanded = expanded
|
||||
};
|
||||
folders.Add(folder, cur);
|
||||
lastFolder.Children.Add(cur);
|
||||
lastFolder = cur;
|
||||
}
|
||||
|
||||
start = sepIdx + 1;
|
||||
sepIdx = f.Path.IndexOf('/', start);
|
||||
}
|
||||
|
||||
lastFolder.Children.Add(new FileTreeNode()
|
||||
{
|
||||
FullPath = f.Path,
|
||||
Backend = f,
|
||||
IsFolder = false,
|
||||
IsExpanded = false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
folders.Clear();
|
||||
Sort(nodes);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private static void Sort(List<FileTreeNode> nodes)
|
||||
{
|
||||
nodes.Sort((l, r) =>
|
||||
{
|
||||
if (l.IsFolder == r.IsFolder)
|
||||
{
|
||||
return l.FullPath.CompareTo(r.FullPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
return l.IsFolder ? -1 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
if (node.Children.Count > 1)
|
||||
Sort(node.Children);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -188,7 +188,12 @@ namespace SourceGit.Models
|
|||
}
|
||||
else if (e.ClickCount % 2 == 0)
|
||||
{
|
||||
_rowDoubleTapped?.Invoke(this, e);
|
||||
var focus = _source.Rows[row.RowIndex];
|
||||
if (focus is IExpander expander && HasChildren(focus))
|
||||
expander.IsExpanded = !expander.IsExpanded;
|
||||
else
|
||||
_rowDoubleTapped?.Invoke(this, e);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (sender.RowSelection.Count > 1)
|
||||
|
@ -420,7 +425,22 @@ namespace SourceGit.Models
|
|||
|
||||
protected override IEnumerable<TModel> GetChildren(TModel node)
|
||||
{
|
||||
if (node == null)
|
||||
return null;
|
||||
|
||||
return _childrenGetter?.Invoke(node);
|
||||
}
|
||||
|
||||
private bool HasChildren(IRow row)
|
||||
{
|
||||
var children = GetChildren(row.Model as TModel);
|
||||
if (children != null)
|
||||
{
|
||||
foreach (var c in children)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue