149 lines
5.3 KiB
C#
149 lines
5.3 KiB
C#
using DataModel.Database;
|
|
using DataModel.Database.Common;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Processor;
|
|
using UI_WinForms.Dialogs;
|
|
using UI_WinForms.Resources;
|
|
|
|
namespace UI_WinForms.Components;
|
|
|
|
public partial class SectionTree : UserControl
|
|
{
|
|
private readonly DataContext db;
|
|
|
|
public SectionTree()
|
|
{
|
|
this.InitializeComponent();
|
|
|
|
// Get the DI context from the main form:
|
|
this.db = Program.SERVICE_PROVIDER.GetService<DataContext>()!;
|
|
|
|
// Dispose of the context when the control is disposed:
|
|
this.Disposed += (_, _) => this.db.Dispose();
|
|
|
|
// Create an image list from a resource:
|
|
var imgList = new ImageList();
|
|
imgList.ImageSize = new Size(45, 45);
|
|
imgList.ColorDepth = ColorDepth.Depth32Bit;
|
|
imgList.Images.Add(Icons.icons8_documents_folder_512);
|
|
|
|
// Set the image list to the tree view:
|
|
this.treeView.ImageList = imgList;
|
|
|
|
// Subscribe to the load event:
|
|
this.Load += this.OnLoad;
|
|
}
|
|
|
|
private async void OnLoad(object? sender, EventArgs e)
|
|
{
|
|
// A dictionary to cache all known tree nodes:
|
|
var treeNodes = new Dictionary<string, TreeNode>();
|
|
|
|
// Get the max. depth of the tree:
|
|
var maxDepth = await SectionProcessor.GetDepth(this.db);
|
|
|
|
// Store nodes, where we cannot find the parents:
|
|
var missingParents = new List<TreeNode>();
|
|
|
|
// Populate the tree view out of the database, layer by layer:
|
|
for (var i = 0; i <= maxDepth; i++)
|
|
{
|
|
await foreach (var section in SectionProcessor.LoadLayer(this.db, i))
|
|
{
|
|
// Create the tree node:
|
|
var node = new TreeNode
|
|
{
|
|
Name = section.DataKey, // [sic] name is the key
|
|
Text = section.Name,
|
|
StateImageIndex = 1,
|
|
};
|
|
|
|
// Cache the node:
|
|
treeNodes.Add(section.DataKey, node);
|
|
|
|
// Is this a root node?
|
|
if (section.Depth is 0)
|
|
|
|
// Set the root node:
|
|
this.treeView.Nodes.Add(node);
|
|
|
|
// Otherwise, attach this section to its parent node:
|
|
else
|
|
{
|
|
// Get the parent from our cache within O(1):
|
|
treeNodes.TryGetValue(section.Parent?.DataKey ?? string.Empty, out var parent);
|
|
|
|
// If the parent node is not found, skip this section:
|
|
if (parent is null)
|
|
{
|
|
missingParents.Add(node);
|
|
continue;
|
|
}
|
|
|
|
// Add the node to the parent:
|
|
parent.Nodes.Add(node);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we found any missing parents, show a dialog:
|
|
if (missingParents.Any())
|
|
{
|
|
MessageBox.Show($"In {missingParents.Count} case(s) we could not found the matching parent. We added these nodes to a special root node, though.", "Parent not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
|
|
// Create a root node for all missing parents:
|
|
var rootMissedParents = new TreeNode
|
|
{
|
|
Name = "MISSING_PARENTS",
|
|
Text = "Missing Parents",
|
|
StateImageIndex = 1,
|
|
};
|
|
|
|
// Add the root node to the tree:
|
|
this.treeView.Nodes.Add(rootMissedParents);
|
|
|
|
// Add all missing parents to the root node:
|
|
foreach (var node in missingParents)
|
|
rootMissedParents.Nodes.Add(node);
|
|
}
|
|
}
|
|
|
|
private async void buttonAdd_Click(object sender, EventArgs e)
|
|
{
|
|
var result = InputDialog.Show(new InputDialog.Options(
|
|
Message: "Please type the desired section name.",
|
|
Title: "Add a section",
|
|
Placeholder: "My next section",
|
|
ShowQuestionCheckbox: true,
|
|
QuestionCheckboxText: "Add a root node (i.e. ignoring the selected node)"
|
|
));
|
|
|
|
if(result.DialogResult == DialogResult.Cancel)
|
|
return;
|
|
|
|
var addRootNode = result.AnswerToQuestion;
|
|
|
|
// Get the currently selected section as parent:
|
|
var selectedNode = this.treeView.SelectedNode;
|
|
|
|
// Add the new section to the database:
|
|
var addedSection = await SectionProcessor.AddSection(this.db, result.Text, addRootNode ? null : selectedNode?.Name);
|
|
|
|
// Add the new section to the tree control:
|
|
var node = new TreeNode
|
|
{
|
|
Name = addedSection.DataKey, // [sic] name is the key
|
|
Text = addedSection.Name,
|
|
StateImageIndex = 1,
|
|
};
|
|
|
|
if(!addRootNode && selectedNode is not null)
|
|
selectedNode.Nodes.Add(node);
|
|
else
|
|
this.treeView.Nodes.Add(node);
|
|
|
|
// Ensure, that the added node is visible and gets the focus:
|
|
node.EnsureVisible();
|
|
this.treeView.SelectedNode = node;
|
|
}
|
|
} |