/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Collections.Generic; using System.Linq; using System.Windows; using dnSpy.Contracts.Images; namespace dnSpy.Contracts.TreeView { /// /// Treenode data base class /// public abstract class TreeNodeData { /// /// Guid of this node /// public abstract Guid Guid { get; } /// /// Gets the data shown in the UI /// public abstract object? Text { get; } /// /// Gets the data shown in a tooltip /// public abstract object? ToolTip { get; } /// /// Icon /// public abstract ImageReference Icon { get; } /// /// Group or null /// public virtual ITreeNodeGroup? TreeNodeGroup => null; /// /// Expanded icon or null to use /// public virtual ImageReference? ExpandedIcon => null; /// /// true if single clicking on a node expands all its children /// public virtual bool SingleClickExpandsChildren => false; /// /// Gets the owner instance. Only the treeview may write to this /// property. /// public ITreeNode TreeNode { get => treeNode; set { if (treeNode is not null) throw new InvalidOperationException(); treeNode = value ?? throw new ArgumentNullException(nameof(value)); } } ITreeNode treeNode; /// /// Constructor /// protected TreeNodeData() => treeNode = null!; /// /// Returns true if the expander should be shown /// /// Default value /// public virtual bool ShowExpander(bool defaultValue) => defaultValue; /// /// Called when it's time to create its children /// /// public virtual IEnumerable CreateChildren() { yield break; } /// /// Called after has been set. /// public virtual void Initialize() { } /// /// Called by before it invalidates all UI properties /// public abstract void OnRefreshUI(); /// /// Called when the item gets activated, eg. double clicked. Returns true if it was handled, /// false otherwise. /// /// public virtual bool Activate() => false; /// /// Called by /// public virtual void OnEnsureChildrenLoaded() { } /// /// Called when the children has changed /// /// Added nodes /// Removed nodes public virtual void OnChildrenChanged(TreeNodeData[] added, TreeNodeData[] removed) { } /// /// Called when has changed /// public virtual void OnIsVisibleChanged() { } /// /// Called when has changed /// /// Value of public virtual void OnIsExpandedChanged(bool isExpanded) { } /// /// Returns true if the nodes can be dragged /// /// Nodes /// public virtual bool CanDrag(TreeNodeData[] nodes) => false; /// /// Starts the drag and drop operation /// /// Drag source /// Nodes public virtual void StartDrag(DependencyObject dragSource, TreeNodeData[] nodes) { } /// /// Copies nodes /// /// Nodes /// public virtual IDataObject Copy(TreeNodeData[] nodes) => throw new NotSupportedException(); /// /// Returns true if drop can execute /// /// Event args /// Index /// public virtual bool CanDrop(DragEventArgs e, int index) => false; /// /// Drops data /// /// Event args /// Index public virtual void Drop(DragEventArgs e, int index) => throw new NotSupportedException(); } /// /// Extension methods /// public static class TreeNodeDataExtensionMethods { /// /// Gets all descendants /// /// This /// public static IEnumerable Descendants(this TreeNodeData self) => self.TreeNode.Descendants().Select(a => a.Data); /// /// Gets all descendants including itself /// /// This /// public static IEnumerable DescendantsAndSelf(this TreeNodeData self) => self.TreeNode.DescendantsAndSelf().Select(a => a.Data); /// /// Gets the ancestor of a certain type /// /// Desired type /// This /// public static T? GetAncestorOrSelf(this TreeNodeData? self) where T : TreeNodeData { while (self is not null) { if (self is T found) return found; var parent = self.TreeNode.Parent; if (parent is null) break; self = parent.Data; } return null; } } }