/*
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;
}
}
}