11using System ;
2+ using System . Collections ;
23using System . Collections . Generic ;
34using System . ComponentModel ;
45using System . Diagnostics . Contracts ;
78using ReClassNET . Extensions ;
89using ReClassNET . Nodes ;
910using ReClassNET . Project ;
10- using ReClassNET . Util ;
1111
1212namespace 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