moel@345: using System;
moel@345: using System.Collections.Generic;
moel@345: using System.Collections.ObjectModel;
moel@345: using System.Runtime.Serialization;
moel@345: using System.Security.Permissions;
moel@345: 
moel@345: namespace Aga.Controls.Tree
moel@345: {
moel@345: 	[Serializable]
moel@345: 	public sealed class TreeNodeAdv : ISerializable
moel@345: 	{
moel@345: 		#region NodeCollection
moel@345: 		private class NodeCollection : Collection<TreeNodeAdv>
moel@345: 		{
moel@345: 			private TreeNodeAdv _owner;
moel@345: 
moel@345: 			public NodeCollection(TreeNodeAdv owner)
moel@345: 			{
moel@345: 				_owner = owner;
moel@345: 			}
moel@345: 
moel@345: 			protected override void ClearItems()
moel@345: 			{
moel@345: 				while (this.Count != 0)
moel@345: 					this.RemoveAt(this.Count - 1);
moel@345: 			}
moel@345: 
moel@345: 			protected override void InsertItem(int index, TreeNodeAdv item)
moel@345: 			{
moel@345: 				if (item == null)
moel@345: 					throw new ArgumentNullException("item");
moel@345: 
moel@345: 				if (item.Parent != _owner)
moel@345: 				{
moel@345: 					if (item.Parent != null)
moel@345: 						item.Parent.Nodes.Remove(item);
moel@345: 					item._parent = _owner;
moel@345: 					item._index = index;
moel@345: 					for (int i = index; i < Count; i++)
moel@345: 						this[i]._index++;
moel@345: 					base.InsertItem(index, item);
moel@345: 				}
moel@345: 
moel@345: 				if (_owner.Tree != null && _owner.Tree.Model == null)
moel@345: 				{
moel@345: 					_owner.Tree.SmartFullUpdate();
moel@345: 				}
moel@345: 			}
moel@345: 
moel@345: 			protected override void RemoveItem(int index)
moel@345: 			{
moel@345: 				TreeNodeAdv item = this[index];
moel@345: 				item._parent = null;
moel@345: 				item._index = -1;
moel@345: 				for (int i = index + 1; i < Count; i++)
moel@345: 					this[i]._index--;
moel@345: 				base.RemoveItem(index);
moel@345: 
moel@345: 				if (_owner.Tree != null && _owner.Tree.Model == null)
moel@345: 				{
moel@345: 					_owner.Tree.UpdateSelection();
moel@345: 					_owner.Tree.SmartFullUpdate();
moel@345: 				}
moel@345: 			}
moel@345: 
moel@345: 			protected override void SetItem(int index, TreeNodeAdv item)
moel@345: 			{
moel@345: 				if (item == null)
moel@345: 					throw new ArgumentNullException("item");
moel@345: 				RemoveAt(index);
moel@345: 				InsertItem(index, item);
moel@345: 			}
moel@345: 		}
moel@345: 		#endregion
moel@345: 
moel@345: 		#region Events
moel@345: 
moel@345: 		public event EventHandler<TreeViewAdvEventArgs> Collapsing;
moel@345: 		internal void OnCollapsing()
moel@345: 		{
moel@345: 			if (Collapsing != null)
moel@345: 				Collapsing(this, new TreeViewAdvEventArgs(this));
moel@345: 		}
moel@345: 
moel@345: 		public event EventHandler<TreeViewAdvEventArgs> Collapsed;
moel@345: 		internal void OnCollapsed()
moel@345: 		{
moel@345: 			if (Collapsed != null)
moel@345: 				Collapsed(this, new TreeViewAdvEventArgs(this));
moel@345: 		}
moel@345: 
moel@345: 		public event EventHandler<TreeViewAdvEventArgs> Expanding;
moel@345: 		internal void OnExpanding()
moel@345: 		{
moel@345: 			if (Expanding != null)
moel@345: 				Expanding(this, new TreeViewAdvEventArgs(this));
moel@345: 		}
moel@345: 
moel@345: 		public event EventHandler<TreeViewAdvEventArgs> Expanded;
moel@345: 		internal void OnExpanded()
moel@345: 		{
moel@345: 			if (Expanded != null)
moel@345: 				Expanded(this, new TreeViewAdvEventArgs(this));
moel@345: 		}
moel@345: 
moel@345: 		#endregion
moel@345: 
moel@345: 		#region Properties
moel@345: 
moel@345: 		private TreeViewAdv _tree;
moel@345: 		public TreeViewAdv Tree
moel@345: 		{
moel@345: 			get { return _tree; }
moel@345: 		}
moel@345: 
moel@345: 		private int _row;
moel@345: 		public int Row
moel@345: 		{
moel@345: 			get { return _row; }
moel@345: 			internal set { _row = value; }
moel@345: 		}
moel@345: 
moel@345: 		private int _index = -1;
moel@345: 		public int Index
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				return _index;
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		private bool _isSelected;
moel@345: 		public bool IsSelected
moel@345: 		{
moel@345: 			get { return _isSelected; }
moel@345: 			set
moel@345: 			{
moel@345: 				if (_isSelected != value)
moel@345: 				{
moel@345: 					if (Tree.IsMyNode(this))
moel@345: 					{
moel@345: 						//_tree.OnSelectionChanging
moel@345: 						if (value)
moel@345: 						{
moel@345: 							if (!_tree.Selection.Contains(this))
moel@345: 								_tree.Selection.Add(this);
moel@345: 
moel@345: 							if (_tree.Selection.Count == 1)
moel@345: 								_tree.CurrentNode = this;
moel@345: 						}
moel@345: 						else
moel@345: 							_tree.Selection.Remove(this);
moel@345: 						_tree.UpdateView();
moel@345: 						_tree.OnSelectionChanged();
moel@345: 					}
moel@345: 					_isSelected = value;
moel@345: 				}
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		/// <summary>
moel@345: 		/// Returns true if all parent nodes of this node are expanded.
moel@345: 		/// </summary>
moel@345: 		internal bool IsVisible
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				TreeNodeAdv node = _parent;
moel@345: 				while (node != null)
moel@345: 				{
moel@345: 					if (!node.IsExpanded)
moel@345: 						return false;
moel@345: 					node = node.Parent;
moel@345: 				}
moel@345: 				return true;
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		private bool _isLeaf;
moel@345: 		public bool IsLeaf
moel@345: 		{
moel@345: 			get { return _isLeaf; }
moel@345: 			internal set { _isLeaf = value; }
moel@345: 		}
moel@345: 
moel@345: 		private bool _isExpandedOnce;
moel@345: 		public bool IsExpandedOnce
moel@345: 		{
moel@345: 			get { return _isExpandedOnce; }
moel@345: 			internal set { _isExpandedOnce = value; }
moel@345: 		}
moel@345: 
moel@345: 		private bool _isExpanded;
moel@345: 		public bool IsExpanded
moel@345: 		{
moel@345: 			get { return _isExpanded; }
moel@345: 			set
moel@345: 			{
moel@345: 				if (value)
moel@345: 					Expand();
moel@345: 				else
moel@345: 					Collapse();
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		internal void AssignIsExpanded(bool value)
moel@345: 		{
moel@345: 			_isExpanded = value;
moel@345: 		}
moel@345: 
moel@345: 		private TreeNodeAdv _parent;
moel@345: 		public TreeNodeAdv Parent
moel@345: 		{
moel@345: 			get { return _parent; }
moel@345: 		}
moel@345: 
moel@345: 		public int Level
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				if (_parent == null)
moel@345: 					return 0;
moel@345: 				else
moel@345: 					return _parent.Level + 1;
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		public TreeNodeAdv PreviousNode
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				if (_parent != null)
moel@345: 				{
moel@345: 					int index = Index;
moel@345: 					if (index > 0)
moel@345: 						return _parent.Nodes[index - 1];
moel@345: 				}
moel@345: 				return null;
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		public TreeNodeAdv NextNode
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				if (_parent != null)
moel@345: 				{
moel@345: 					int index = Index;
moel@345: 					if (index < _parent.Nodes.Count - 1)
moel@345: 						return _parent.Nodes[index + 1];
moel@345: 				}
moel@345: 				return null;
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		internal TreeNodeAdv BottomNode
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				TreeNodeAdv parent = this.Parent;
moel@345: 				if (parent != null)
moel@345: 				{
moel@345: 					if (parent.NextNode != null)
moel@345: 						return parent.NextNode;
moel@345: 					else
moel@345: 						return parent.BottomNode;
moel@345: 				}
moel@345: 				return null;
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		internal TreeNodeAdv NextVisibleNode
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				if (IsExpanded && Nodes.Count > 0)
moel@345: 					return Nodes[0];
moel@345: 				else
moel@345: 				{
moel@345: 					TreeNodeAdv nn = NextNode;
moel@345: 					if (nn != null)
moel@345: 						return nn;
moel@345: 					else
moel@345: 						return BottomNode;
moel@345: 				}
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		public bool CanExpand
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				return (Nodes.Count > 0 || (!IsExpandedOnce && !IsLeaf));
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		private object _tag;
moel@345: 		public object Tag
moel@345: 		{
moel@345: 			get { return _tag; }
moel@345: 		}
moel@345: 
moel@345: 		private Collection<TreeNodeAdv> _nodes;
moel@345: 		internal Collection<TreeNodeAdv> Nodes
moel@345: 		{
moel@345: 			get { return _nodes; }
moel@345: 		}
moel@345: 
moel@345: 		private ReadOnlyCollection<TreeNodeAdv> _children;
moel@345: 		public ReadOnlyCollection<TreeNodeAdv> Children
moel@345: 		{
moel@345: 			get
moel@345: 			{
moel@345: 				return _children;
moel@345: 			}
moel@345: 		}
moel@345: 
moel@345: 		private int? _rightBounds;
moel@345: 		internal int? RightBounds
moel@345: 		{
moel@345: 			get { return _rightBounds; }
moel@345: 			set { _rightBounds = value; }
moel@345: 		}
moel@345: 
moel@345: 		private int? _height;
moel@345: 		internal int? Height
moel@345: 		{
moel@345: 			get { return _height; }
moel@345: 			set { _height = value; }
moel@345: 		}
moel@345: 
moel@345: 		private bool _isExpandingNow;
moel@345: 		internal bool IsExpandingNow
moel@345: 		{
moel@345: 			get { return _isExpandingNow; }
moel@345: 			set { _isExpandingNow = value; }
moel@345: 		}
moel@345: 
moel@346: 		private bool _autoExpandOnStructureChanged = true;
moel@345: 		public bool AutoExpandOnStructureChanged
moel@345: 		{
moel@345: 			get { return _autoExpandOnStructureChanged; }
moel@345: 			set { _autoExpandOnStructureChanged = value; }
moel@345: 		}
moel@345: 
moel@345: 		#endregion
moel@345: 
moel@345: 		public TreeNodeAdv(object tag)
moel@345: 			: this(null, tag)
moel@345: 		{
moel@345: 		}
moel@345: 
moel@345: 		internal TreeNodeAdv(TreeViewAdv tree, object tag)
moel@345: 		{
moel@345: 			_row = -1;
moel@345: 			_tree = tree;
moel@345: 			_nodes = new NodeCollection(this);
moel@345: 			_children = new ReadOnlyCollection<TreeNodeAdv>(_nodes);
moel@345: 			_tag = tag;
moel@345: 		}
moel@345: 
moel@345: 		public override string ToString()
moel@345: 		{
moel@345: 			if (Tag != null)
moel@345: 				return Tag.ToString();
moel@345: 			else
moel@345: 				return base.ToString();
moel@345: 		}
moel@345: 
moel@345: 		public void Collapse()
moel@345: 		{
moel@345: 			if (_isExpanded)
moel@345: 				Collapse(true);
moel@345: 		}
moel@345: 
moel@345: 		public void CollapseAll()
moel@345: 		{
moel@345: 			Collapse(false);
moel@345: 		}
moel@345: 
moel@345: 		public void Collapse(bool ignoreChildren)
moel@345: 		{
moel@345: 			SetIsExpanded(false, ignoreChildren);
moel@345: 		}
moel@345: 
moel@345: 		public void Expand()
moel@345: 		{
moel@345: 			if (!_isExpanded)
moel@345: 				Expand(true);
moel@345: 		}
moel@345: 
moel@345: 		public void ExpandAll()
moel@345: 		{
moel@345: 			Expand(false);
moel@345: 		}
moel@345: 
moel@345: 		public void Expand(bool ignoreChildren)
moel@345: 		{
moel@345: 			SetIsExpanded(true, ignoreChildren);
moel@345: 		}
moel@345: 
moel@345: 		private void SetIsExpanded(bool value, bool ignoreChildren)
moel@345: 		{
moel@345: 			if (Tree == null)
moel@345: 				_isExpanded = value;
moel@345: 			else
moel@345: 				Tree.SetIsExpanded(this, value, ignoreChildren);
moel@345: 		}
moel@345: 
moel@345: 		#region ISerializable Members
moel@345: 
moel@345: 		private TreeNodeAdv(SerializationInfo info, StreamingContext context)
moel@345: 			: this(null, null)
moel@345: 		{
moel@345: 			int nodesCount = 0;
moel@345: 			nodesCount = info.GetInt32("NodesCount");
moel@345: 			_isExpanded = info.GetBoolean("IsExpanded");
moel@345: 			_tag = info.GetValue("Tag", typeof(object));
moel@345: 
moel@345: 			for (int i = 0; i < nodesCount; i++)
moel@345: 			{
moel@345: 				TreeNodeAdv child = (TreeNodeAdv)info.GetValue("Child" + i, typeof(TreeNodeAdv));
moel@345: 				Nodes.Add(child);
moel@345: 			}
moel@345: 
moel@345: 		}
moel@345: 
moel@345: 		[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
moel@345: 		public void GetObjectData(SerializationInfo info, StreamingContext context)
moel@345: 		{
moel@345: 			info.AddValue("IsExpanded", IsExpanded);
moel@345: 			info.AddValue("NodesCount", Nodes.Count);
moel@345: 			if ((Tag != null) && Tag.GetType().IsSerializable)
moel@345: 				info.AddValue("Tag", Tag, Tag.GetType());
moel@345: 
moel@345: 			for (int i = 0; i < Nodes.Count; i++)
moel@345: 				info.AddValue("Child" + i, Nodes[i], typeof(TreeNodeAdv));
moel@345: 
moel@345: 		}
moel@345: 
moel@345: 		#endregion
moel@345: 	}
moel@345: }