// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Collections; using System.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.Utils; using ICSharpCode.TreeView; namespace ICSharpCode.SharpDevelop.Dom { public abstract class ModelCollectionTreeNode : SharpTreeNode { protected static readonly IComparer NodeTextComparer = KeyComparer.Create((SharpTreeNode n) => n.Text.ToString(), StringComparer.OrdinalIgnoreCase, StringComparer.OrdinalIgnoreCase); protected ModelCollectionTreeNode() { this.LazyLoading = true; } protected abstract IModelCollection ModelChildren { get; } protected abstract IComparer NodeComparer { get; } protected virtual bool IsSpecialNode() { return false; } protected virtual void InsertSpecialNodes() { throw new NotSupportedException("this node is not a special node!"); } protected virtual void DetachEventHandlers() { // If children loaded, also detach the collection change event handler if (!LazyLoading) { ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged; } } protected override void OnIsVisibleChanged() { base.OnIsVisibleChanged(); if (IsVisible) { if (!LazyLoading) { ModelChildren.CollectionChanged += ModelChildrenCollectionChanged; SynchronizeModelChildren(); } } else { ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged; } } public virtual void ShowContextMenu() { // Do nothing in base class } #region Manage Children protected override void LoadChildren() { Children.Clear(); if (IsSpecialNode()) InsertSpecialNodes(); InsertChildren(ModelChildren); ModelChildren.CollectionChanged += ModelChildrenCollectionChanged; } protected void InsertChildren(IEnumerable children) { foreach (object child in children) { var treeNode = SD.TreeNodeFactory.CreateTreeNode(child); if (treeNode != null) Children.OrderedInsert(treeNode, NodeComparer); } } protected void SynchronizeModelChildren() { HashSet set = new HashSet(ModelChildren); Children.RemoveAll(n => !set.Contains(n.Model)); set.ExceptWith(Children.Select(n => n.Model)); InsertChildren(set); if (IsSpecialNode()) InsertSpecialNodes(); } void ModelChildrenCollectionChanged(IReadOnlyCollection removedItems, IReadOnlyCollection addedItems) { if (!IsVisible) { SwitchBackToLazyLoading(); return; } Children.RemoveAll(n => removedItems.Contains(n.Model)); InsertChildren(addedItems); } void SwitchBackToLazyLoading() { ModelChildren.CollectionChanged -= ModelChildrenCollectionChanged; Children.Clear(); LazyLoading = true; } #endregion } public class WaitForSolutionLoadedTreeNode : SharpTreeNode { public WaitForSolutionLoadedTreeNode() { this.LazyLoading = false; } public override object Text { get { return "Waiting for solution load to be completed..."; } } } }