From c2e909a3867386cdeb3549a2062fcd9e8e34b12f Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 14 Feb 2011 01:38:52 +0100 Subject: [PATCH] Filtering performance improvement. --- ILSpy/ILSpy.csproj | 3 +++ ILSpy/TreeNodes/ILSpyTreeNode.cs | 37 ++++++++++++++++++++++++++------ SharpTreeView/SharpTreeNode.cs | 29 +++++++++++++++++++++---- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 8eed57475..645433e1d 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -224,5 +224,8 @@ + + + \ No newline at end of file diff --git a/ILSpy/TreeNodes/ILSpyTreeNode.cs b/ILSpy/TreeNodes/ILSpyTreeNode.cs index 14376e79c..44a9483d3 100644 --- a/ILSpy/TreeNodes/ILSpyTreeNode.cs +++ b/ILSpy/TreeNodes/ILSpyTreeNode.cs @@ -32,6 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes abstract class ILSpyTreeNode : SharpTreeNode { FilterSettings filterSettings; + bool childrenNeedFiltering; public FilterSettings FilterSettings { get { return filterSettings; } @@ -86,8 +87,12 @@ namespace ICSharpCode.ILSpy.TreeNodes protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { - foreach (ILSpyTreeNode node in e.NewItems) - ApplyFilterToChild(node); + if (IsVisible) { + foreach (ILSpyTreeNode node in e.NewItems) + ApplyFilterToChild(node); + } else { + childrenNeedFiltering = true; + } } base.OnChildrenChanged(e); } @@ -109,12 +114,12 @@ namespace ICSharpCode.ILSpy.TreeNodes break; case FilterResult.Recurse: child.FilterSettings = this.FilterSettings; - child.EnsureLazyChildren(); + child.EnsureChildrenFiltered(); child.IsHidden = child.Children.All(c => c.IsHidden); break; case FilterResult.MatchAndRecurse: child.FilterSettings = StripSearchTerm(this.FilterSettings); - child.EnsureLazyChildren(); + child.EnsureChildrenFiltered(); child.IsHidden = child.Children.All(c => c.IsHidden); break; default: @@ -136,8 +141,28 @@ namespace ICSharpCode.ILSpy.TreeNodes protected virtual void OnFilterSettingsChanged() { RaisePropertyChanged("Text"); - foreach (ILSpyTreeNode node in this.Children.OfType()) - ApplyFilterToChild(node); + if (IsVisible) { + foreach (ILSpyTreeNode node in this.Children.OfType()) + ApplyFilterToChild(node); + } else { + childrenNeedFiltering = true; + } + } + + protected override void OnIsVisibleChanged() + { + base.OnIsVisibleChanged(); + EnsureChildrenFiltered(); + } + + void EnsureChildrenFiltered() + { + EnsureLazyChildren(); + if (childrenNeedFiltering) { + childrenNeedFiltering = false; + foreach (ILSpyTreeNode node in this.Children.OfType()) + ApplyFilterToChild(node); + } } } diff --git a/SharpTreeView/SharpTreeNode.cs b/SharpTreeView/SharpTreeNode.cs index 692ef8976..8b8c99250 100644 --- a/SharpTreeView/SharpTreeNode.cs +++ b/SharpTreeView/SharpTreeNode.cs @@ -26,6 +26,7 @@ namespace ICSharpCode.TreeView bool newIsVisible = parentIsVisible && !isHidden; if (isVisible != newIsVisible) { isVisible = newIsVisible; + // invalidate the augmented data SharpTreeNode node = this; while (node != null && node.totalListLength >= 0) { @@ -49,6 +50,8 @@ namespace ICSharpCode.TreeView var flattener = GetListRoot().treeFlattener; if (flattener != null) { flattener.NodesRemoved(GetVisibleIndexForNode(this), removedNodes); + foreach (var n in removedNodes) + n.OnIsVisibleChanged(); } } // Tell the flattener about the new nodes: @@ -56,11 +59,15 @@ namespace ICSharpCode.TreeView var flattener = GetListRoot().treeFlattener; if (flattener != null) { flattener.NodesInserted(GetVisibleIndexForNode(this), VisibleDescendantsAndSelf()); + foreach (var n in VisibleDescendantsAndSelf()) + n.OnIsVisibleChanged(); } } } } + protected virtual void OnIsVisibleChanged() {} + void UpdateChildIsVisible(bool updateFlattener) { if (modelChildren != null && modelChildren.Count > 0) { @@ -125,14 +132,22 @@ namespace ICSharpCode.TreeView if (modelParent != null) UpdateIsVisible(modelParent.isVisible && modelParent.isExpanded, true); RaisePropertyChanged("IsHidden"); + if (Parent != null) + Parent.RaisePropertyChanged("ShowExpander"); } } } + /// + /// Return true when this node is not hidden and when all parent nodes are expanded and not hidden. + /// + public bool IsVisible { + get { return isVisible; } + } + bool isSelected; - public bool IsSelected - { + public bool IsSelected { get { return isSelected; } set { if (isSelected != value) { @@ -220,7 +235,7 @@ namespace ICSharpCode.TreeView public virtual bool ShowExpander { - get { return Children.Count > 0 || LazyLoading; } + get { return LazyLoading || Children.Any(c => !c.isHidden); } } bool isExpanded; @@ -232,15 +247,21 @@ namespace ICSharpCode.TreeView { if (isExpanded != value) { isExpanded = value; - UpdateChildIsVisible(true); if (isExpanded) { EnsureLazyChildren(); + OnExpanding(); + } else { + OnCollapsing(); } + UpdateChildIsVisible(true); RaisePropertyChanged("IsExpanded"); } } } + protected virtual void OnExpanding() {} + protected virtual void OnCollapsing() {} + bool lazyLoading; public bool LazyLoading