mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
247 lines
9.1 KiB
C#
247 lines
9.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using mRemoteNG.Connection;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using mRemoteNG.Connection.Protocol;
|
|
using mRemoteNG.Tools;
|
|
using mRemoteNG.Tree;
|
|
|
|
namespace mRemoteNG.Container
|
|
{
|
|
[DefaultProperty("Name")]
|
|
public class ContainerInfo : ConnectionInfo, INotifyCollectionChanged
|
|
{
|
|
[Browsable(false)]
|
|
public List<ConnectionInfo> Children { get; } = new List<ConnectionInfo>();
|
|
|
|
[Category(""), Browsable(false), ReadOnly(false), Bindable(false), DefaultValue(""), DesignOnly(false)]
|
|
public bool IsExpanded { get; set; }
|
|
|
|
|
|
public ContainerInfo()
|
|
{
|
|
SetDefaults();
|
|
IsContainer = true;
|
|
}
|
|
|
|
public override TreeNodeType GetTreeNodeType()
|
|
{
|
|
return TreeNodeType.Container;
|
|
}
|
|
|
|
public bool HasChildren()
|
|
{
|
|
return Children.Count > 0;
|
|
}
|
|
|
|
public void AddChild(ConnectionInfo newChildItem)
|
|
{
|
|
AddChildAt(newChildItem, Children.Count);
|
|
}
|
|
|
|
public void AddChildAbove(ConnectionInfo newChildItem, ConnectionInfo reference)
|
|
{
|
|
var newChildIndex = Children.IndexOf(reference);
|
|
if (newChildIndex < 0)
|
|
newChildIndex = Children.Count;
|
|
AddChildAt(newChildItem, newChildIndex);
|
|
}
|
|
|
|
public void AddChildBelow(ConnectionInfo newChildItem, ConnectionInfo reference)
|
|
{
|
|
var newChildIndex = Children.IndexOf(reference) + 1;
|
|
if (newChildIndex > Children.Count || newChildIndex < 1)
|
|
newChildIndex = Children.Count;
|
|
AddChildAt(newChildItem, newChildIndex);
|
|
}
|
|
|
|
public void AddChildAt(ConnectionInfo newChildItem, int index)
|
|
{
|
|
if (Children.Contains(newChildItem)) return;
|
|
newChildItem.Parent?.RemoveChild(newChildItem);
|
|
newChildItem.Parent = this;
|
|
Children.Insert(index, newChildItem);
|
|
SubscribeToChildEvents(newChildItem);
|
|
RaiseCollectionChangedEvent(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newChildItem));
|
|
}
|
|
|
|
public void AddChildRange(IEnumerable<ConnectionInfo> newChildren)
|
|
{
|
|
foreach (var child in newChildren)
|
|
{
|
|
AddChild(child);
|
|
}
|
|
}
|
|
|
|
public void RemoveChild(ConnectionInfo removalTarget)
|
|
{
|
|
if (!Children.Contains(removalTarget)) return;
|
|
removalTarget.Parent = null;
|
|
Children.Remove(removalTarget);
|
|
UnsubscribeToChildEvents(removalTarget);
|
|
RaiseCollectionChangedEvent(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removalTarget));
|
|
}
|
|
|
|
public void RemoveChildRange(IEnumerable<ConnectionInfo> removalTargets)
|
|
{
|
|
foreach (var child in removalTargets)
|
|
{
|
|
RemoveChild(child);
|
|
}
|
|
}
|
|
|
|
public void SetChildPosition(ConnectionInfo child, int newIndex)
|
|
{
|
|
var originalIndex = Children.IndexOf(child);
|
|
if (originalIndex < 0 || originalIndex == newIndex || newIndex < 0) return;
|
|
Children.Remove(child);
|
|
if (newIndex > Children.Count) newIndex = Children.Count;
|
|
Children.Insert(newIndex, child);
|
|
RaiseCollectionChangedEvent(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, child, newIndex, originalIndex));
|
|
}
|
|
|
|
public void SetChildAbove(ConnectionInfo childToPromote, ConnectionInfo reference)
|
|
{
|
|
var newIndex = GetNewChildIndexAboveReference(childToPromote, reference);
|
|
SetChildPosition(childToPromote, newIndex);
|
|
}
|
|
|
|
private int GetNewChildIndexAboveReference(ConnectionInfo childToPromote, ConnectionInfo reference)
|
|
{
|
|
var originalIndex = Children.IndexOf(childToPromote);
|
|
var newIndex = Children.IndexOf(reference);
|
|
if (originalIndex < newIndex)
|
|
newIndex -= 1;
|
|
return newIndex < 0 ? 0 : newIndex;
|
|
}
|
|
|
|
public void SetChildBelow(ConnectionInfo childToPromote, ConnectionInfo reference)
|
|
{
|
|
var newIndex = GetNewChildIndexBelowReference(childToPromote, reference);
|
|
SetChildPosition(childToPromote, newIndex);
|
|
}
|
|
|
|
private int GetNewChildIndexBelowReference(ConnectionInfo childToPromote, ConnectionInfo reference)
|
|
{
|
|
var originalIndex = Children.IndexOf(childToPromote);
|
|
var newIndex = Children.IndexOf(reference);
|
|
if (originalIndex > newIndex)
|
|
newIndex += 1;
|
|
return newIndex < 0 ? 0 : newIndex;
|
|
}
|
|
|
|
public void PromoteChild(ConnectionInfo child)
|
|
{
|
|
var originalIndex = Children.IndexOf(child);
|
|
SetChildPosition(child, originalIndex - 1);
|
|
}
|
|
|
|
public void DemoteChild(ConnectionInfo child)
|
|
{
|
|
var originalIndex = Children.IndexOf(child);
|
|
SetChildPosition(child, originalIndex + 1);
|
|
}
|
|
|
|
public void Sort(ListSortDirection sortDirection = ListSortDirection.Ascending)
|
|
{
|
|
SortOn(connectionInfo => connectionInfo.Name, sortDirection);
|
|
}
|
|
|
|
public void SortOn<TProperty>(Func<ConnectionInfo, TProperty> propertyToCompare, ListSortDirection sortDirection = ListSortDirection.Ascending)
|
|
where TProperty : IComparable<TProperty>
|
|
{
|
|
var connectionComparer = new ConnectionInfoComparer<TProperty>(propertyToCompare)
|
|
{
|
|
SortDirection = sortDirection
|
|
};
|
|
Children.Sort(connectionComparer);
|
|
RaiseCollectionChangedEvent(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
|
}
|
|
|
|
public void SortRecursive(ListSortDirection sortDirection = ListSortDirection.Ascending)
|
|
{
|
|
SortOnRecursive(connectionInfo => connectionInfo.Name, sortDirection);
|
|
}
|
|
|
|
public void SortOnRecursive<TProperty>(Func<ConnectionInfo, TProperty> propertyToCompare, ListSortDirection sortDirection = ListSortDirection.Ascending)
|
|
where TProperty : IComparable<TProperty>
|
|
{
|
|
foreach (var child in Children.OfType<ContainerInfo>())
|
|
child.SortOnRecursive(propertyToCompare, sortDirection);
|
|
SortOn(propertyToCompare, sortDirection);
|
|
}
|
|
|
|
// Deep clone, recursive
|
|
public override ConnectionInfo Clone()
|
|
{
|
|
var newContainer = new ContainerInfo();
|
|
newContainer.CopyFrom(this);
|
|
newContainer.ConstantID = MiscTools.CreateConstantID();
|
|
newContainer.OpenConnections = new ProtocolList();
|
|
newContainer.Inheritance = Inheritance.Clone();
|
|
foreach (var child in Children.ToArray())
|
|
{
|
|
var newChild = child.Clone();
|
|
newChild.RemoveParent();
|
|
newContainer.AddChild(newChild);
|
|
}
|
|
return newContainer;
|
|
}
|
|
|
|
private void SetDefaults()
|
|
{
|
|
Name = "New Folder";
|
|
IsExpanded = true;
|
|
}
|
|
|
|
public IEnumerable<ConnectionInfo> GetRecursiveChildList()
|
|
{
|
|
var childList = new List<ConnectionInfo>();
|
|
foreach (var child in Children)
|
|
{
|
|
childList.Add(child);
|
|
var childContainer = child as ContainerInfo;
|
|
if (childContainer != null)
|
|
childList.AddRange(GetRecursiveChildList(childContainer));
|
|
}
|
|
return childList;
|
|
}
|
|
|
|
private IEnumerable<ConnectionInfo> GetRecursiveChildList(ContainerInfo container)
|
|
{
|
|
var childList = new List<ConnectionInfo>();
|
|
foreach (var child in container.Children)
|
|
{
|
|
childList.Add(child);
|
|
var childContainer = child as ContainerInfo;
|
|
if (childContainer != null)
|
|
childList.AddRange(GetRecursiveChildList(childContainer));
|
|
}
|
|
return childList;
|
|
}
|
|
|
|
protected virtual void SubscribeToChildEvents(ConnectionInfo child)
|
|
{
|
|
child.PropertyChanged += RaisePropertyChangedEvent;
|
|
var childAsContainer = child as ContainerInfo;
|
|
if (childAsContainer == null) return;
|
|
childAsContainer.CollectionChanged += RaiseCollectionChangedEvent;
|
|
}
|
|
|
|
protected virtual void UnsubscribeToChildEvents(ConnectionInfo child)
|
|
{
|
|
child.PropertyChanged -= RaisePropertyChangedEvent;
|
|
var childAsContainer = child as ContainerInfo;
|
|
if (childAsContainer == null) return;
|
|
childAsContainer.CollectionChanged -= RaiseCollectionChangedEvent;
|
|
}
|
|
|
|
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
private void RaiseCollectionChangedEvent(object sender, NotifyCollectionChangedEventArgs args)
|
|
{
|
|
CollectionChanged?.Invoke(sender, args);
|
|
}
|
|
}
|
|
} |