From 8990ebe04cf10bab0112585f37c8648a8075f501 Mon Sep 17 00:00:00 2001
From: Daniel Grunwald <daniel@danielgrunwald.de>
Date: Tue, 11 Mar 2014 22:05:05 +0100
Subject: [PATCH] Fix performance problem with DerivedTypesTreeNode.

Once the DerivedTypesTreeNode was created, any change to the type definition was causing an expensive search for derived types; even if the DerivedTypesTreeNode was collapsed.
We now never perform this search on updates, and instead collapse the node.
---
 .../Dom/ClassBrowser/DerivedTypesTreeNode.cs     | 16 +++++++++++++++-
 .../Base/Project/Dom/ModelCollectionTreeNode.cs  | 10 ++++++----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/Main/Base/Project/Dom/ClassBrowser/DerivedTypesTreeNode.cs b/src/Main/Base/Project/Dom/ClassBrowser/DerivedTypesTreeNode.cs
index 581bcebd14..c0f1956299 100644
--- a/src/Main/Base/Project/Dom/ClassBrowser/DerivedTypesTreeNode.cs
+++ b/src/Main/Base/Project/Dom/ClassBrowser/DerivedTypesTreeNode.cs
@@ -43,12 +43,18 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser
 			if (definition == null)
 				throw new ArgumentNullException("definition");
 			this.definition = definition;
-			this.definition.Updated += (sender, e) => UpdateDerivedTypes();
+			this.definition.Updated += OnDefinitionUpdated;
 			this.text = SD.ResourceService.GetString("MainWindow.Windows.ClassBrowser.DerivedTypes");
 			derivedTypes = new SimpleModelCollection<ITypeDefinitionModel>();
 			childrenLoaded = false;
 		}
 
+		protected override void DetachEventHandlers()
+		{
+			this.definition.Updated -= OnDefinitionUpdated;
+			base.DetachEventHandlers();
+		}
+		
 		protected override IModelCollection<object> ModelChildren {
 			get {
 				if (!childrenLoaded) {
@@ -59,6 +65,14 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser
 			}
 		}
 		
+		void OnDefinitionUpdated(object sender, EventArgs e)
+		{
+			// Listing the derived types can be expensive; so it's better to switch back to lazy-loading
+			// (collapsing the node if necessary)
+			SwitchBackToLazyLoading();
+			childrenLoaded = false;
+		}
+		
 		public override SharpTreeNode FindChildNodeRecursively(Func<SharpTreeNode, bool> predicate)
 		{
 			// Don't search children of this node, because they are repeating type nodes from elsewhere
diff --git a/src/Main/Base/Project/Dom/ModelCollectionTreeNode.cs b/src/Main/Base/Project/Dom/ModelCollectionTreeNode.cs
index 4faa47652d..ef0605eced 100644
--- a/src/Main/Base/Project/Dom/ModelCollectionTreeNode.cs
+++ b/src/Main/Base/Project/Dom/ModelCollectionTreeNode.cs
@@ -51,7 +51,7 @@ namespace ICSharpCode.SharpDevelop.Dom
 		protected virtual void DetachEventHandlers()
 		{
 			// If children loaded, also detach the collection change event handler
-			if (!LazyLoading) {
+			if (listeningToCollectionChangedEvents) {
 				ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged;
 				listeningToCollectionChangedEvents = false;
 			}
@@ -122,10 +122,12 @@ namespace ICSharpCode.SharpDevelop.Dom
 			InsertChildren(addedItems);
 		}
 		
-		void SwitchBackToLazyLoading()
+		protected void SwitchBackToLazyLoading()
 		{
-			ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged;
-			listeningToCollectionChangedEvents = false;
+			if (listeningToCollectionChangedEvents) {
+				ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged;
+				listeningToCollectionChangedEvents = false;
+			}
 			Children.Clear();
 			LazyLoading = true;
 		}