2023-01-24 15:29:31 +01:00
|
|
|
|
/* Copyright (c) Cloud Software Group, Inc.
|
2013-06-24 13:41:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms,
|
|
|
|
|
* with or without modification, are permitted provided
|
|
|
|
|
* that the following conditions are met:
|
|
|
|
|
*
|
|
|
|
|
* * Redistributions of source code must retain the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer.
|
|
|
|
|
* * Redistributions in binary form must reproduce the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer in the documentation and/or other
|
|
|
|
|
* materials provided with the distribution.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
|
|
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
|
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
|
|
namespace XenAdmin.Controls
|
|
|
|
|
{
|
|
|
|
|
partial class VirtualTreeNode
|
|
|
|
|
{
|
|
|
|
|
[DebuggerDisplay("{Tag}")]
|
|
|
|
|
public class PersistenceInfo : IEquatable<PersistenceInfo>
|
|
|
|
|
{
|
|
|
|
|
public ReadOnlyCollection<object> Path { get; private set; }
|
|
|
|
|
public ReadOnlyCollection<object> PathToMaximalSubTree { get; private set; }
|
|
|
|
|
public VirtualTreeNode Node { get; private set; }
|
|
|
|
|
public object Tag { get; private set; }
|
|
|
|
|
|
|
|
|
|
public PersistenceInfo(VirtualTreeNode node)
|
|
|
|
|
{
|
|
|
|
|
Util.ThrowIfParameterNull(node, "node");
|
|
|
|
|
|
|
|
|
|
Node = node;
|
|
|
|
|
Path = new ReadOnlyCollection<object>(GetPath(node));
|
|
|
|
|
|
|
|
|
|
var maxSubTree = MaximalSubTree(node, node.Tag);
|
|
|
|
|
PathToMaximalSubTree = new ReadOnlyCollection<object>(maxSubTree == null ? new List<object>() : GetPath(maxSubTree));
|
|
|
|
|
|
|
|
|
|
Tag = node.Tag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static List<object> GetPath(VirtualTreeNode node)
|
|
|
|
|
{
|
|
|
|
|
var path = new List<object>();
|
|
|
|
|
|
2013-10-08 11:17:57 +02:00
|
|
|
|
if (node.Tag != null && node.Parent != null)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
path.Add(node.Tag);
|
2013-10-08 11:17:57 +02:00
|
|
|
|
|
|
|
|
|
path.AddRange(new List<VirtualTreeNode>(node.Ancestors).FindAll(o => o.Parent != null).ConvertAll(n => n.Tag).FindAll(o => o != null));
|
2013-06-24 13:41:48 +02:00
|
|
|
|
path.Reverse();
|
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Find the maximal sub-tree under which the object appears only once
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="me"></param>
|
|
|
|
|
/// <param name="o"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private VirtualTreeNode MaximalSubTree(VirtualTreeNode me, Object o)
|
|
|
|
|
{
|
|
|
|
|
if (me.Parent == null)
|
|
|
|
|
return me;
|
|
|
|
|
|
|
|
|
|
foreach (VirtualTreeNode sibling in me.Parent.Nodes)
|
|
|
|
|
{
|
|
|
|
|
if (sibling == me)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (ObjectExistsUnder(o, sibling))
|
|
|
|
|
return me;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MaximalSubTree(me.Parent, o);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool ObjectExistsUnder(Object o, VirtualTreeNode parent)
|
|
|
|
|
{
|
|
|
|
|
foreach (VirtualTreeNode child in parent.Nodes)
|
|
|
|
|
{
|
|
|
|
|
if (child.Tag == o)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (ObjectExistsUnder(o, child))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
|
{
|
|
|
|
|
return Equals(obj as PersistenceInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
if (Tag == null)
|
|
|
|
|
{
|
|
|
|
|
return string.Empty.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
return Tag.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region IEquatable<SelectionInfo> Members
|
|
|
|
|
|
|
|
|
|
public bool Equals(PersistenceInfo other)
|
|
|
|
|
{
|
|
|
|
|
if (other != null)
|
|
|
|
|
{
|
|
|
|
|
if (Tag == null && other.Tag == null)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (Tag != null && other.Tag != null && Tag.Equals(other.Tag))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|