Click here to Skip to main content
15,895,833 members
Articles / Programming Languages / C#

A Generic Tree Collection

Rate me:
Please Sign up or sign in to vote.
4.87/5 (106 votes)
20 Nov 2005CPOL9 min read 229.7K   12.1K   164  
An implementation of a generic tree collection in C#.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;
using System.Security.Permissions;

[assembly: SuppressMessage( "Microsoft.Performance", "CA1804:RemoveUnusedLocals", Scope = "member", Target = "Common.NodeTree`1+EnumeratorBase`1.Count", MessageId = "o" )]
[assembly: SuppressMessage( "Microsoft.Performance", "CA1804:RemoveUnusedLocals", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair+BaseNodesEnumerableCollection.Count", MessageId = "o" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.GetNodeTree(Common.INode`1<T>):Common.NodeTree`1<T>" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.GetNodeTree(Common.ITree`1<T>):Common.NodeTree`1<T>" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.NewTree():Common.ITree`1<T>" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.NewNode():Common.INode`1<T>" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.XmlAdapterTag" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Common.NodeTree`1.XmlDeserialize(System.IO.Stream):Common.ITree`1<T>" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.IEnumerableCollectionPair`1.Nodes" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.NodeTree`1.Nodes" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.NodeTree`1+AllEnumerator.Nodes" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair.Nodes" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair+BaseNodesEnumerableCollection.GetEnumerator():System.Collections.Generic.IEnumerator`1<Common.INode`1<T>>" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+AllEnumerator" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+RootObject" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+NodeXmlSerializationAdapter" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+NodeXmlSerializationAdapter+IXmlCollection" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Scope = "type", Target = "Common.NodeTree`1+TreeXmlSerializationAdapter" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "Common.NodeTree`1.Dispose():System.Void" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "Common.NodeTree`1.Finalize():System.Void" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair+BaseNodesEnumerableCollection.Dispose():System.Void" )]
[assembly: SuppressMessage( "Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Scope = "member", Target = "Common.NodeTree`1+BaseEnumerableCollectionPair+BaseNodesEnumerableCollection.Finalize():System.Void" )]
[assembly: SuppressMessage( "Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible", Scope = "member", Target = "Common.NodeTree`1.XmlAdapterTag" )]
[assembly: SuppressMessage( "Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Scope = "member", Target = "Common.NodeTree`1+NodeXmlSerializationAdapter.Children" )]

namespace Common
{

	//-----------------------------------------------------------------------------
	// IDeepCopy

	public interface IDeepCopy
	{
		object CreateDeepCopy();
	}

	//-----------------------------------------------------------------------------
	// IEnumerableCollection

	public interface IEnumerableCollection<T> : IEnumerable<T>, ICollection
	{
		bool Contains( T item );
	}

	//-----------------------------------------------------------------------------
	// IEnumerableCollectionPair

	public interface IEnumerableCollectionPair<T>
	{
		IEnumerableCollection<INode<T>> Nodes { get; }
		IEnumerableCollection<T> Values { get; }
	}

	//-----------------------------------------------------------------------------
	// EventArgs

	public class NodeTreeDataEventArgs<T> : EventArgs
	{
		private T _Data = default( T );

		public T Data { get { return _Data; } }

		public NodeTreeDataEventArgs( T data )
		{
			_Data = data;
		}
	}

	public class NodeTreeNodeEventArgs<T> : EventArgs
	{
		private INode<T> _Node = null;

		public INode<T> Node { get { return _Node; } }

		public NodeTreeNodeEventArgs( INode<T> node )
		{
			_Node = node;
		}
	}

	public enum NodeTreeInsertOperation
	{
		Previous,
		Next,
		Child,
		Tree
	}

	public class NodeTreeInsertEventArgs<T> : EventArgs
	{
		private NodeTreeInsertOperation _Operation;
		public NodeTreeInsertOperation Operation { get { return _Operation; } }

		private INode<T> _Node = null;
		public INode<T> Node { get { return _Node; } }

		public NodeTreeInsertEventArgs( NodeTreeInsertOperation operation, INode<T> node )
		{
			_Operation = operation;
			_Node = node;
		}
	}

	//-----------------------------------------------------------------------------
	// INode<T>

	public interface INode<T> : IEnumerableCollectionPair<T>, IDisposable//, ICollection<T>
	{
		T Data { get; set; }

		string ToStringRecursive();

		int Depth { get; }
		int BranchIndex { get; }
		int BranchCount { get; }

		int Count { get; }
		int DirectChildCount { get; }

		INode<T> Parent { get; }
		INode<T> Previous { get; }
		INode<T> Next { get; }
		INode<T> Child { get; }

		ITree<T> Tree { get; }

		INode<T> Root { get; }
		INode<T> Top { get; }
		INode<T> First { get; }
		INode<T> Last { get; }

		INode<T> LastChild { get; }

		bool IsTree { get; }
		bool IsRoot { get; }
		bool IsTop { get; }
		bool HasParent { get; }
		bool HasPrevious { get; }
		bool HasNext { get; }
		bool HasChild { get; }
		bool IsFirst { get; }
		bool IsLast { get; }

		INode<T> this[ T item ] { get; }

		bool Contains( INode<T> item );
		bool Contains( T item );

		INode<T> InsertPrevious( T o );
		INode<T> InsertNext( T o );
		INode<T> InsertChild( T o );
		INode<T> Add( T o );
		INode<T> AddChild( T o );

		void InsertPrevious( ITree<T> tree );
		void InsertNext( ITree<T> tree );
		void InsertChild( ITree<T> tree );
		void Add( ITree<T> tree );
		void AddChild( ITree<T> tree );

		ITree<T> Cut( T o );
		ITree<T> Copy( T o );
		ITree<T> DeepCopy( T o );
		bool Remove( T o );

		ITree<T> Cut();
		ITree<T> Copy();
		ITree<T> DeepCopy();
		void Remove();

		bool CanMoveToParent { get; }
		bool CanMoveToPrevious { get; }
		bool CanMoveToNext { get; }
		bool CanMoveToChild { get; }
		bool CanMoveToFirst { get; }
		bool CanMoveToLast { get; }

		void MoveToParent();
		void MoveToPrevious();
		void MoveToNext();
		void MoveToChild();
		void MoveToFirst();
		void MoveToLast();

		IEnumerableCollectionPair<T> All { get; }
		IEnumerableCollectionPair<T> AllChildren { get; }
		IEnumerableCollectionPair<T> DirectChildren { get; }
		IEnumerableCollectionPair<T> DirectChildrenInReverse { get; }

		event EventHandler<NodeTreeDataEventArgs<T>> Validate;
		event EventHandler<NodeTreeDataEventArgs<T>> Setting;
		event EventHandler<NodeTreeDataEventArgs<T>> SetDone;
		event EventHandler<NodeTreeInsertEventArgs<T>> Inserting;
		event EventHandler<NodeTreeInsertEventArgs<T>> Inserted;
		event EventHandler Cutting;
		event EventHandler CutDone;
		event EventHandler<NodeTreeNodeEventArgs<T>> Copying;
		event EventHandler<NodeTreeNodeEventArgs<T>> Copied;
		event EventHandler<NodeTreeNodeEventArgs<T>> DeepCopying;
		event EventHandler<NodeTreeNodeEventArgs<T>> DeepCopied;
	}

	//-----------------------------------------------------------------------------
	// ITree<T>

	public interface ITree<T> : IEnumerableCollectionPair<T>, IDisposable//, ICollection<T>
	{
		Type DataType { get; }

		IEqualityComparer<T> DataComparer { get; set; }

		void XmlSerialize( Stream stream );

		void Clear();
		int Count { get; }
		int DirectChildCount { get; }

		INode<T> Root { get; }

		INode<T> this[ T o ] { get; }

		string ToStringRecursive();

		bool Contains( T item );
		bool Contains( INode<T> item );

		INode<T> InsertChild( T o );
		INode<T> AddChild( T o );

		void InsertChild( ITree<T> tree );
		void AddChild( ITree<T> tree );

		ITree<T> Cut( T o );
		ITree<T> Copy( T o );
		ITree<T> DeepCopy( T o );
		bool Remove( T o );

		ITree<T> Copy();
		ITree<T> DeepCopy();

		IEnumerableCollectionPair<T> All { get; }
		IEnumerableCollectionPair<T> AllChildren { get; }
		IEnumerableCollectionPair<T> DirectChildren { get; }
		IEnumerableCollectionPair<T> DirectChildrenInReverse { get; }

		event EventHandler<NodeTreeDataEventArgs<T>> Validate;
		event EventHandler Clearing;
		event EventHandler Cleared;
		event EventHandler<NodeTreeDataEventArgs<T>> Setting;
		event EventHandler<NodeTreeDataEventArgs<T>> SetDone;
		event EventHandler<NodeTreeInsertEventArgs<T>> Inserting;
		event EventHandler<NodeTreeInsertEventArgs<T>> Inserted;
		event EventHandler Cutting;
		event EventHandler CutDone;
		event EventHandler<NodeTreeNodeEventArgs<T>> Copying;
		event EventHandler<NodeTreeNodeEventArgs<T>> Copied;
		event EventHandler<NodeTreeNodeEventArgs<T>> DeepCopying;
		event EventHandler<NodeTreeNodeEventArgs<T>> DeepCopied;
	}

	//-----------------------------------------------------------------------------
	// NodeTree

	[Serializable]
	public class NodeTree<T> : INode<T>, ITree<T>, ISerializable
	{
		private T _Data = default( T );

		private NodeTree<T> _Parent = null;
		private NodeTree<T> _Previous = null;
		private NodeTree<T> _Next = null;
		private NodeTree<T> _Child = null;

		protected NodeTree() { }

		~NodeTree()
		{
			Dispose( false );
		}

		public void Dispose()
		{
			Dispose( true );

			GC.SuppressFinalize( this );
		}

		protected virtual void Dispose( bool disposing )
		{
			if ( disposing )
			{
				if ( _EventHandlerList != null ) _EventHandlerList.Dispose();
			}
		}

		//-----------------------------------------------------------------------------
		// Instantiation

		public static ITree<T> NewTree()
		{
			return new RootObject();
		}

		public static ITree<T> NewTree( IEqualityComparer<T> dataComparer )
		{
			return new RootObject( dataComparer );
		}

		protected static INode<T> NewNode()
		{
			return new NodeTree<T>();
		}

		protected virtual NodeTree<T> CreateTree()
		{
			return new RootObject();
		}

		protected virtual NodeTree<T> CreateNode()
		{
			return new NodeTree<T>();
		}

		//-----------------------------------------------------------------------------
		// ToString

		/// <summary>Obtains the <see cref="String"/> representation of this instance.</summary>
		/// <returns>The <see cref="String"/> representation of this instance.</returns>
		/// <remarks>
		/// <p>
		/// This method returns a <see cref="String"/> that represents this instance.
		/// </p>
		/// </remarks>
		public override string ToString()
		{
			T data = Data;
			if ( data == null ) return String.Empty;
			return data.ToString();
		}

		public virtual string ToStringRecursive()
		{
			string s = String.Empty;

			foreach ( NodeTree<T> node in All.Nodes )
				s += new String( '\t', node.Depth ) + node + Environment.NewLine;

			return s;
		}

		//-----------------------------------------------------------------------------
		// Counts

		public virtual int Depth
		{
			get
			{
				int i = -1;

				for ( INode<T> node = this ; !node.IsRoot ; node = node.Parent ) i++;

				return i;
			}
		}

		public virtual int BranchIndex
		{
			get
			{
				int i = -1;

				for ( INode<T> node = this ; node != null ; node = node.Previous ) i++;

				return i;
			}
		}

		public virtual int BranchCount
		{
			get
			{
				int i = 0;

				for ( INode<T> node = First ; node != null ; node = node.Next ) i++;

				return i;
			}
		}

		//-----------------------------------------------------------------------------
		// DeepCopyData

		[ReflectionPermission( SecurityAction.Demand, Unrestricted = true )]
		protected virtual T DeepCopyData( T data )
		{
			//if ( ! Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			if ( data == null ) { Debug.Assert( true ); return default( T ); }

			// IDeepCopy
			IDeepCopy deepCopy = data as IDeepCopy;
			if ( deepCopy != null ) return ( T ) deepCopy.CreateDeepCopy();

			// ICloneable
			ICloneable cloneable = data as ICloneable;
			if ( cloneable != null ) return ( T ) cloneable.Clone();

			// Copy constructor
			ConstructorInfo ctor = data.GetType().GetConstructor(
				 BindingFlags.Instance | BindingFlags.Public,
				 null, new Type[] { typeof( T ) }, null );
			if ( ctor != null ) return ( T ) ctor.Invoke( new object[] { data } );
			//return ( T ) Activator.CreateInstance( typeof( T ), new object[] { data } );

			// give up
			return data;
		}

		//-----------------------------------------------------------------------------
		// RootObject

		[Serializable]
		protected class RootObject : NodeTree<T>
		{
			private int _Version = 0;
			protected override int Version
			{
				get { return _Version; }
				set { _Version = value; }
			}

			private IEqualityComparer<T> _DataComparer;
			public override IEqualityComparer<T> DataComparer
			{
				get
				{
					if ( _DataComparer == null ) _DataComparer = EqualityComparer<T>.Default;

					return _DataComparer;
				}

				set { _DataComparer = value; }
			}

			public RootObject()
			{
			}

			public RootObject( IEqualityComparer<T> dataComparer )
			{
				_DataComparer = dataComparer;
			}

			/// <summary>Obtains the <see cref="String"/> representation of this instance.</summary>
			/// <returns>The <see cref="String"/> representation of this instance.</returns>
			/// <remarks>
			/// <p>
			/// This method returns a <see cref="String"/> that represents this instance.
			/// </p>
			/// </remarks>
			public override string ToString() { return "ROOT: " + DataType.Name; }

			// Save
			/// <summary>Populates a SerializationInfo with the data needed to serialize the target T.</summary>
			/// <param name="info">The SerializationInfo to populate with data.</param>
			/// <param name="context">The destination for this serialization.</param>
			/// <remarks>
			/// <p>This method is called during serialization.</p>
			/// <p>Do not call this method directly.</p>
			/// </remarks>
			[SecurityPermission( SecurityAction.Demand, SerializationFormatter = true )]
			public override void GetObjectData( SerializationInfo info, StreamingContext context )
			{
				base.GetObjectData( info, context );

				info.AddValue( "RootObjectVersion", 1 );
				//info.AddValue( "DataType", _DataType );
			}

			// Load
			/// <summary>Initializes a new instance of the class during deserialization.</summary>
			/// <param name="info">The SerializationInfo populated with data.</param>
			/// <param name="context">The source for this serialization.</param>
			/// <remarks>
			/// <p>This method is called during deserialization.</p>
			/// <p>Do not call this method directly.</p>
			/// </remarks>
			protected RootObject( SerializationInfo info, StreamingContext context )
				: base( info, context )
			{
				int iVersion = info.GetInt32( "RootObjectVersion" );
				if ( iVersion != 1 ) throw new SerializationException( "Unknown version" );

				//_DataType = info.GetValue( "DataType", typeof( Type ) ) as Type;
			}
		}

		//-----------------------------------------------------------------------------
		// GetRootObject

		protected virtual RootObject GetRootObject
		{
			get
			{
				return ( RootObject ) Root;
			}
		}

		//-----------------------------------------------------------------------------
		// DataComparer

		public virtual IEqualityComparer<T> DataComparer
		{
			get
			{
				if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a Tree" );

				return GetRootObject.DataComparer;
			}

			set
			{
				if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a Tree" );

				GetRootObject.DataComparer = value;
			}
		}

		//-----------------------------------------------------------------------------
		// Version

		protected virtual int Version
		{
			get
			{
				INode<T> root = Root;

				if ( !root.IsTree ) throw new InvalidOperationException( "This is not a Tree" );

				return GetNodeTree( root ).Version;
			}

			set
			{
				INode<T> root = Root;

				if ( !root.IsTree ) throw new InvalidOperationException( "This is not a Tree" );

				GetNodeTree( root ).Version = value;
			}
		}

		protected bool HasChanged( int version ) { return ( Version != version ); }

		protected void IncrementVersion()
		{
			INode<T> root = Root;

			if ( !root.IsTree ) throw new InvalidOperationException( "This is not a Tree" );

			GetNodeTree( root ).Version++;
		}

		//-----------------------------------------------------------------------------
		// ISerializable

		// Save
		/// <summary>Populates a SerializationInfo with the data needed to serialize the target T.</summary>
		/// <param name="info">The SerializationInfo to populate with data.</param>
		/// <param name="context">The destination for this serialization.</param>
		/// <remarks>
		/// <p>This method is called during serialization.</p>
		/// <p>Do not call this method directly.</p>
		/// </remarks>
		[SecurityPermission( SecurityAction.Demand, SerializationFormatter = true )]
		public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
		{
			info.AddValue( "NodeTreeVersion", 1 );
			info.AddValue( "Data", _Data );
			info.AddValue( "Parent", _Parent );
			info.AddValue( "Previous", _Previous );
			info.AddValue( "Next", _Next );
			info.AddValue( "Child", _Child );
		}

		// Load
		/// <summary>Initializes a new instance of the class during deserialization.</summary>
		/// <param name="info">The SerializationInfo populated with data.</param>
		/// <param name="context">The source for this serialization.</param>
		/// <remarks>
		/// <p>This method is called during deserialization.</p>
		/// <p>Do not call this method directly.</p>
		/// </remarks>
		protected NodeTree( SerializationInfo info, StreamingContext context )
		{
			int iVersion = info.GetInt32( "NodeTreeVersion" );
			if ( iVersion != 1 ) throw new SerializationException( "Unknown version" );

			_Data = ( T ) info.GetValue( "Data", typeof( T ) );
			_Parent = ( NodeTree<T> ) info.GetValue( "Parent", typeof( NodeTree<T> ) );
			_Previous = ( NodeTree<T> ) info.GetValue( "Previous", typeof( NodeTree<T> ) );
			_Next = ( NodeTree<T> ) info.GetValue( "Next", typeof( NodeTree<T> ) );
			_Child = ( NodeTree<T> ) info.GetValue( "Child", typeof( NodeTree<T> ) );
		}

		//-----------------------------------------------------------------------------
		// XmlSerialization

		public virtual void XmlSerialize( Stream stream )
		{
			XmlSerializer xmlSerializer;

			try
			{
				xmlSerializer = new XmlSerializer( typeof( TreeXmlSerializationAdapter ) );
			}
			catch ( Exception x )
			{
				Debug.Assert( x == null ); // false
				throw;
			}

			try
			{
				xmlSerializer.Serialize( stream, new TreeXmlSerializationAdapter( XmlAdapterTag, this ) );
			}
			catch ( Exception x )
			{
				Debug.Assert( x == null ); // false
				throw;
			}

		}

		public static ITree<T> XmlDeserialize( Stream stream )
		{
			XmlSerializer xmlSerializer;

			try
			{
				xmlSerializer = new XmlSerializer( typeof( TreeXmlSerializationAdapter ) );
			}
			catch ( Exception x )
			{
				Debug.Assert( x == null ); // false
				throw;
			}

			object o;

			try
			{
				o = xmlSerializer.Deserialize( stream );
			}
			catch ( Exception x )
			{
				Debug.Assert( x == null ); // false
				throw;
			}

			TreeXmlSerializationAdapter adapter = ( TreeXmlSerializationAdapter ) o;

			ITree<T> tree = adapter.Tree;

			return tree;
		}

		//-----------------------------------------------------------------------------

		protected static readonly object XmlAdapterTag = new object();

		[XmlType( "Tree" )]
		public class TreeXmlSerializationAdapter
		{
			private int _Version = 0;

			[XmlAttribute]
			public int Version
			{
				get { return 1; }
				set { _Version = value; }
			}

			private ITree<T> _Tree;

			[XmlIgnore]
			public ITree<T> Tree
			{
				get { return _Tree; }
			}

			private TreeXmlSerializationAdapter()
			{
			}

			public TreeXmlSerializationAdapter( object tag, ITree<T> tree )
			{
				if ( !ReferenceEquals( XmlAdapterTag, tag ) ) throw new InvalidOperationException( "Don't use this class" );

				_Tree = tree;
			}

			public NodeXmlSerializationAdapter Root
			{
				get
				{
					return new NodeXmlSerializationAdapter( XmlAdapterTag, _Tree.Root );
				}

				set
				{
					_Tree = NodeTree<T>.NewTree();

					ReformTree( _Tree.Root, value );
				}
			}

			private void ReformTree( INode<T> parent, NodeXmlSerializationAdapter node )
			{
				foreach ( NodeXmlSerializationAdapter child in node.Children )
				{
					INode<T> n = parent.AddChild( child.Data );

					ReformTree( n, child );
				}
			}

		}

		[XmlType( "Node" )]
		public class NodeXmlSerializationAdapter
		{
			private int _Version = 0;

			[XmlAttribute]
			public int Version
			{
				get { return 1; }
				set { _Version = value; }
			}

			private INode<T> _Node;

			private IXmlCollection _Children = new ChildCollection();

			[XmlIgnore]
			public INode<T> Node
			{
				get { return _Node; }
			}

			// Load
			private NodeXmlSerializationAdapter()
			{
				_Node = NodeTree<T>.NewNode();
			}

			// Save
			public NodeXmlSerializationAdapter( object tag, INode<T> node )
			{
				if ( !ReferenceEquals( XmlAdapterTag, tag ) ) throw new InvalidOperationException( "Don't use this class" );

				_Node = node;

				foreach ( INode<T> child in node.DirectChildren.Nodes )
					_Children.Add( new NodeXmlSerializationAdapter( XmlAdapterTag, child ) );
			}

			public T Data
			{
				get { return _Node.Data; }

				set
				{
					GetNodeTree( _Node )._Data = value;
				}
			}

			public IXmlCollection Children
			{
				get { return _Children; }
				set { Debug.Assert( value == null ); }
			}

			public interface IXmlCollection : ICollection
			{
				NodeXmlSerializationAdapter this[ int index ] { get; }

				void Add( NodeXmlSerializationAdapter item );
			}

			private class ChildCollection : List<NodeXmlSerializationAdapter>, IXmlCollection { }
		}


		//-----------------------------------------------------------------------------
		// INode<T>

		public T Data
		{
			get
			{
				return _Data;
			}

			set
			{
				if ( IsRoot ) throw new InvalidOperationException( "This is a Root" );

				OnSetting( this, value );

				_Data = value;

				OnSetDone( this, value );
			}
		}

		public INode<T> Parent { get { return _Parent; } }
		public INode<T> Previous { get { return _Previous; } }
		public INode<T> Next { get { return _Next; } }
		public INode<T> Child { get { return _Child; } }

		//-----------------------------------------------------------------------------

		public ITree<T> Tree
		{
			get
			{
				return ( ITree<T> ) Root;
			}
		}

		public INode<T> Root
		{
			get
			{
				INode<T> node = this;

				while ( node.Parent != null )
					node = node.Parent;

				return node;
			}
		}

		public INode<T> Top
		{
			get
			{
				if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );
				//if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
				if ( this.IsRoot ) return null;

				INode<T> node = this;

				while ( node.Parent.Parent != null )
					node = node.Parent;

				return node;
			}
		}

		public INode<T> First
		{
			get
			{
				INode<T> node = this;

				while ( node.Previous != null )
					node = node.Previous;

				return node;
			}
		}

		public INode<T> Last
		{
			get
			{
				INode<T> node = this;

				while ( node.Next != null )
					node = node.Next;

				return node;
			}
		}

		public INode<T> LastChild
		{
			get
			{
				if ( Child == null ) return null;
				return Child.Last;
			}
		}

		//-----------------------------------------------------------------------------

		public bool HasPrevious { get { return Previous != null; } }
		public bool HasNext { get { return Next != null; } }
		public bool HasChild { get { return Child != null; } }
		public bool IsFirst { get { return Previous == null; } }
		public bool IsLast { get { return Next == null; } }

		public bool IsTree
		{
			get
			{
				if ( !IsRoot ) return false;
				return this is RootObject;
			}
		}

		public bool IsRoot
		{
			get
			{
				bool b = ( Parent == null );

				if ( b )
				{
					Debug.Assert( Previous == null );
					Debug.Assert( Next == null );
				}

				return b;
			}
		}

		public bool HasParent
		{
			get
			{
				//if ( IsRoot ) throw new InvalidOperationException( "This is a Root" );
				if ( IsRoot ) return false;
				return Parent.Parent != null;
			}
		}

		public bool IsTop
		{
			get
			{
				//if ( IsRoot ) throw new InvalidOperationException( "This is a Root" );
				if ( IsRoot ) return false;
				return Parent.Parent == null;
			}
		}

		//-----------------------------------------------------------------------------

		public virtual INode<T> this[ T item ]
		{
			get
			{
				if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

				IEqualityComparer<T> comparer = DataComparer;

				foreach ( INode<T> n in All.Nodes )
					if ( comparer.Equals( n.Data, item ) )
						return n;

				return null;
			}
		}

		public virtual bool Contains( INode<T> item )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			return All.Nodes.Contains( item );
		}

		public virtual bool Contains( T item )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			return All.Values.Contains( item );
		}

		//-----------------------------------------------------------------------------

		public INode<T> InsertPrevious( T o )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			NodeTree<T> newNode = CreateNode();
			newNode._Data = o;

			this.InsertPreviousCore( newNode );

			return newNode;
		}

		public INode<T> InsertNext( T o )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			NodeTree<T> newNode = CreateNode();
			newNode._Data = o;

			this.InsertNextCore( newNode );

			return newNode;
		}

		public INode<T> InsertChild( T o )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			NodeTree<T> newNode = CreateNode();
			newNode._Data = o;

			this.InsertChildCore( newNode );

			return newNode;
		}

		public INode<T> Add( T o )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			return this.Last.InsertNext( o );
		}

		public INode<T> AddChild( T o )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			if ( Child == null )
				return InsertChild( o );
			else
				return Child.Add( o );
		}

		//-----------------------------------------------------------------------------

		public void InsertPrevious( ITree<T> tree )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			NodeTree<T> newTree = GetNodeTree( tree );

			if ( !newTree.IsRoot ) throw new ArgumentException( "Tree is not a Root" );
			if ( !newTree.IsTree ) throw new ArgumentException( "Tree is not a tree" );

			for ( INode<T> n = newTree.Child ; n != null ; n = n.Next )
			{
				NodeTree<T> node = GetNodeTree( n );
				NodeTree<T> copy = node.CopyCore();
				InsertPreviousCore( copy );
			}
		}

		public void InsertNext( ITree<T> tree )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			NodeTree<T> newTree = GetNodeTree( tree );

			if ( !newTree.IsRoot ) throw new ArgumentException( "Tree is not a Root" );
			if ( !newTree.IsTree ) throw new ArgumentException( "Tree is not a tree" );

			for ( INode<T> n = newTree.LastChild ; n != null ; n = n.Previous )
			{
				NodeTree<T> node = GetNodeTree( n );
				NodeTree<T> copy = node.CopyCore();
				InsertNextCore( copy );
			}
		}

		public void InsertChild( ITree<T> tree )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			NodeTree<T> newTree = GetNodeTree( tree );

			if ( !newTree.IsRoot ) throw new ArgumentException( "Tree is not a Root" );
			if ( !newTree.IsTree ) throw new ArgumentException( "Tree is not a tree" );

			for ( INode<T> n = newTree.LastChild ; n != null ; n = n.Previous )
			{
				NodeTree<T> node = GetNodeTree( n );
				NodeTree<T> copy = node.CopyCore();
				InsertChildCore( copy );
			}
		}

		public void Add( ITree<T> tree )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			this.Last.InsertNext( tree );
		}

		public void AddChild( ITree<T> tree )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			if ( this.Child == null )
				this.InsertChild( tree );
			else
				this.Child.Add( tree );
		}

		//-----------------------------------------------------------------------------

		protected virtual void InsertPreviousCore( INode<T> newINode )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !newINode.IsRoot ) throw new ArgumentException( "Node is not a Root" );
			if ( newINode.IsTree ) throw new ArgumentException( "Node is a tree" );

			IncrementVersion();

			OnInserting( this, NodeTreeInsertOperation.Previous, newINode );

			NodeTree<T> newNode = GetNodeTree( newINode );

			newNode._Parent = this._Parent;
			newNode._Previous = this._Previous;
			newNode._Next = this;
			this._Previous = newNode;

			if ( newNode.Previous != null )
			{
				NodeTree<T> Previous = GetNodeTree( newNode.Previous );
				Previous._Next = newNode;
			}
			else // this is a first node
			{
				NodeTree<T> Parent = GetNodeTree( newNode.Parent );
				Parent._Child = newNode;
			}

			OnInserted( this, NodeTreeInsertOperation.Previous, newINode );
		}

		protected virtual void InsertNextCore( INode<T> newINode )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !newINode.IsRoot ) throw new ArgumentException( "Node is not a Root" );
			if ( newINode.IsTree ) throw new ArgumentException( "Node is a tree" );

			IncrementVersion();

			OnInserting( this, NodeTreeInsertOperation.Next, newINode );

			NodeTree<T> newNode = GetNodeTree( newINode );

			newNode._Parent = this._Parent;
			newNode._Previous = this;
			newNode._Next = this._Next;
			this._Next = newNode;

			if ( newNode.Next != null )
			{
				NodeTree<T> Next = GetNodeTree( newNode.Next );
				Next._Previous = newNode;
			}

			OnInserted( this, NodeTreeInsertOperation.Next, newINode );
		}

		protected virtual void InsertChildCore( INode<T> newINode )
		{
			if ( !newINode.IsRoot ) throw new ArgumentException( "Node is not a Root" );
			if ( newINode.IsTree ) throw new ArgumentException( "Node is a tree" );

			IncrementVersion();

			OnInserting( this, NodeTreeInsertOperation.Child, newINode );

			NodeTree<T> newNode = GetNodeTree( newINode );

			newNode._Parent = this;
			newNode._Next = this._Child;
			this._Child = newNode;

			if ( newNode.Next != null )
			{
				NodeTree<T> Next = GetNodeTree( newNode.Next );
				Next._Previous = newNode;
			}

			OnInserted( this, NodeTreeInsertOperation.Child, newINode );
		}

		protected virtual void AddCore( INode<T> newINode )
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );

			NodeTree<T> lastNode = GetNodeTree( Last );

			lastNode.InsertNextCore( newINode );
		}

		protected virtual void AddChildCore( INode<T> newINode )
		{
			if ( this.Child == null )
				this.InsertChildCore( newINode );
			else
			{
				NodeTree<T> childNode = GetNodeTree( Child );

				childNode.AddCore( newINode );
			}
		}

		//-----------------------------------------------------------------------------

		public ITree<T> Cut( T o )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			INode<T> n = this[ o ];
			if ( n == null ) return null;
			return n.Cut();
		}

		public ITree<T> Copy( T o )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			INode<T> n = this[ o ];
			if ( n == null ) return null;
			return n.Copy();
		}

		public ITree<T> DeepCopy( T o )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			INode<T> n = this[ o ];
			if ( n == null ) return null;
			return n.DeepCopy();
		}

		public bool Remove( T o )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			INode<T> n = this[ o ];
			if ( n == null ) return false;

			n.Remove();
			return true;
		}

		//-----------------------------------------------------------------------------

		private NodeTree<T> BoxInTree( NodeTree<T> node )
		{
			if ( !node.IsRoot ) throw new ArgumentException( "Node is not a Root" );
			if ( node.IsTree ) throw new ArgumentException( "Node is a tree" );

			NodeTree<T> tree = CreateTree();

			tree.AddChildCore( node );

			return tree;
		}

		public ITree<T> Cut()
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			NodeTree<T> node = CutCore();

			return BoxInTree( node );
		}

		public ITree<T> Copy()
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			if ( IsTree )
			{
				NodeTree<T> NewTree = CopyCore();

				return NewTree;
			}
			else
			{
				NodeTree<T> NewNode = CopyCore();

				return BoxInTree( NewNode );
			}
		}

		public ITree<T> DeepCopy()
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			if ( IsTree )
			{
				NodeTree<T> NewTree = DeepCopyCore();

				return NewTree;
			}
			else
			{
				NodeTree<T> NewNode = DeepCopyCore();

				return BoxInTree( NewNode );
			}
		}

		public void Remove()
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			RemoveCore();
		}

		//-----------------------------------------------------------------------------

		protected virtual NodeTree<T> CutCore()
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );

			IncrementVersion();

			OnCutting( this );

			INode<T> OldRoot = Root;

			if ( this._Next != null )
				this._Next._Previous = this._Previous;

			if ( this.Previous != null )
				this._Previous._Next = this._Next;
			else // this is a first node
			{
				Debug.Assert( Parent.Child == this );
				this._Parent._Child = this._Next;
				Debug.Assert( this.Next == null || this.Next.Previous == null );
			}

			this._Parent = null;
			this._Previous = null;
			this._Next = null;

			OnCutDone( OldRoot, this );

			return this;
		}

		protected virtual NodeTree<T> CopyCore()
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );
			if ( IsRoot && !IsTree ) throw new InvalidOperationException( "This is a Root" );

			if ( IsTree )
			{
				NodeTree<T> NewTree = CreateTree();

				OnCopying( this, NewTree );

				CopyChildNodes( this, NewTree, false );

				OnCopied( this, NewTree );

				return NewTree;
			}
			else
			{
				NodeTree<T> NewNode = CreateNode();

				NewNode._Data = Data;

				OnCopying( this, NewNode );

				CopyChildNodes( this, NewNode, false );

				OnCopied( this, NewNode );

				return NewNode;
			}
		}

		protected virtual NodeTree<T> DeepCopyCore()
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );
			if ( IsRoot && !IsTree ) throw new InvalidOperationException( "This is a Root" );

			if ( IsTree )
			{
				NodeTree<T> NewTree = CreateTree();

				OnCopying( this, NewTree );

				CopyChildNodes( this, NewTree, true );

				OnCopied( this, NewTree );

				return NewTree;
			}
			else
			{
				NodeTree<T> NewNode = CreateNode();

				NewNode._Data = DeepCopyData( Data );

				OnDeepCopying( this, NewNode );

				CopyChildNodes( this, NewNode, true );

				OnDeepCopied( this, NewNode );

				return NewNode;
			}
		}

		private void CopyChildNodes( INode<T> oldNode, NodeTree<T> newNode, bool bDeepCopy )
		{
			NodeTree<T> previousNewChildNode = null;

			for ( INode<T> oldChildNode = oldNode.Child ; oldChildNode != null ; oldChildNode = oldChildNode.Next )
			{
				NodeTree<T> newChildNode = CreateNode();

				if ( !bDeepCopy )
					newChildNode._Data = oldChildNode.Data;
				else
					newChildNode._Data = DeepCopyData( oldChildNode.Data );

				//				if ( ! bDeepCopy )
				//					OnCopying( oldChildNode, newChildNode );
				//				else
				//					OnDeepCopying( oldChildNode, newChildNode );

				if ( oldChildNode.Previous == null ) newNode._Child = newChildNode;

				newChildNode._Parent = newNode;
				newChildNode._Previous = previousNewChildNode;
				if ( previousNewChildNode != null ) previousNewChildNode._Next = newChildNode;

				//				if ( ! bDeepCopy )
				//					OnCopied( oldChildNode, newChildNode );
				//				else
				//					OnDeepCopied( oldChildNode, newChildNode );

				CopyChildNodes( oldChildNode, newChildNode, bDeepCopy );

				previousNewChildNode = newChildNode;
			}
		}


		protected virtual void RemoveCore()
		{
			if ( this.IsRoot ) throw new InvalidOperationException( "This is a Root" );

			CutCore();
		}

		//-----------------------------------------------------------------------------

		public bool CanMoveToParent
		{
			get
			{
				if ( this.IsRoot ) return false;
				if ( this.IsTop ) return false;

				return true;
			}
		}

		public bool CanMoveToPrevious
		{
			get
			{
				if ( this.IsRoot ) return false;
				if ( this.IsFirst ) return false;

				return true;
			}
		}

		public bool CanMoveToNext
		{
			get
			{
				if ( this.IsRoot ) return false;
				if ( this.IsLast ) return false;

				return true;
			}
		}

		public bool CanMoveToChild
		{
			get
			{
				if ( this.IsRoot ) return false;
				if ( this.IsFirst ) return false;

				return true;
			}
		}

		public bool CanMoveToFirst
		{
			get
			{
				if ( this.IsRoot ) return false;
				if ( this.IsFirst ) return false;

				return true;
			}
		}

		public bool CanMoveToLast
		{
			get
			{
				if ( this.IsRoot ) return false;
				if ( this.IsLast ) return false;

				return true;
			}
		}

		//-----------------------------------------------------------------------------

		public void MoveToParent()
		{
			if ( !CanMoveToParent ) throw new InvalidOperationException( "Cannot move to Parent" );

			NodeTree<T> parentNode = GetNodeTree( this.Parent );

			NodeTree<T> thisNode = this.CutCore();

			parentNode.InsertNextCore( thisNode );
		}

		public void MoveToPrevious()
		{
			if ( !CanMoveToPrevious ) throw new InvalidOperationException( "Cannot move to Previous" );

			NodeTree<T> previousNode = GetNodeTree( this.Previous );

			NodeTree<T> thisNode = this.CutCore();

			previousNode.InsertPreviousCore( thisNode );
		}

		public void MoveToNext()
		{
			if ( !CanMoveToNext ) throw new InvalidOperationException( "Cannot move to Next" );

			NodeTree<T> nextNode = GetNodeTree( this.Next );

			NodeTree<T> thisNode = this.CutCore();

			nextNode.InsertNextCore( thisNode );
		}

		public void MoveToChild()
		{
			if ( !CanMoveToChild ) throw new InvalidOperationException( "Cannot move to Child" );

			NodeTree<T> previousNode = GetNodeTree( this.Previous );

			NodeTree<T> thisNode = this.CutCore();

			previousNode.AddChildCore( thisNode );
		}

		public void MoveToFirst()
		{
			if ( !CanMoveToFirst ) throw new InvalidOperationException( "Cannot move to first" );

			NodeTree<T> firstNode = GetNodeTree( this.First );

			NodeTree<T> thisNode = this.CutCore();

			firstNode.InsertPreviousCore( thisNode );
		}


		public void MoveToLast()
		{
			if ( !CanMoveToLast ) throw new InvalidOperationException( "Cannot move to last" );

			NodeTree<T> lastNode = GetNodeTree( this.Last );

			NodeTree<T> thisNode = this.CutCore();

			lastNode.InsertNextCore( thisNode );
		}

		//-----------------------------------------------------------------------------
		// Enumerators

		public virtual IEnumerableCollection<INode<T>> Nodes
		{
			get
			{
				return All.Nodes;
			}
		}

		public virtual IEnumerableCollection<T> Values
		{
			get
			{
				return All.Values;
			}
		}

		//-----------------------------------------------------------------------------
		// BaseEnumerableCollectionPair

		protected abstract class BaseEnumerableCollectionPair : IEnumerableCollectionPair<T>
		{
			private NodeTree<T> _Root = null;

			protected NodeTree<T> Root
			{
				get { return _Root; }
				set { _Root = value; }
			}

			protected BaseEnumerableCollectionPair( NodeTree<T> root )
			{
				_Root = root;
			}

			// Nodes
			public abstract IEnumerableCollection<INode<T>> Nodes { get; }

			protected abstract class BaseNodesEnumerableCollection : IEnumerableCollection<INode<T>>, IEnumerator<INode<T>>
			{
				private int _Version = 0;
				private object _SyncRoot = new object();

				private NodeTree<T> _Root = null;
				protected NodeTree<T> Root
				{
					get { return _Root; }
					set { _Root = value; }
				}

				private INode<T> _CurrentNode = null;
				protected INode<T> CurrentNode
				{
					get { return _CurrentNode; }
					set { _CurrentNode = value; }
				}

				private bool _BeforeFirst = true;
				protected bool BeforeFirst
				{
					get { return _BeforeFirst; }
					set { _BeforeFirst = value; }
				}

				private bool _AfterLast = false;
				protected bool AfterLast
				{
					get { return _AfterLast; }
					set { _AfterLast = value; }
				}

				protected BaseNodesEnumerableCollection( NodeTree<T> root )
				{
					_Root = root;
					_CurrentNode = root;

					_Version = _Root.Version;
				}

				~BaseNodesEnumerableCollection()
				{
					Dispose( false );
				}

				protected abstract BaseNodesEnumerableCollection CreateCopy();

				protected virtual bool HasChanged { get { return _Root.HasChanged( _Version ); } }

				// IDisposable
				public void Dispose()
				{
					Dispose( true );

					GC.SuppressFinalize( this );
				}

				protected virtual void Dispose( bool disposing )
				{
				}

				// IEnumerable
				IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }

				// IEnumerable<INode<T>>
				public virtual IEnumerator<INode<T>> GetEnumerator()
				{
					return this;
				}

				// ICollection
				public virtual int Count
				{
					get
					{
						BaseNodesEnumerableCollection e = CreateCopy();

						int i = 0;
						foreach ( INode<T> o in e ) i++;
						return i;
					}
				}

				public virtual bool IsSynchronized { get { return false; } }

				public virtual object SyncRoot { get { return _SyncRoot; } }

				void ICollection.CopyTo( Array array, int index )
				{
					if ( array == null ) throw new ArgumentNullException( "array" );
					if ( array.Rank > 1 ) throw new ArgumentException( "array is multidimensional", "array" );
					if ( index < 0 ) throw new ArgumentOutOfRangeException( "index" );

					int count = Count;

					if ( count > 0 )
						if ( index >= array.Length ) throw new ArgumentException( "index is out of bounds", "index" );

					if ( index + count > array.Length ) throw new ArgumentException( "Not enough space in array", "array" );

					BaseNodesEnumerableCollection e = CreateCopy();

					foreach ( INode<T> n in e )
						array.SetValue( n, index++ );
				}

				public virtual void CopyTo( T[] array, int index )
				{
					( ( ICollection ) this ).CopyTo( array, index );
				}

				// ICollectionEnumerable<INode<T>>
				public virtual bool Contains( INode<T> item )
				{
					BaseNodesEnumerableCollection e = CreateCopy();

					IEqualityComparer<INode<T>> comparer = EqualityComparer<INode<T>>.Default;

					foreach ( INode<T> n in e )
						if ( comparer.Equals( n, item ) )
							return true;

					return false;
				}

				// IEnumerator
				object IEnumerator.Current
				{
					get { return Current; }
				}

				// IEnumerator<INode<T>>
				public virtual void Reset()
				{
					if ( HasChanged ) throw new InvalidOperationException( "Tree has been modified." );

					_CurrentNode = _Root;

					_BeforeFirst = true;
					_AfterLast = false;
				}

				public virtual bool MoveNext()
				{
					if ( HasChanged ) throw new InvalidOperationException( "Tree has been modified." );

					_BeforeFirst = false;

					return true;
				}

				public virtual INode<T> Current
				{
					get
					{
						if ( _BeforeFirst ) throw new InvalidOperationException( "Enumeration has not started." );
						if ( _AfterLast ) throw new InvalidOperationException( "Enumeration has finished." );

						return _CurrentNode;
					}
				}

			}

			// Values
			public virtual IEnumerableCollection<T> Values
			{
				get
				{
					return new ValuesEnumerableCollection( _Root.DataComparer, this.Nodes );
				}
			}

			private class ValuesEnumerableCollection : IEnumerableCollection<T>, IEnumerator<T>
			{
				IEqualityComparer<T> _DataComparer;
				private IEnumerableCollection<INode<T>> _Nodes;
				private IEnumerator<INode<T>> _Enumerator;

				public ValuesEnumerableCollection( IEqualityComparer<T> dataComparer, IEnumerableCollection<INode<T>> nodes )
				{
					_DataComparer = dataComparer;
					_Nodes = nodes;
					_Enumerator = _Nodes.GetEnumerator();
				}

				protected ValuesEnumerableCollection( ValuesEnumerableCollection o )
				{
					_Nodes = o._Nodes;
					_Enumerator = _Nodes.GetEnumerator();
				}

				protected virtual ValuesEnumerableCollection CreateCopy()
				{
					return new ValuesEnumerableCollection( this );
				}

				// IDisposable
				~ValuesEnumerableCollection()
				{
					Dispose( false );
				}

				public void Dispose()
				{
					Dispose( true );

					GC.SuppressFinalize( this );
				}

				protected virtual void Dispose( bool disposing )
				{
				}

				// IEnumerable
				IEnumerator IEnumerable.GetEnumerator()
				{
					return GetEnumerator();
				}

				// IEnumerable<T>
				public virtual IEnumerator<T> GetEnumerator()
				{
					return this;
				}

				// ICollection
				public virtual int Count
				{
					get
					{
						return _Nodes.Count;
					}
				}

				public virtual bool IsSynchronized { get { return false; } }

				public virtual object SyncRoot { get { return _Nodes.SyncRoot; } }

				public virtual void CopyTo( Array array, int index )
				{
					if ( array == null ) throw new ArgumentNullException( "array" );
					if ( array.Rank > 1 ) throw new ArgumentException( "array is multidimensional", "array" );
					if ( index < 0 ) throw new ArgumentOutOfRangeException( "index" );

					int count = Count;

					if ( count > 0 )
						if ( index >= array.Length ) throw new ArgumentException( "index is out of bounds", "index" );

					if ( index + count > array.Length ) throw new ArgumentException( "Not enough space in array", "array" );

					ValuesEnumerableCollection e = CreateCopy();

					foreach ( T n in e )
						array.SetValue( n, index++ );
				}

				// IEnumerableCollection<T>
				public virtual bool Contains( T item )
				{
					ValuesEnumerableCollection e = CreateCopy();

					foreach ( T n in e )
						if ( _DataComparer.Equals( n, item ) )
							return true;

					return false;
				}

				// IEnumerator
				object IEnumerator.Current
				{
					get { return Current; }
				}

				// IEnumerator<T> Members
				public virtual void Reset()
				{
					_Enumerator.Reset();
				}

				public virtual bool MoveNext()
				{
					return _Enumerator.MoveNext();
				}

				public virtual T Current
				{
					get
					{
						if ( _Enumerator == null ) { Debug.Assert( false ); return default( T ); }
						if ( _Enumerator.Current == null ) { Debug.Assert( false ); return default( T ); }

						return _Enumerator.Current.Data;
					}
				}
			}
		}

		//-----------------------------------------------------------------------------
		// AllEnumerator

		public IEnumerableCollectionPair<T> All { get { return new AllEnumerator( this ); } }

		protected class AllEnumerator : BaseEnumerableCollectionPair
		{
			public AllEnumerator( NodeTree<T> root ) : base( root ) { }

			public override IEnumerableCollection<INode<T>> Nodes
			{
				get
				{
					return new NodesEnumerableCollection( Root );
				}
			}

			protected class NodesEnumerableCollection : BaseNodesEnumerableCollection
			{
				private bool _First = true;

				public NodesEnumerableCollection( NodeTree<T> root ) : base( root ) { }

				protected NodesEnumerableCollection( NodesEnumerableCollection o ) : base( o.Root ) { }

				protected override BaseNodesEnumerableCollection CreateCopy()
				{
					return new NodesEnumerableCollection( this );
				}

				public override void Reset()
				{
					base.Reset();

					_First = true;
				}

				public override bool MoveNext()
				{
					if ( !base.MoveNext() ) goto hell;

					if ( CurrentNode == null ) throw new InvalidOperationException( "Current is null" );

					if ( CurrentNode.IsRoot )
					{
						CurrentNode = CurrentNode.Child;
						if ( CurrentNode == null ) goto hell;
					}

					if ( _First ) { _First = false; return true; }

					if ( CurrentNode.Child != null ) { CurrentNode = CurrentNode.Child; return true; }

					for ( ; CurrentNode.Parent != null ; CurrentNode = CurrentNode.Parent )
					{
						if ( CurrentNode == Root ) goto hell;
						if ( CurrentNode.Next != null ) { CurrentNode = CurrentNode.Next; return true; }
					}

				hell:

					AfterLast = true;
					return false;
				}
			}

		}

		//-----------------------------------------------------------------------------
		// AllChildrenEnumerator

		public IEnumerableCollectionPair<T> AllChildren { get { return new AllChildrenEnumerator( this ); } }

		private class AllChildrenEnumerator : BaseEnumerableCollectionPair
		{
			public AllChildrenEnumerator( NodeTree<T> root ) : base( root ) { }

			public override IEnumerableCollection<INode<T>> Nodes
			{
				get
				{
					return new NodesEnumerableCollection( Root );
				}
			}

			protected class NodesEnumerableCollection : BaseNodesEnumerableCollection
			{
				public NodesEnumerableCollection( NodeTree<T> root ) : base( root ) { }

				protected NodesEnumerableCollection( NodesEnumerableCollection o ) : base( o.Root ) { }

				protected override BaseNodesEnumerableCollection CreateCopy()
				{
					return new NodesEnumerableCollection( this );
				}

				public override bool MoveNext()
				{
					if ( !base.MoveNext() ) goto hell;

					if ( CurrentNode == null ) throw new InvalidOperationException( "Current is null" );

					if ( CurrentNode.Child != null ) { CurrentNode = CurrentNode.Child; return true; }

					for ( ; CurrentNode.Parent != null ; CurrentNode = CurrentNode.Parent )
					{
						if ( CurrentNode == Root ) goto hell;
						if ( CurrentNode.Next != null ) { CurrentNode = CurrentNode.Next; return true; }
					}

				hell:

					AfterLast = true;
					return false;
				}
			}
		}

		//-----------------------------------------------------------------------------
		// DirectChildrenEnumerator

		public IEnumerableCollectionPair<T> DirectChildren { get { return new DirectChildrenEnumerator( this ); } }

		private class DirectChildrenEnumerator : BaseEnumerableCollectionPair
		{
			public DirectChildrenEnumerator( NodeTree<T> root ) : base( root ) { }

			public override IEnumerableCollection<INode<T>> Nodes
			{
				get
				{
					return new NodesEnumerableCollection( Root );
				}
			}

			protected class NodesEnumerableCollection : BaseNodesEnumerableCollection
			{
				public NodesEnumerableCollection( NodeTree<T> root ) : base( root ) { }

				protected NodesEnumerableCollection( NodesEnumerableCollection o ) : base( o.Root ) { }

				protected override BaseNodesEnumerableCollection CreateCopy()
				{
					return new NodesEnumerableCollection( this );
				}

				public override int Count
				{
					get
					{
						return Root.DirectChildCount;
					}
				}

				public override bool MoveNext()
				{
					if ( !base.MoveNext() ) goto hell;

					if ( CurrentNode == null ) throw new InvalidOperationException( "Current is null" );

					if ( CurrentNode == Root )
						CurrentNode = Root.Child;
					else
						CurrentNode = CurrentNode.Next;

					if ( CurrentNode != null ) return true;

				hell:

					AfterLast = true;
					return false;
				}
			}
		}

		//-----------------------------------------------------------------------------
		// DirectChildrenInReverseEnumerator

		public IEnumerableCollectionPair<T> DirectChildrenInReverse { get { return new DirectChildrenInReverseEnumerator( this ); } }

		private class DirectChildrenInReverseEnumerator : BaseEnumerableCollectionPair
		{
			public DirectChildrenInReverseEnumerator( NodeTree<T> root ) : base( root ) { }

			public override IEnumerableCollection<INode<T>> Nodes
			{
				get
				{
					return new NodesEnumerableCollection( Root );
				}
			}

			protected class NodesEnumerableCollection : BaseNodesEnumerableCollection
			{
				public NodesEnumerableCollection( NodeTree<T> root ) : base( root ) { }

				protected NodesEnumerableCollection( NodesEnumerableCollection o ) : base( o.Root ) { }

				protected override BaseNodesEnumerableCollection CreateCopy()
				{
					return new NodesEnumerableCollection( this );
				}

				public override int Count
				{
					get
					{
						return Root.DirectChildCount;
					}
				}

				public override bool MoveNext()
				{
					if ( !base.MoveNext() ) goto hell;

					if ( CurrentNode == null ) throw new InvalidOperationException( "Current is null" );

					if ( CurrentNode == Root )
						CurrentNode = Root.LastChild;
					else
						CurrentNode = CurrentNode.Previous;

					if ( CurrentNode != null ) return true;

				hell:

					AfterLast = true;
					return false;
				}
			}
		}

		//-----------------------------------------------------------------------------
		// DirectChildCount

		public int DirectChildCount
		{
			get
			{
				int i = 0;

				for ( INode<T> n = this.Child ; n != null ; n = n.Next ) i++;

				return i;
			}
		}

		//-----------------------------------------------------------------------------
		// ITree<T>

		public virtual Type DataType
		{
			get
			{
				return typeof( T );
			}
		}

		public void Clear()
		{
			if ( !this.IsRoot ) throw new InvalidOperationException( "This is not a Root" );
			if ( !this.IsTree ) throw new InvalidOperationException( "This is not a tree" );

			OnClearing( this );

			_Child = null;

			OnCleared( this );
		}

		//-----------------------------------------------------------------------------
		// GetNodeTree

		protected static NodeTree<T> GetNodeTree( ITree<T> tree )
		{
			if ( tree == null ) throw new ArgumentNullException( "Tree is null" );

			return ( NodeTree<T> ) tree; // can throw an InvalidCastException.
		}

		protected static NodeTree<T> GetNodeTree( INode<T> node )
		{
			if ( node == null ) throw new ArgumentNullException( "Node is null" );

			return ( NodeTree<T> ) node; // can throw an InvalidCastException.
		}

		//-----------------------------------------------------------------------------
		// ICollection

		//		public virtual bool IsSynchronized { get { return false; } } // Not thread safe

		//		public virtual T SyncRoot { get { return this; } } // Not sure about this!

		public virtual int Count
		{
			get
			{
				int i = IsRoot ? 0 : 1;

				for ( INode<T> n = this.Child ; n != null ; n = n.Next )
					i += n.Count;

				return i;
			}
		}

		public virtual bool IsReadOnly { get { return false; } }

		//-----------------------------------------------------------------------------
		// Events

		private EventHandlerList _EventHandlerList;

		protected EventHandlerList EventHandlerList
		{
			get { return _EventHandlerList; }
			//set { _EventHandlerList = value; }
		}

		protected EventHandlerList GetCreateEventHandlerList()
		{
			if ( _EventHandlerList == null ) _EventHandlerList = new EventHandlerList();

			return _EventHandlerList;
		}

		private static readonly object _ValidateEventKey = new object();
		private static readonly object _ClearingEventKey = new object();
		private static readonly object _ClearedEventKey = new object();
		private static readonly object _SettingEventKey = new object();
		private static readonly object _SetDoneEventKey = new object();
		private static readonly object _InsertingEventKey = new object();
		private static readonly object _InsertedEventKey = new object();
		private static readonly object _CuttingEventKey = new object();
		private static readonly object _CutDoneEventKey = new object();
		private static readonly object _CopyingEventKey = new object();
		private static readonly object _CopiedEventKey = new object();
		private static readonly object _DeepCopyingEventKey = new object();
		private static readonly object _DeepCopiedEventKey = new object();

		protected static object ValidateEventKey { get { return _ValidateEventKey; } }
		protected static object ClearingEventKey { get { return _ClearingEventKey; } }
		protected static object ClearedEventKey { get { return _ClearedEventKey; } }
		protected static object SettingEventKey { get { return _SettingEventKey; } }
		protected static object SetDoneEventKey { get { return _SetDoneEventKey; } }
		protected static object InsertingEventKey { get { return _InsertingEventKey; } }
		protected static object InsertedEventKey { get { return _InsertedEventKey; } }
		protected static object CuttingEventKey { get { return _CuttingEventKey; } }
		protected static object CutDoneEventKey { get { return _CutDoneEventKey; } }
		protected static object CopyingEventKey { get { return _CopyingEventKey; } }
		protected static object CopiedEventKey { get { return _CopiedEventKey; } }
		protected static object DeepCopyingEventKey { get { return _DeepCopyingEventKey; } }
		protected static object DeepCopiedEventKey { get { return _DeepCopiedEventKey; } }

		public event EventHandler<NodeTreeDataEventArgs<T>> Validate
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( ValidateEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( ValidateEventKey, value );
			}
		}

		public event EventHandler Clearing
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( ClearingEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( ClearingEventKey, value );
			}
		}

		public event EventHandler Cleared
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( ClearedEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( ClearedEventKey, value );
			}
		}

		public event EventHandler<NodeTreeDataEventArgs<T>> Setting
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( SettingEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( SettingEventKey, value );
			}
		}

		public event EventHandler<NodeTreeDataEventArgs<T>> SetDone
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( SetDoneEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( SetDoneEventKey, value );
			}
		}

		public event EventHandler<NodeTreeInsertEventArgs<T>> Inserting
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( InsertingEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( InsertingEventKey, value );
			}
		}

		public event EventHandler<NodeTreeInsertEventArgs<T>> Inserted
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( InsertedEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( InsertedEventKey, value );
			}
		}

		public event EventHandler Cutting
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( CuttingEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( CuttingEventKey, value );
			}
		}

		public event EventHandler CutDone
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( CutDoneEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( CutDoneEventKey, value );
			}
		}

		public event EventHandler<NodeTreeNodeEventArgs<T>> Copying
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( CopyingEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( CopyingEventKey, value );
			}
		}

		public event EventHandler<NodeTreeNodeEventArgs<T>> Copied
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( CopiedEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( CopiedEventKey, value );
			}
		}

		public event EventHandler<NodeTreeNodeEventArgs<T>> DeepCopying
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( DeepCopyingEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( DeepCopyingEventKey, value );
			}
		}

		public event EventHandler<NodeTreeNodeEventArgs<T>> DeepCopied
		{
			add
			{
				GetCreateEventHandlerList().AddHandler( DeepCopiedEventKey, value );
			}

			remove
			{
				GetCreateEventHandlerList().RemoveHandler( DeepCopiedEventKey, value );
			}
		}


		//-----------------------------------------------------------------------------
		// Validate

		protected virtual void OnValidate( INode<T> node, T data )
		{
			if ( !Root.IsTree ) throw new InvalidOperationException( "This is not a tree" );
			if ( data is INode<T> ) throw new ArgumentException( "Object is a node" );

			if ( ( !typeof( T ).IsClass ) || ( ( object ) data ) != null )
				if ( !DataType.IsInstanceOfType( data ) )
					throw new ArgumentException( "Object is not a " + DataType.Name );

			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeDataEventArgs<T>> e = ( EventHandler<NodeTreeDataEventArgs<T>> ) _EventHandlerList[ ValidateEventKey ];
				if ( e != null ) e( node, new NodeTreeDataEventArgs<T>( data ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnValidate( node, data );
		}

		//-----------------------------------------------------------------------------
		// Clear

		protected virtual void OnClearing( ITree<T> tree )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler e = ( EventHandler ) _EventHandlerList[ ClearingEventKey ];
				if ( e != null ) e( tree, EventArgs.Empty );
			}
		}

		protected virtual void OnCleared( ITree<T> tree )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler e = ( EventHandler ) _EventHandlerList[ ClearedEventKey ];
				if ( e != null ) e( tree, EventArgs.Empty );
			}
		}

		//-----------------------------------------------------------------------------
		// Set

		protected virtual void OnSetting( INode<T> node, T data )
		{
			OnSettingCore( node, data, true );
		}

		protected virtual void OnSettingCore( INode<T> node, T data, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeDataEventArgs<T>> e = ( EventHandler<NodeTreeDataEventArgs<T>> ) _EventHandlerList[ SettingEventKey ];
				if ( e != null ) e( node, new NodeTreeDataEventArgs<T>( data ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnSettingCore( node, data, false );

			if ( raiseValidate ) OnValidate( node, data );
		}

		protected virtual void OnSetDone( INode<T> node, T data )
		{
			OnSetDoneCore( node, data, true );
		}

		protected virtual void OnSetDoneCore( INode<T> node, T data, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeDataEventArgs<T>> e = ( EventHandler<NodeTreeDataEventArgs<T>> ) _EventHandlerList[ SetDoneEventKey ];
				if ( e != null ) e( node, new NodeTreeDataEventArgs<T>( data ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnSetDoneCore( node, data, false );

			//			if ( raiseValidate ) OnValidate( Node, Data );
		}

		//-----------------------------------------------------------------------------
		// Insert

		protected virtual void OnInserting( INode<T> oldNode, NodeTreeInsertOperation operation, INode<T> newNode )
		{
			OnInsertingCore( oldNode, operation, newNode, true );
		}

		protected virtual void OnInsertingCore( INode<T> oldNode, NodeTreeInsertOperation operation, INode<T> newNode, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeInsertEventArgs<T>> e = ( EventHandler<NodeTreeInsertEventArgs<T>> ) _EventHandlerList[ InsertingEventKey ];
				if ( e != null ) e( oldNode, new NodeTreeInsertEventArgs<T>( operation, newNode ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnInsertingCore( oldNode, operation, newNode, false );

			if ( raiseValidate ) OnValidate( oldNode, newNode.Data );

			if ( raiseValidate ) OnInsertingTree( newNode );
		}

		protected virtual void OnInsertingTree( INode<T> newNode )
		{
			for ( INode<T> child = newNode.Child ; child != null ; child = child.Next )
			{
				OnInsertingTree( newNode, child );

				OnInsertingTree( child );
			}
		}

		protected virtual void OnInsertingTree( INode<T> newNode, INode<T> child )
		{
			OnInsertingTreeCore( newNode, child, true );
		}

		protected virtual void OnInsertingTreeCore( INode<T> newNode, INode<T> child, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeInsertEventArgs<T>> e = ( EventHandler<NodeTreeInsertEventArgs<T>> ) _EventHandlerList[ InsertingEventKey ];
				if ( e != null ) e( newNode, new NodeTreeInsertEventArgs<T>( NodeTreeInsertOperation.Tree, child ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnInsertingTreeCore( newNode, child, false );

			if ( raiseValidate ) OnValidate( newNode, child.Data );
		}

		protected virtual void OnInserted( INode<T> oldNode, NodeTreeInsertOperation operation, INode<T> newNode )
		{
			OnInsertedCore( oldNode, operation, newNode, true );
		}

		protected virtual void OnInsertedCore( INode<T> oldNode, NodeTreeInsertOperation operation, INode<T> newNode, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeInsertEventArgs<T>> e = ( EventHandler<NodeTreeInsertEventArgs<T>> ) _EventHandlerList[ InsertedEventKey ];
				if ( e != null ) e( oldNode, new NodeTreeInsertEventArgs<T>( operation, newNode ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnInsertedCore( oldNode, operation, newNode, false );

			//			if ( raiseValidate ) OnValidate( OldNode, NewNode.Data );

			if ( raiseValidate ) OnInsertedTree( newNode );
		}

		protected virtual void OnInsertedTree( INode<T> newNode )
		{
			for ( INode<T> child = newNode.Child ; child != null ; child = child.Next )
			{
				OnInsertedTree( newNode, child );

				OnInsertedTree( child );
			}
		}

		protected virtual void OnInsertedTree( INode<T> newNode, INode<T> child )
		{
			OnInsertedTreeCore( newNode, child, true );
		}

		protected virtual void OnInsertedTreeCore( INode<T> newNode, INode<T> child, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeInsertEventArgs<T>> e = ( EventHandler<NodeTreeInsertEventArgs<T>> ) _EventHandlerList[ InsertedEventKey ];
				if ( e != null ) e( newNode, new NodeTreeInsertEventArgs<T>( NodeTreeInsertOperation.Tree, child ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnInsertedTreeCore( newNode, child, false );

			//			if ( raiseValidate ) OnValidate( newNode, child.Data );
		}

		//-----------------------------------------------------------------------------
		// Cut

		protected virtual void OnCutting( INode<T> oldNode )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler e = ( EventHandler ) _EventHandlerList[ CuttingEventKey ];
				if ( e != null ) e( oldNode, EventArgs.Empty );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnCutting( oldNode );
		}

		protected virtual void OnCutDone( INode<T> oldRoot, INode<T> oldNode )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler e = ( EventHandler ) _EventHandlerList[ CutDoneEventKey ];
				if ( e != null ) e( oldNode, EventArgs.Empty );
			}

			if ( !IsTree ) GetNodeTree( oldRoot ).OnCutDone( oldRoot, oldNode );
		}

		//-----------------------------------------------------------------------------
		// Copy

		protected virtual void OnCopying( INode<T> oldNode, INode<T> newNode )
		{
			OnCopyingCore( oldNode, newNode, true );
		}

		protected virtual void OnCopyingCore( INode<T> oldNode, INode<T> newNode, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeNodeEventArgs<T>> e = ( EventHandler<NodeTreeNodeEventArgs<T>> ) _EventHandlerList[ CopyingEventKey ];
				if ( e != null ) e( oldNode, new NodeTreeNodeEventArgs<T>( newNode ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnCopyingCore( oldNode, newNode, false );

			//			if ( raiseValidate ) OnValidate( oldNode, newNode.Data );
		}

		protected virtual void OnCopied( INode<T> oldNode, INode<T> newNode )
		{
			OnCopiedCore( oldNode, newNode, true );
		}

		protected virtual void OnCopiedCore( INode<T> oldNode, INode<T> newNode, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeNodeEventArgs<T>> e = ( EventHandler<NodeTreeNodeEventArgs<T>> ) _EventHandlerList[ CopiedEventKey ];
				if ( e != null ) e( oldNode, new NodeTreeNodeEventArgs<T>( newNode ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnCopiedCore( oldNode, newNode, false );

			//			if ( raiseValidate ) OnValidate( oldNode, newNode.Data );
		}

		//-----------------------------------------------------------------------------
		// DeepCopy

		protected virtual void OnDeepCopying( INode<T> oldNode, INode<T> newNode )
		{
			OnDeepCopyingCore( oldNode, newNode, true );
		}

		protected virtual void OnDeepCopyingCore( INode<T> oldNode, INode<T> newNode, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeNodeEventArgs<T>> e = ( EventHandler<NodeTreeNodeEventArgs<T>> ) _EventHandlerList[ DeepCopyingEventKey ];
				if ( e != null ) e( oldNode, new NodeTreeNodeEventArgs<T>( newNode ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnDeepCopyingCore( oldNode, newNode, false );

			//			if ( raiseValidate ) OnValidate( oldNode, newNode.Data );
		}

		protected virtual void OnDeepCopied( INode<T> oldNode, INode<T> newNode )
		{
			OnDeepCopiedCore( oldNode, newNode, true );
		}

		protected virtual void OnDeepCopiedCore( INode<T> oldNode, INode<T> newNode, bool raiseValidate )
		{
			if ( _EventHandlerList != null )
			{
				EventHandler<NodeTreeNodeEventArgs<T>> e = ( EventHandler<NodeTreeNodeEventArgs<T>> ) _EventHandlerList[ DeepCopiedEventKey ];
				if ( e != null ) e( oldNode, new NodeTreeNodeEventArgs<T>( newNode ) );
			}

			if ( !IsRoot ) GetNodeTree( Root ).OnDeepCopiedCore( oldNode, newNode, false );

			//			if ( raiseValidate ) OnValidate( oldNode, newNode.Data );
		}

		//-----------------------------------------------------------------------------

	} // class NodeTree

	//-----------------------------------------------------------------------------

}



By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
I discovered C# and .NET 1.0 Beta 1 in late 2000 and loved them immediately.
I have been writing software professionally in C# ever since

In real life, I have spent 3 years travelling abroad,
I have held a UK Private Pilots Licence for 20 years,
and I am a PADI Divemaster.

I now live near idyllic Bournemouth in England.

I can work 'virtually' anywhere!

Comments and Discussions