2022-07-09 13:06:49 +00:00
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 )
{
2022-07-09 13:29:22 +00:00
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)"
) ) ;
2022-07-09 13:06:49 +00:00
if ( result . DialogResult = = DialogResult . Cancel )
return ;
2022-07-09 13:29:22 +00:00
var addRootNode = result . AnswerToQuestion ;
2022-07-09 13:06:49 +00:00
// Get the currently selected section as parent:
var selectedNode = this . treeView . SelectedNode ;
// Add the new section to the database:
2022-07-09 13:29:22 +00:00
var addedSection = await SectionProcessor . AddSection ( this . db , result . Text , addRootNode ? null : selectedNode ? . Name ) ;
2022-07-09 13:06:49 +00:00
// 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 ,
} ;
2022-07-09 13:29:22 +00:00
if ( ! addRootNode & & selectedNode is not null )
2022-07-09 13:06:49 +00:00
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 ;
}
}