diff options
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeNode.cs')
-rw-r--r-- | mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeNode.cs | 686 |
1 files changed, 686 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeNode.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeNode.cs new file mode 100644 index 00000000000..c8aa8493f92 --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeNode.cs @@ -0,0 +1,686 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2004-2005 Novell, Inc. +// +// Authors: +// Jackson Harper (jackson@ximian.com) +// Kazuki Oikawa (kazuki@panicode.com) + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Runtime.Serialization; +using System.Text; + +namespace System.Windows.Forms { + [TypeConverter(typeof(TreeNodeConverter))] + [Serializable] + public class TreeNode : MarshalByRefObject, ICloneable, ISerializable { + #region Fields + private TreeView tree_view; + internal TreeNode parent; + + private string text; + private int image_index = -1; + private int selected_image_index = -1; + internal TreeNodeCollection nodes; + internal TreeViewAction check_reason = TreeViewAction.Unknown; + + private bool is_expanded = false; + private Rectangle bounds = Rectangle.Empty; + private bool check; + private bool is_editing; + internal OwnerDrawPropertyBag prop_bag; + + private object tag; + + internal IntPtr handle; + + #endregion // Fields + + #region Internal Constructors + internal TreeNode (TreeView tree_view) : this () + { + this.tree_view = tree_view; + is_expanded = true; + } + + private TreeNode (SerializationInfo info, StreamingContext context) : this () + { + Text = (string) info.GetValue ("Text", typeof (string)); + prop_bag = (OwnerDrawPropertyBag) info.GetValue ("prop_bag", typeof (OwnerDrawPropertyBag)); + image_index = (int) info.GetValue ("ImageIndex", typeof (int)); + selected_image_index = (int) info.GetValue ("SelectedImageIndex", typeof (int)); + tag = info.GetValue ("Tag", typeof (object)); + check = (bool) info.GetValue ("Checked", typeof (bool)); + + int count = (int) info.GetValue ("NumberOfChildren", typeof (int)); + for (int i = 0; i < count; i++) { + TreeNode node = (TreeNode) info.GetValue ("Child-" + i, typeof (TreeNode)); + Nodes.Add (node); + } + } + + #endregion // Internal Constructors + + #region Public Constructors + public TreeNode () + { + nodes = new TreeNodeCollection (this); + } + + public TreeNode (string text) : this () + { + Text = text; + } + + public TreeNode (string text, TreeNode [] children) : this (text) + { + Nodes.AddRange (children); + } + + public TreeNode (string text, int image_index, int selected_image_index) : this (text) + { + this.image_index = image_index; + this.selected_image_index = selected_image_index; + } + + public TreeNode (string text, int image_index, int selected_image_index, + TreeNode [] children) : this (text, image_index, selected_image_index) + { + Nodes.AddRange (children); + } + + #endregion // Public Constructors + + #region ICloneable Members + public virtual object Clone() + { + TreeNode tn = new TreeNode (text, image_index, selected_image_index); + if (nodes != null) { + foreach (TreeNode child in nodes) + tn.Nodes.Add ((TreeNode)child.Clone ()); + } + tn.Tag = tag; + tn.Checked = Checked; + if (prop_bag != null) + tn.prop_bag = OwnerDrawPropertyBag.Copy (prop_bag); + return tn; + } + + #endregion // ICloneable Members + + #region ISerializable Members + void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) + { + info.AddValue ("Text", Text); + info.AddValue ("prop_bag", prop_bag, typeof (OwnerDrawPropertyBag)); + info.AddValue ("ImageIndex", ImageIndex); + info.AddValue ("SelectedImageIndex", SelectedImageIndex); + info.AddValue ("Tag", Tag); + info.AddValue ("Checked", Checked); + + info.AddValue ("NumberOfChildren", Nodes.Count); + for (int i = 0; i < Nodes.Count; i++) + info.AddValue ("Child-" + i, Nodes [i], typeof (TreeNode)); + } + #endregion // ISerializable Members + + #region Public Instance Properties + public Color BackColor { + get { + if (prop_bag != null) + return prop_bag.BackColor; + if (TreeView != null) + return TreeView.BackColor; + return Color.Empty; + } + set { + if (prop_bag == null) + prop_bag = new OwnerDrawPropertyBag (); + prop_bag.BackColor = value; + + TreeView tree_view = TreeView; + if (tree_view != null) + tree_view.UpdateNode (this); + } + } + + public Rectangle Bounds { + get { return bounds; } + } + + public bool Checked { + get { return check; } + set { + if (check == value) + return; + TreeViewCancelEventArgs args = new TreeViewCancelEventArgs (this, false, check_reason); + if (TreeView != null) + TreeView.OnBeforeCheck (args); + if (!args.Cancel) { + check = value; + if (TreeView != null) { + TreeView.OnAfterCheck (new TreeViewEventArgs (this, check_reason)); + TreeView.UpdateNode (this); + } + } + check_reason = TreeViewAction.Unknown; + } + } + + public TreeNode FirstNode { + get { + if (nodes.Count > 0) + return nodes [0]; + return null; + } + } + + public Color ForeColor { + get { + if (prop_bag != null) + return prop_bag.ForeColor; + if (TreeView != null) + return TreeView.ForeColor; + return Color.Empty; + } + set { + if (prop_bag == null) + prop_bag = new OwnerDrawPropertyBag (); + prop_bag.ForeColor = value; + + TreeView tree_view = TreeView; + if (tree_view != null) + tree_view.UpdateNode (this); + } + } + + public string FullPath { + get { + if (TreeView == null) + throw new Exception ("No TreeView associated"); + + StringBuilder builder = new StringBuilder (); + BuildFullPath (builder); + return builder.ToString (); + } + } + + [Localizable(true)] + public int ImageIndex { + get { return image_index; } + set { + if (image_index == value) + return; + image_index = value; + TreeView tree = TreeView; + if (tree != null) + tree.UpdateNode (this); + } + } + + public bool IsEditing { + get { return is_editing; } + } + + public bool IsExpanded { + get { return is_expanded; } + } + + public bool IsSelected { + get { + if (TreeView == null) + return false; + return TreeView.SelectedNode == this; + } + } + + public bool IsVisible { + get { + if (TreeView == null) + return false; + + if (bounds.Y < 0 && bounds.Y > TreeView.ClientRectangle.Height) + return false; + + TreeNode parent = Parent; + while (parent != null) { + if (!parent.IsExpanded) + return false; + parent = parent.Parent; + } + return true; + } + } + + public TreeNode LastNode { + get { + return (nodes == null || nodes.Count == 0) ? null : nodes [nodes.Count - 1]; + } + } + + public TreeNode NextNode { + get { + if (parent == null) + return null; + int index = Index; + if (parent.Nodes.Count > index + 1) + return parent.Nodes [index + 1]; + return null; + } + } + + public TreeNode NextVisibleNode { + get { + OpenTreeNodeEnumerator o = new OpenTreeNodeEnumerator (this); + if (!o.MoveNext ()) + return null; + TreeNode c = (TreeNode) o.Current; + if (!c.IsInClippingRect) + return null; + return c; + } + } + + [Localizable(true)] + public Font NodeFont { + get { + if (prop_bag != null) + return prop_bag.Font; + if (TreeView != null) + return TreeView.Font; + return null; + } + set { + if (prop_bag == null) + prop_bag = new OwnerDrawPropertyBag (); + prop_bag.Font = value; + InvalidateWidth (); + } + } + + [ListBindable(false)] + public TreeNodeCollection Nodes { + get { + if (nodes == null) + nodes = new TreeNodeCollection (this); + return nodes; + } + } + + public TreeNode Parent { + get { + TreeView tree_view = TreeView; + if (tree_view != null && tree_view.root_node == parent) + return null; + return parent; + } + } + + public TreeNode PrevNode { + get { + if (parent == null) + return null; + int index = Index; + if (index <= 0 || index > parent.Nodes.Count) + return null; + return parent.Nodes [index - 1]; + } + } + + public TreeNode PrevVisibleNode { + get { + OpenTreeNodeEnumerator o = new OpenTreeNodeEnumerator (this); + if (!o.MovePrevious ()) + return null; + TreeNode c = (TreeNode) o.Current; + if (!c.IsInClippingRect) + return null; + return c; + } + } + + [Localizable(true)] + public int SelectedImageIndex { + get { return selected_image_index; } + set { selected_image_index = value; } + } + + [Bindable(true)] + [Localizable(false)] + [TypeConverter(typeof(System.ComponentModel.StringConverter))] + [DefaultValue(null)] + public object Tag { + get { return tag; } + set { tag = value; } + } + + [Localizable(true)] + public string Text { + get { + if (text == null) + return String.Empty; + return text; + } + set { + if (text == value) + return; + text = value; + bounds.Width = 0; + } + } + + public TreeView TreeView { + get { + if (tree_view != null) + return tree_view; + TreeNode walk = parent; + while (walk != null) { + if (walk.TreeView != null) + break; + walk = walk.parent; + } + if (walk == null) + return null; + return walk.TreeView; + } + } + + public IntPtr Handle { + get { + // MS throws a NullReferenceException if the TreeView isn't set... + if (handle == IntPtr.Zero && TreeView != null) + handle = TreeView.CreateNodeHandle (); + return handle; + } + } + + #endregion // Public Instance Properties + + + public static TreeNode FromHandle (TreeView tree, IntPtr handle) + { + if (handle == IntPtr.Zero) + return null; + // No arg checking on MS it just throws a NullRef if treeview is null + return tree.NodeFromHandle (handle); + } + + #region Public Instance Methods + public void BeginEdit () { + is_editing = true; + } + + public void Collapse () { + Collapse(false); + } + + public void EndEdit (bool cancel) { + is_editing = false; + if (!cancel && TreeView != null) + Text = TreeView.LabelEditText; + } + + public void Expand () { + Expand(false); + } + + public void ExpandAll () { + ExpandRecursive (this); + if(TreeView != null) + TreeView.UpdateNode (TreeView.root_node); + } + + public void EnsureVisible () + { + if (TreeView == null) + return; + + if (this.Parent != null) + ExpandParentRecursive (this.Parent); + + if (bounds.Y < 0) { + TreeView.SetTop (this); + } else if (bounds.Bottom > TreeView.ViewportRectangle.Bottom) { + TreeView.SetBottom (this); + } + } + + public int GetNodeCount (bool include_subtrees) { + if (!include_subtrees) + return Nodes.Count; + + int count = 0; + GetNodeCountRecursive (this, ref count); + + return count; + } + + public void Remove () { + if (parent == null) + return; + int index = Index; + parent.Nodes.RemoveAt (index); + } + + public void Toggle () { + if (is_expanded) + Collapse (); + else + Expand (); + } + + public override String ToString () { + return String.Concat ("TreeNode: ", Text); + } + + #endregion // Public Instance Methods + + #region Internal & Private Methods and Properties + + internal bool IsRoot { + get { + TreeView tree_view = TreeView; + if (tree_view == null) + return false; + if (tree_view.root_node == this) + return true; + return false; + } + } + + bool BuildFullPath (StringBuilder path) + { + if (parent == null) + return false; + + if (parent.BuildFullPath (path)) + path.Append (TreeView.PathSeparator); + + path.Append (text); + return true; + } + + public int Index { + get { + if (parent == null) + return 0; + return parent.Nodes.IndexOf (this); + } + } + + private void Expand (bool byInternal) + { + if (is_expanded) + return; + bool cancel = false; + if (TreeView != null) { + TreeViewCancelEventArgs e = new TreeViewCancelEventArgs (this, false, TreeViewAction.Expand); + TreeView.OnBeforeExpand (e); + cancel = e.Cancel; + } + + if (!cancel) { + is_expanded = true; + if (TreeView != null) + TreeView.OnAfterExpand (new TreeViewEventArgs (this)); + if (IsVisible && TreeView != null) + TreeView.UpdateBelow (this); + } + } + + private void Collapse (bool byInternal) + { + if (!is_expanded) + return; + + if (IsRoot) + return; + + bool cancel = false; + if (TreeView != null) { + TreeViewCancelEventArgs e = new TreeViewCancelEventArgs (this, false, TreeViewAction.Collapse); + TreeView.OnBeforeCollapse (e); + cancel = e.Cancel; + } + + if (!cancel) { + is_expanded = false; + if (TreeView != null) + TreeView.OnAfterCollapse (new TreeViewEventArgs (this)); + if (IsVisible && TreeView != null) + TreeView.UpdateBelow (this); + if(!byInternal && TreeView != null && HasFocusInChildren ()) + TreeView.SelectedNode = this; + } + } + + private bool HasFocusInChildren() + { + if(TreeView == null) return false; + foreach(TreeNode node in nodes) { + if(node == TreeView.SelectedNode) return true; + if(node.HasFocusInChildren()) + return true; + } + return false; + } + + private void ExpandRecursive (TreeNode node) + { + node.Expand (true); + foreach (TreeNode child in node.Nodes) { + ExpandRecursive (child); + } + } + + private void ExpandParentRecursive (TreeNode node) + { + node.Expand (true); + if (node.Parent != null) + ExpandParentRecursive (node.Parent); + } + + internal void CollapseAll () + { + CollapseRecursive (this); + } + + internal void CollapseAllUncheck () + { + CollapseUncheckRecursive (this); + } + + private void CollapseRecursive (TreeNode node) + { + node.Collapse (); + foreach (TreeNode child in node.Nodes) { + CollapseRecursive (child); + } + } + + private void CollapseUncheckRecursive (TreeNode node) + { + node.Collapse (); + node.Checked = false; + foreach (TreeNode child in node.Nodes) { + CollapseUncheckRecursive (child); + } + } + + internal void SetNodes (TreeNodeCollection nodes) + { + this.nodes = nodes; + } + + private void GetNodeCountRecursive (TreeNode node, ref int count) + { + count += node.Nodes.Count; + foreach (TreeNode child in node.Nodes) { + GetNodeCountRecursive (child, ref count); + } + } + + internal bool NeedsWidth { + get { return bounds.Width == 0; } + } + + internal void InvalidateWidth () + { + bounds.Width = 0; + } + + internal void SetWidth (int width) + { + bounds.Width = width; + } + + internal void SetHeight (int height) + { + bounds.Height = height; + } + + internal void SetPosition (int x, int y) + { + bounds.X = x; + bounds.Y = y; + } + + internal void SetParent (TreeNode parent) + { + this.parent = parent; + } + + private bool IsInClippingRect + { + get { + if (TreeView == null) + return false; + if (bounds.Y < 0 && bounds.Y > TreeView.ClientRectangle.Height) + return false; + return true; + } + } + #endregion // Internal & Private Methods and Properties + + } +} + |