Skip to content

Commit 1884ff6

Browse files
committed
Simplify ClassNodeView (1).
1 parent aef0411 commit 1884ff6

File tree

1 file changed

+88
-59
lines changed

1 file changed

+88
-59
lines changed

ReClass.NET/UI/ClassNodeView.cs

Lines changed: 88 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Generic;
34
using System.ComponentModel;
45
using System.Diagnostics.Contracts;
@@ -7,45 +8,36 @@
78
using ReClassNET.Extensions;
89
using ReClassNET.Nodes;
910
using ReClassNET.Project;
10-
using ReClassNET.Util;
1111

1212
namespace ReClassNET.UI
1313
{
1414
public partial class ClassNodeView : UserControl
1515
{
1616
/// <summary>A custom tree node for class nodes with hierarchical structure.</summary>
17-
private class ClassTreeNode : TreeNode, IDisposable
17+
private class ClassTreeNode : TreeNode
1818
{
19-
public ClassNode ClassNode { get; }
19+
private readonly ClassNodeView control;
2020

21-
private readonly ValueTypeWrapper<bool> enableHierarchyView;
22-
private readonly ValueTypeWrapper<bool> autoExpand;
21+
public ClassNode ClassNode { get; }
2322

2423
/// <summary>Constructor of the class.</summary>
2524
/// <param name="node">The class node.</param>
26-
/// <param name="enableHierarchyView">The value if the hierarchy view is enabled.</param>
27-
/// <param name="autoExpand">The value if nodes should get expanded.</param>
28-
public ClassTreeNode(ClassNode node, ValueTypeWrapper<bool> enableHierarchyView, ValueTypeWrapper<bool> autoExpand)
29-
: this(node, enableHierarchyView, autoExpand, null)
25+
/// <param name="control">The <see cref="ClassNodeView"/> instance this node should belong to.</param>
26+
public ClassTreeNode(ClassNode node, ClassNodeView control)
27+
: this(node, control, null)
3028
{
3129
Contract.Requires(node != null);
32-
Contract.Requires(enableHierarchyView != null);
33-
Contract.Requires(autoExpand != null);
30+
Contract.Requires(control != null);
3431
}
3532

36-
private ClassTreeNode(ClassNode node, ValueTypeWrapper<bool> enableHierarchyView, ValueTypeWrapper<bool> autoExpand, HashSet<ClassNode> seen)
33+
private ClassTreeNode(ClassNode node, ClassNodeView control, HashSet<ClassNode> seen)
3734
{
3835
Contract.Requires(node != null);
39-
Contract.Requires(enableHierarchyView != null);
40-
Contract.Requires(autoExpand != null);
41-
42-
this.enableHierarchyView = enableHierarchyView;
43-
this.autoExpand = autoExpand;
36+
Contract.Requires(control != null);
4437

4538
ClassNode = node;
4639

47-
node.NameChanged += NameChanged_Handler;
48-
node.NodesChanged += NodesChanged_Handler;
40+
this.control = control;
4941

5042
Text = node.Name;
5143

@@ -55,22 +47,10 @@ private ClassTreeNode(ClassNode node, ValueTypeWrapper<bool> enableHierarchyView
5547
RebuildClassHierarchy(seen ?? new HashSet<ClassNode> { ClassNode });
5648
}
5749

58-
public void Dispose()
50+
public void Update()
5951
{
60-
ClassNode.NameChanged -= NameChanged_Handler;
61-
ClassNode.NodesChanged -= NodesChanged_Handler;
52+
Text = ClassNode.Name;
6253

63-
Nodes.Cast<ClassTreeNode>().ForEach(t => t.Dispose());
64-
Nodes.Clear();
65-
}
66-
67-
private void NameChanged_Handler(BaseNode sender)
68-
{
69-
Text = sender.Name;
70-
}
71-
72-
private void NodesChanged_Handler(BaseNode sender)
73-
{
7454
RebuildClassHierarchy(new HashSet<ClassNode> { ClassNode });
7555
}
7656

@@ -80,7 +60,7 @@ private void RebuildClassHierarchy(HashSet<ClassNode> seen)
8060
{
8161
Contract.Requires(seen != null);
8262

83-
if (!enableHierarchyView.Value)
63+
if (!control.EnableClassHierarchyView)
8464
{
8565
return;
8666
}
@@ -90,35 +70,47 @@ private void RebuildClassHierarchy(HashSet<ClassNode> seen)
9070
.Select(w => w.ResolveMostInnerNode())
9171
.OfType<ClassNode>()
9272
.Distinct()
93-
.ToArray();
73+
.ToList();
9474

9575
if (distinctClasses.SequenceEqualsEx(Nodes.Cast<ClassTreeNode>().Select(t => t.ClassNode)))
9676
{
9777
return;
9878
}
9979

100-
Nodes.Cast<ClassTreeNode>().ForEach(t => t.Dispose());
10180
Nodes.Clear();
10281

10382
foreach (var child in distinctClasses)
10483
{
10584
var childSeen = new HashSet<ClassNode>(seen);
10685
if (childSeen.Add(child))
10786
{
108-
Nodes.Add(new ClassTreeNode(child, enableHierarchyView, autoExpand, childSeen));
87+
Nodes.Add(new ClassTreeNode(child, control, childSeen));
10988
}
11089
}
11190

112-
if (autoExpand.Value)
91+
if (control.AutoExpandClassNodes)
11392
{
11493
Expand();
11594
}
11695
}
11796
}
11897

98+
private class NodeSorter : IComparer
99+
{
100+
public int Compare(object x, object y)
101+
{
102+
var compare = Application.CurrentCulture.CompareInfo;
103+
104+
if (x is ClassTreeNode n1 && y is ClassTreeNode n2)
105+
{
106+
return compare.Compare(n1.Text, n2.Text);
107+
}
108+
109+
return 0;
110+
}
111+
}
112+
119113
private readonly TreeNode root;
120-
private readonly ValueTypeWrapper<bool> enableHierarchyView;
121-
private readonly ValueTypeWrapper<bool> autoExpand;
122114

123115
private ReClassNetProject project;
124116

@@ -140,7 +132,6 @@ public ReClassNetProject Project
140132
{
141133
classesTreeView.BeginUpdate();
142134

143-
root.Nodes.Cast<ClassTreeNode>().ForEach(t => t.Dispose());
144135
root.Nodes.Clear();
145136

146137
if (project != null)
@@ -183,6 +174,12 @@ public ClassNode SelectedClass
183174
}
184175
}
185176

177+
[DefaultValue(false)]
178+
public bool AutoExpandClassNodes { get; set; }
179+
180+
[DefaultValue(false)]
181+
public bool EnableClassHierarchyView { get; set; }
182+
186183
public ClassNodeView()
187184
{
188185
Contract.Ensures(root != null);
@@ -191,9 +188,7 @@ public ClassNodeView()
191188

192189
DoubleBuffered = true;
193190

194-
enableHierarchyView = new ValueTypeWrapper<bool>(false);
195-
autoExpand = new ValueTypeWrapper<bool>(false);
196-
191+
classesTreeView.TreeViewNodeSorter = new NodeSorter();
197192
classesTreeView.ImageList = new ImageList();
198193
classesTreeView.ImageList.Images.Add(Properties.Resources.B16x16_Text_List_Bullets);
199194
classesTreeView.ImageList.Images.Add(Properties.Resources.B16x16_Class_Type);
@@ -301,13 +296,12 @@ private void enableHierarchyViewToolStripMenuItem_Click(object sender, EventArgs
301296
expandAllClassesToolStripMenuItem.Enabled =
302297
collapseAllClassesToolStripMenuItem.Enabled = enableHierarchyViewToolStripMenuItem.Checked;
303298

304-
enableHierarchyView.Value = enableHierarchyViewToolStripMenuItem.Checked;
299+
EnableClassHierarchyView = enableHierarchyViewToolStripMenuItem.Checked;
305300

306301
var classes = root.Nodes.Cast<ClassTreeNode>().Select(t => t.ClassNode).ToList();
307302

308303
classesTreeView.BeginUpdate();
309304

310-
root.Nodes.Cast<ClassTreeNode>().ForEach(t => t.Dispose());
311305
root.Nodes.Clear();
312306

313307
classes.ForEach(AddClassInternal);
@@ -321,9 +315,9 @@ private void autoExpandHierarchyViewToolStripMenuItem_Click(object sender, Event
321315
{
322316
autoExpandHierarchyViewToolStripMenuItem.Checked = !autoExpandHierarchyViewToolStripMenuItem.Checked;
323317

324-
autoExpand.Value = autoExpandHierarchyViewToolStripMenuItem.Checked;
318+
AutoExpandClassNodes = autoExpandHierarchyViewToolStripMenuItem.Checked;
325319

326-
if (autoExpand.Value)
320+
if (AutoExpandClassNodes)
327321
{
328322
root.ExpandAll();
329323
}
@@ -354,31 +348,45 @@ private void showCodeOfClassToolStripMenuItem_Click(object sender, EventArgs e)
354348

355349
#endregion
356350

351+
public void Clear()
352+
{
353+
root.Nodes.Clear();
354+
}
355+
357356
/// <summary>Adds the class to the view.</summary>
358357
/// <param name="node">The class to add.</param>
359358
public void AddClass(ClassNode node)
360359
{
361360
Contract.Requires(node != null);
362361

363-
AddClassInternal(node);
362+
AddClasses(new[] { node });
363+
}
364+
365+
public void AddClasses(IEnumerable<ClassNode> nodes)
366+
{
367+
Contract.Requires(nodes != null);
368+
369+
classesTreeView.BeginUpdate();
370+
371+
foreach (var node in nodes)
372+
{
373+
AddClassInternal(node);
374+
}
364375

365376
classesTreeView.Sort();
377+
378+
classesTreeView.EndUpdate();
366379
}
367380

368381
/// <summary>Removes the class from the view.</summary>
369382
/// <param name="node">The class to remove.</param>
370383
public void RemoveClass(ClassNode node)
371384
{
372-
var tn = FindClassTreeNode(node);
373-
if (tn == null)
385+
foreach (var tn in FindClassTreeNodes(node))
374386
{
375-
return;
387+
tn.Remove();
376388
}
377389

378-
root.Nodes.Remove(tn);
379-
380-
tn.Dispose();
381-
382390
if (selectedClass == node)
383391
{
384392
if (root.Nodes.Count > 0)
@@ -400,17 +408,38 @@ private void AddClassInternal(ClassNode node)
400408
{
401409
Contract.Requires(node != null);
402410

403-
root.Nodes.Add(new ClassTreeNode(node, enableHierarchyView, autoExpand));
411+
root.Nodes.Add(new ClassTreeNode(node, this));
404412

405413
root.Expand();
406414
}
407415

416+
/// <summary>Searches for the <see cref="ClassTreeNode"/> which represents the class.</summary>
417+
/// <param name="node">The class to search.</param>
418+
/// <returns>The found class tree node.</returns>
419+
private ClassTreeNode FindMainClassTreeNode(ClassNode node)
420+
{
421+
return root.Nodes
422+
.Cast<ClassTreeNode>()
423+
.FirstOrDefault(t => t.ClassNode == node);
424+
}
425+
408426
/// <summary>Searches for the ClassTreeNode which represents the class.</summary>
409427
/// <param name="node">The class to search.</param>
410428
/// <returns>The found class tree node.</returns>
411-
private ClassTreeNode FindClassTreeNode(ClassNode node)
429+
private IEnumerable<ClassTreeNode> FindClassTreeNodes(ClassNode node)
430+
{
431+
return root.Nodes
432+
.Cast<ClassTreeNode>()
433+
.Traverse(t => t.Nodes.Cast<ClassTreeNode>())
434+
.Where(n => n.ClassNode == node);
435+
}
436+
437+
public void UpdateClassNode(ClassNode node)
412438
{
413-
return root.Nodes.Cast<ClassTreeNode>().FirstOrDefault(t => t.ClassNode == node);
439+
foreach (var tn in FindClassTreeNodes(node))
440+
{
441+
tn.Update();
442+
}
414443
}
415444
}
416445
}

0 commit comments

Comments
 (0)