LearnGodot/Component/MainTreePanel.cs
2025-12-21 23:04:12 +08:00

197 lines
4.0 KiB
C#

using System.Collections.Generic;
using System.IO;
using System.Linq;
using Godot;
using Learn.Models;
using Newtonsoft.Json;
namespace Learn.Component;
public partial class MainTreePanel : Tree
{
public class MainTreeData
{
public List<string> Columns { get; set; }
public Dictionary<string, Item> Items { get; set; }
}
private readonly HashSet<string> _columns = new();
private readonly HashSet<TreeNode> _selectingNodes = new();
private readonly Dictionary<TreeItem, TreeNode> _mapper = new();
private readonly Dictionary<string, Item> _items = new();
public HashSet<TreeNode> SelectingNodes => _selectingNodes;
public override void _Ready()
{
Columns = 1;
SetColumnTitlesVisible(true);
SetColumnTitle(0, "文件名");
SetColumnCustomMinimumWidth(0, 400);
SetColumnExpand(0, true);
MultiSelected += OnMultiSelected;
UpdateColumns();
}
public void AddColumn(string columnName)
{
if (string.IsNullOrEmpty(columnName)) return;
_columns.Add(columnName);
UpdateColumns();
}
public void RemoveColumn(string columnName)
{
if (string.IsNullOrEmpty(columnName)) return;
_columns.Remove(columnName);
UpdateColumns();
}
public void UpdateColumns()
{
Columns = _columns.Count + 1;
int index = 1;
foreach (var column in _columns)
{
SetColumnTitle(index, column);
SetColumnCustomMinimumWidth(index, 200);
SetColumnExpand(index, true);
index += 1;
}
foreach (var kv in _mapper)
{
index = 1;
foreach (var column in _columns)
{
if (kv.Value.TryGetValue(column, out var value, out _))
{
kv.Key.SetText(index, value);
}
else
{
kv.Key.SetText(index, "");
}
index += 1;
}
}
}
private void OnMultiSelected(TreeItem item, long column, bool selected)
{
if(selected) _selectingNodes.Add(_mapper[item]);
else _selectingNodes.Remove(_mapper[item]);
}
private TreeItem CreateNode(TreeItem father, Item item)
{
var node = CreateItem(father);
var name = Path.GetFileName(item.MainInfo["Path"]);
node.SetText(0, name);
return node;
}
private Item InitItem(string path, bool isDir)
{
if (_items.TryGetValue(path, out var item))
{
return item;
}
item = new Item
{
MainInfo =
{
["IsDir"] = isDir ? "True" : "False",
["Path"] = path
}
};
_items.Add(path, item);
return item;
}
public void ClearData()
{
foreach (var item in _items.Values)
{
item.Info.Clear();
}
UpdateColumns();
}
public void LoadData(string dataPath)
{
var data = JsonConvert.DeserializeObject<MainTreeData>(File.ReadAllText(dataPath));
foreach (var kv in data.Items)
{
if (string.IsNullOrEmpty(kv.Key)) continue;
_items[kv.Key] = kv.Value;
}
_columns.Clear();
foreach (var column in data.Columns)
{
_columns.Add(column);
}
UpdateColumns();
}
public void SaveData(string dataPath)
{
var data = new MainTreeData
{
Columns = _columns.ToList(),
Items = _items
};
File.WriteAllText(dataPath, JsonConvert.SerializeObject(data, Formatting.Indented));
}
public void Scan(string path)
{
Clear();
_mapper.Clear();
_selectingNodes.Clear();
TreeItem root = CreateItem();
BuildTree(root, path);
}
private void BuildTree(TreeItem root, string path)
{
var nodes = new Stack<(TreeItem node, string path)>();
_mapper[root] = new TreeNode(null);
nodes.Push((root, path));
while (nodes.Count > 0)
{
var node = nodes.Pop();
var father = node.node;
var fatherNode = _mapper[father];
foreach (var filePath in Directory.GetFiles(node.path))
{
var item = InitItem(filePath, false);
var childNode = new TreeNode(item);
fatherNode.AddNode(childNode);
var child = CreateNode(father, item);
_mapper[child] = childNode;
}
foreach (var subDirPath in Directory.GetDirectories(node.path))
{
var item = InitItem(subDirPath, true);
var childNode = new TreeNode(item);
fatherNode.AddNode(childNode);
var child = CreateNode(father, item);
_mapper[child] = childNode;
nodes.Push((child, subDirPath));
}
}
}
}