1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004 Novell, Inc.
23 // Jackson Harper (jackson@ximian.com)
28 using System.Runtime.Serialization;
30 namespace System.Windows.Forms {
33 public class TreeNode : MarshalByRefObject, ICloneable /*, ISerializable */ {
35 private TreeView tree_view;
36 internal TreeNode parent;
40 private int image_index = -1;
41 private int selected_image_index = -1;
42 internal TreeNodeCollection nodes;
44 private bool is_expanded = true;
45 private Rectangle bounds = Rectangle.Empty;
47 internal OwnerDrawPropertyBag prop_bag;
50 private IntPtr handle;
52 internal TreeNode (TreeView tree_view) : this ()
54 this.tree_view = tree_view;
59 nodes = new TreeNodeCollection (this);
62 public TreeNode (string text) : this ()
67 public TreeNode (string text, TreeNode [] children) : this (text)
69 Nodes.AddRange (children);
72 public TreeNode (string text, int image_index, int selected_image_index) : this (text)
74 this.image_index = image_index;
75 this.selected_image_index = selected_image_index;
78 public TreeNode (string text, int image_index, int selected_image_index,
79 TreeNode [] children) : this (text, image_index, selected_image_index)
81 Nodes.AddRange (children);
84 internal TreeView TreeView {
86 if (tree_view != null)
88 TreeNode walk = parent;
89 while (walk != null) {
90 if (walk.TreeView != null)
91 tree_view = walk.TreeView;
98 #region ICloneable Members
100 public object Clone()
102 TreeNode tn = new TreeNode (text, image_index, selected_image_index);
104 foreach (TreeNode child in nodes)
105 tn.Nodes.Add ((TreeNode)child.Clone ());
108 tn.Checked = Checked;
109 if (prop_bag != null)
110 tn.prop_bag = OwnerDrawPropertyBag.Copy (prop_bag);
116 public TreeNode Parent {
118 if (tree_view != null && tree_view.root_node == parent)
138 public Rectangle Bounds {
139 get { return bounds; }
142 public bool Checked {
143 get { return check; }
144 set { check = value; }
147 public Color BackColor {
149 return prop_bag == null ? Color.Empty : prop_bag.BackColor;
152 if (prop_bag == null)
153 prop_bag = new OwnerDrawPropertyBag ();
154 prop_bag.BackColor = value;
158 public Color ForeColor {
160 return prop_bag == null ? Color.Empty : prop_bag.ForeColor;
163 if (prop_bag == null)
164 prop_bag = new OwnerDrawPropertyBag ();
165 prop_bag.ForeColor = value;
169 public Font NodeFont {
171 return prop_bag == null ? null : prop_bag.Font;
174 if (prop_bag == null)
175 prop_bag = new OwnerDrawPropertyBag ();
176 prop_bag.Font = value;
180 public TreeNodeCollection Nodes {
183 nodes = new TreeNodeCollection (this);
188 public TreeNode FirstNode {
196 public string FullPath {
198 if (tree_view == null)
199 throw new Exception ("No TreeView associated");
201 StringBuilder builder = new StringBuilder ();
202 BuildFullPath (builder);
203 return builder.ToString ();
207 bool BuildFullPath (StringBuilder path)
212 if (parent.BuildFullPath (path))
213 path.Append (tree_view.PathSeparator);
219 public bool IsExpanded {
220 get { return is_expanded; }
223 public TreeNode NextNode {
227 if (parent.Nodes.Count > index + 1)
228 return parent.Nodes [index + 1];
233 public TreeNode PrevNode {
237 if (index == 0 || index > parent.Nodes.Count)
239 return parent.Nodes [index - 1];
243 public TreeNode NextVisibleNode {
245 OpenTreeNodeEnumerator o = new OpenTreeNodeEnumerator (this);
248 TreeNode c = (TreeNode) o.Current;
249 if (!c.IsInClippingRect)
255 public TreeNode PrevVisibleNode {
257 OpenTreeNodeEnumerator o = new OpenTreeNodeEnumerator (this);
258 if (!o.MovePrevious ())
260 TreeNode c = (TreeNode) o.Current;
261 if (!c.IsInClippingRect)
267 public TreeNode LastNode {
269 return (nodes == null || nodes.Count == 0) ? null : nodes [nodes.Count - 1];
274 get { return index; }
277 public int ImageIndex {
278 get { return image_index; }
279 set { image_index = value; }
282 public int SelectedImageIndex {
283 get { return selected_image_index; }
284 set { selected_image_index = value; }
292 public void Expand ()
298 if (TreeView != null) {
299 TreeViewCancelEventArgs e = new TreeViewCancelEventArgs (this, false, TreeViewAction.Expand);
300 TreeView.OnBeforeCollapse (e);
306 if (TreeView != null)
307 TreeView.OnAfterCollapse (new TreeViewEventArgs (this));
308 if (IsNodeVisible () && TreeView != null)
309 TreeView.UpdateBelow (this);
313 public void Collapse ()
319 if (TreeView != null) {
320 TreeViewCancelEventArgs e = new TreeViewCancelEventArgs (this, false, TreeViewAction.Collapse);
321 TreeView.OnBeforeCollapse (e);
327 if (TreeView != null)
328 TreeView.OnAfterCollapse (new TreeViewEventArgs (this));
329 if (IsNodeVisible () && TreeView != null)
330 TreeView.UpdateBelow (this);
334 public void Remove ()
338 parent.Nodes.RemoveAt (Index);
341 public void ExpandAll ()
343 ExpandRecursive (this);
346 private void ExpandRecursive (TreeNode node)
349 foreach (TreeNode child in node.Nodes) {
350 ExpandRecursive (child);
354 internal void CollapseAll ()
356 CollapseRecursive (this);
359 private void CollapseRecursive (TreeNode node)
362 foreach (TreeNode child in node.Nodes) {
363 CollapseRecursive (child);
367 public int GetNodeCount (bool include_subtrees)
369 if (!include_subtrees)
373 GetNodeCountRecursive (this, ref count);
378 public void Toggle ()
385 if (TreeView != null)
389 internal void SetNodes (TreeNodeCollection nodes)
394 private void GetNodeCountRecursive (TreeNode node, ref int count)
396 count += node.Nodes.Count;
397 foreach (TreeNode child in node.Nodes) {
398 GetNodeCountRecursive (child, ref count);
402 public override String ToString ()
404 return String.Concat ("TreeNode: ", Text);
407 internal void UpdateBounds (int x, int y, int width, int height)
411 bounds.Width = width;
412 bounds.Height = height;
415 internal void SetAddedData (TreeView tree_view, TreeNode parent, int index)
417 this.tree_view = tree_view;
418 this.parent = parent;
422 private bool IsInClippingRect
425 if (TreeView == null)
427 if (bounds.Y < 0 && bounds.Y > tree_view.ClientRectangle.Height)
433 private bool IsNodeVisible ()
435 if (TreeView == null)
438 if (bounds.Y < 0 && bounds.Y > TreeView.ClientRectangle.Height)
441 TreeNode parent = Parent;
442 while (parent != null) {
443 if (!parent.IsExpanded)
445 parent = parent.Parent;