Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeView.cs')
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeView.cs1571
1 files changed, 1571 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeView.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeView.cs
new file mode 100644
index 00000000000..eae661b3562
--- /dev/null
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TreeView.cs
@@ -0,0 +1,1571 @@
+// 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.Collections;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.InteropServices;
+
+namespace System.Windows.Forms {
+ [DefaultProperty("Nodes")]
+ [DefaultEvent("AfterSelect")]
+ [Designer("System.Windows.Forms.Design.TreeViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
+ public class TreeView : Control {
+ #region Fields
+ private string path_separator = "\\";
+ private int item_height = -1;
+ private bool sorted;
+ internal TreeNode top_node;
+ internal TreeNode root_node;
+ internal bool nodes_added;
+ private TreeNodeCollection nodes;
+
+ private TreeNode selected_node = null;
+ private TreeNode focused_node = null;
+ private bool select_mmove = false;
+
+ private ImageList image_list;
+ private int image_index = -1;
+ private int selected_image_index = -1;
+
+ private bool full_row_select;
+ private bool hot_tracking;
+ private int indent = 19;
+
+ private TextBox edit_text_box;
+ private TreeNode edit_node;
+
+ private bool checkboxes;
+ private bool label_edit;
+ private bool scrollable;
+ private bool show_lines = true;
+ private bool show_root_lines = true;
+ private bool show_plus_minus = true;
+ private bool hide_selection = true;
+
+ private bool add_hscroll;
+ private bool add_vscroll;
+ private int max_node_width;
+ private VScrollBar vbar;
+ private int skipped_nodes;
+ private HScrollBar hbar;
+ private int hbar_offset;
+ private int used_height;
+ private bool update_node_bounds;
+
+ private int update_stack;
+ private bool update_needed;
+
+ private TreeViewEventHandler on_after_check;
+ private TreeViewEventHandler on_after_collapse;
+ private TreeViewEventHandler on_after_expand;
+ private NodeLabelEditEventHandler on_after_label_edit;
+ private TreeViewEventHandler on_after_select;
+ private TreeViewCancelEventHandler on_before_check;
+ private TreeViewCancelEventHandler on_before_collapse;
+ private TreeViewCancelEventHandler on_before_expand;
+ private NodeLabelEditEventHandler on_before_label_edit;
+ private TreeViewCancelEventHandler on_before_select;
+
+ private Pen dash;
+ private StringFormat string_format;
+ private int open_node_count = -1;
+
+ private int drag_begin_x = 0;
+ private int drag_begin_y = 0;
+ private long handle_count = 1;
+
+ #endregion // Fields
+
+ #region Public Constructors
+ public TreeView ()
+ {
+ base.background_color = ThemeEngine.Current.ColorWindow;
+ base.foreground_color = ThemeEngine.Current.ColorWindowText;
+
+ root_node = new TreeNode (this);
+ root_node.Text = "ROOT NODE";
+ nodes = new TreeNodeCollection (root_node);
+ root_node.SetNodes (nodes);
+
+ MouseDown += new MouseEventHandler (MouseDownHandler);
+ MouseUp += new MouseEventHandler(MouseUpHandler);
+ MouseMove += new MouseEventHandler(MouseMoveHandler);
+ SizeChanged += new EventHandler (SizeChangedHandler);
+ FontChanged += new EventHandler (FontChangedHandler);
+ LostFocus += new EventHandler (FocusChangedHandler);
+ GotFocus += new EventHandler (FocusChangedHandler);
+ MouseWheel += new MouseEventHandler(MouseWheelHandler);
+
+ SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
+
+ string_format = new StringFormat ();
+ string_format.LineAlignment = StringAlignment.Center;
+ string_format.Alignment = StringAlignment.Center;
+ }
+
+ #endregion // Public Constructors
+
+ #region Public Instance Properties
+ public override Color BackColor {
+ get { return base.BackColor;}
+ set { base.BackColor = value; }
+ }
+
+
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override Image BackgroundImage {
+ get { return base.BackgroundImage; }
+ set { base.BackgroundImage = value; }
+ }
+
+ [DefaultValue(BorderStyle.Fixed3D)]
+ [DispId(-504)]
+ public BorderStyle BorderStyle {
+ get { return InternalBorderStyle; }
+ set { InternalBorderStyle = value; }
+ }
+
+ [DefaultValue(false)]
+ public bool CheckBoxes {
+ get { return checkboxes; }
+ set {
+ if (value == checkboxes)
+ return;
+ checkboxes = value;
+
+ // Match a "bug" in the MS implementation where disabling checkboxes
+ // collapses the entire tree, but enabling them does not affect the
+ // state of the tree.
+ if (!checkboxes)
+ root_node.CollapseAllUncheck ();
+
+ Refresh ();
+ }
+ }
+
+ public override Color ForeColor {
+ get { return base.ForeColor; }
+ set { base.ForeColor = value; }
+ }
+ [DefaultValue(false)]
+ public bool FullRowSelect {
+ get { return full_row_select; }
+ set {
+ if (value == full_row_select)
+ return;
+ full_row_select = value;
+ Refresh ();
+ }
+ }
+ [DefaultValue(true)]
+ public bool HideSelection {
+ get { return hide_selection; }
+ set {
+ if (hide_selection == value)
+ return;
+ hide_selection = value;
+ this.Refresh ();
+ }
+ }
+
+ [DefaultValue(false)]
+ public bool HotTracking {
+ get { return hot_tracking; }
+ set { hot_tracking = value; }
+ }
+
+ [DefaultValue(0)]
+ [Editor("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
+ [Localizable(true)]
+ [TypeConverter(typeof(TreeViewImageIndexConverter))]
+ public int ImageIndex {
+ get { return image_index; }
+ set {
+ if (value < -1) {
+ throw new ArgumentException ("'" + value + "' is not a valid value for 'value'. " +
+ "'value' must be greater than or equal to 0.");
+ }
+ if (image_index == value)
+ return;
+ image_index = value;
+ Refresh ();
+ }
+ }
+
+ [DefaultValue(null)]
+ public ImageList ImageList {
+ get { return image_list; }
+ set {
+ image_list = value;
+ Refresh ();
+ }
+ }
+
+ [Localizable(true)]
+ public int Indent {
+ get { return indent; }
+ set {
+ if (indent == value)
+ return;
+ if (value > 32000) {
+ throw new ArgumentException ("'" + value + "' is not a valid value for 'Indent'. " +
+ "'Indent' must be less than or equal to 32000");
+ }
+ if (value < 0) {
+ throw new ArgumentException ("'" + value + "' is not a valid value for 'Indent'. " +
+ "'Indent' must be greater than or equal to 0.");
+ }
+ indent = value;
+ Refresh ();
+ }
+ }
+
+ [Localizable(true)]
+ public int ItemHeight {
+ get {
+ if (item_height == -1)
+ return FontHeight + 3;
+ return item_height;
+ }
+ set {
+ if (value == item_height)
+ return;
+ item_height = value;
+ Refresh ();
+ }
+ }
+
+ [DefaultValue(false)]
+ public bool LabelEdit {
+ get { return label_edit; }
+ set { label_edit = value; }
+ }
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
+ [MergableProperty(false)]
+ [Localizable(true)]
+ public TreeNodeCollection Nodes {
+ get { return nodes; }
+ }
+
+ [DefaultValue("\\")]
+ public string PathSeparator {
+ get { return path_separator; }
+ set { path_separator = value; }
+ }
+
+ [DefaultValue(true)]
+ public bool Scrollable {
+ get { return scrollable; }
+ set {
+ if (scrollable == value)
+ return;
+ scrollable = value;
+ }
+ }
+
+ [Editor("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
+ [TypeConverter(typeof(TreeViewImageIndexConverter))]
+ [Localizable(true)]
+ [DefaultValue(0)]
+ public int SelectedImageIndex {
+ get { return selected_image_index; }
+ set {
+ if (value < -1) {
+ throw new ArgumentException ("'" + value + "' is not a valid value for 'value'. " +
+ "'value' must be greater than or equal to 0.");
+ }
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public TreeNode SelectedNode {
+ get { return selected_node; }
+ set {
+ if (selected_node == value)
+ return;
+
+ TreeViewCancelEventArgs e = new TreeViewCancelEventArgs (value, false, TreeViewAction.Unknown);
+ OnBeforeSelect (e);
+
+ if (e.Cancel)
+ return;
+
+ Rectangle invalid = Rectangle.Empty;
+
+ if (selected_node != null) {
+ invalid = Bloat (selected_node.Bounds);
+ }
+ if (focused_node != null) {
+ invalid = Rectangle.Union (invalid,
+ Bloat (focused_node.Bounds));
+ }
+
+ if (value != null)
+ invalid = Rectangle.Union (invalid, Bloat (value.Bounds));
+
+ selected_node = value;
+ focused_node = value;
+
+ if (full_row_select) {
+ invalid.X = 0;
+ invalid.Width = ViewportRectangle.Width;
+ }
+
+ if (invalid != Rectangle.Empty)
+ Invalidate (invalid);
+
+ // We ensure its visible after we update because
+ // scrolling is used for insure visible
+ if (selected_node != null)
+ selected_node.EnsureVisible ();
+
+ OnAfterSelect (new TreeViewEventArgs (value, TreeViewAction.Unknown));
+ }
+ }
+
+ private Rectangle Bloat (Rectangle rect)
+ {
+ rect.Y--;
+ rect.X--;
+ rect.Height += 2;
+ rect.Width += 2;
+ return rect;
+ }
+
+ [DefaultValue(true)]
+ public bool ShowLines {
+ get { return show_lines; }
+ set {
+ if (show_lines == value)
+ return;
+ show_lines = value;
+ Refresh ();
+ }
+ }
+
+ [DefaultValue(true)]
+ public bool ShowPlusMinus {
+ get { return show_plus_minus; }
+ set {
+ if (show_plus_minus == value)
+ return;
+ show_plus_minus = value;
+ Refresh ();
+ }
+ }
+
+ [DefaultValue(true)]
+ public bool ShowRootLines {
+ get { return show_root_lines; }
+ set {
+ if (show_root_lines == value)
+ return;
+ show_root_lines = value;
+ Refresh ();
+ }
+ }
+
+ [DefaultValue(false)]
+ public bool Sorted {
+ get { return sorted; }
+ set {
+ if (sorted != value)
+ sorted = value;
+ if (sorted) {
+ Nodes.Sort ();
+ top_node = null;
+ Refresh ();
+ }
+ }
+ }
+
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Bindable(false)]
+ public override string Text {
+ get { return base.Text; }
+ set { base.Text = value; }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public TreeNode TopNode {
+ get { return top_node; }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public int VisibleCount {
+ get {
+ return ClientRectangle.Height / ItemHeight;
+ }
+ }
+
+ #endregion // Public Instance Properties
+
+ #region Protected Instance Properties
+ protected override CreateParams CreateParams {
+ get {
+ CreateParams cp = base.CreateParams;
+ return cp;
+ }
+ }
+
+ protected override Size DefaultSize {
+ get { return new Size (121, 97); }
+ }
+
+ #endregion // Protected Instance Properties
+
+ #region Public Instance Methods
+ public void BeginUpdate () {
+ update_stack++;
+ }
+
+ public void CollapseAll ()
+ {
+ root_node.CollapseAll ();
+ }
+
+ public void EndUpdate ()
+ {
+ if (update_stack > 1) {
+ update_stack--;
+ } else {
+ update_stack = 0;
+ if (update_needed) {
+ Invalidate (ViewportRectangle);
+ update_needed = false;
+ }
+ }
+ }
+
+ public void ExpandAll () {
+ root_node.ExpandAll ();
+ }
+
+ public TreeNode GetNodeAt (Point pt) {
+ return GetNodeAt (pt.Y);
+ }
+
+ public TreeNode GetNodeAt (int x, int y)
+ {
+ return GetNodeAt (y);
+ }
+
+ private TreeNode GetNodeAtUseX (int x, int y) {
+ TreeNode node = GetNodeAt (y);
+ if (node == null || !(IsTextArea (node, x) || full_row_select))
+ return null;
+ return node;
+
+ }
+
+ public int GetNodeCount (bool include_subtrees) {
+ return root_node.GetNodeCount (include_subtrees);
+ }
+
+ public override string ToString () {
+ int count = Nodes.Count;
+ if (count <= 0)
+ return String.Concat (base.ToString (), "Node Count: 0");
+ return String.Concat (base.ToString (), "Node Count: ", count, " Nodes[0]: ", Nodes [0]);
+
+ }
+
+ #endregion // Public Instance Methods
+
+ #region Protected Instance Methods
+ protected override void CreateHandle () {
+ base.CreateHandle ();
+ }
+
+ protected override void Dispose (bool disposing) {
+ if (disposing)
+ image_list = null;
+
+ base.Dispose (disposing);
+ }
+
+ protected OwnerDrawPropertyBag GetItemRenderStyles (TreeNode node, int state) {
+ return node.prop_bag;
+ }
+
+ protected override bool IsInputKey (Keys key_data) {
+
+ if ((key_data & Keys.Alt) == 0) {
+ switch (key_data & Keys.KeyCode) {
+ case Keys.Enter:
+ case Keys.Escape:
+ case Keys.Prior:
+ case Keys.Next:
+ case Keys.End:
+ case Keys.Home:
+ case Keys.Left:
+ case Keys.Up:
+ case Keys.Right:
+ case Keys.Down:
+ return true;
+ }
+ }
+ return base.IsInputKey (key_data);
+ }
+
+ protected override void OnKeyDown (KeyEventArgs e)
+ {
+ OpenTreeNodeEnumerator ne;
+
+ switch (e.KeyData & Keys.KeyCode) {
+ case Keys.Add:
+ if (selected_node != null && selected_node.IsExpanded)
+ selected_node.Expand ();
+ break;
+ case Keys.Subtract:
+ if (selected_node != null && selected_node.IsExpanded)
+ selected_node.Collapse ();
+ break;
+ case Keys.Left:
+ if (selected_node != null) {
+ if (selected_node.IsExpanded)
+ selected_node.Collapse ();
+ else {
+ ne = new OpenTreeNodeEnumerator (selected_node);
+ if (ne.MovePrevious () && ne.MovePrevious ())
+ SelectedNode = ne.CurrentNode;
+ }
+ }
+ break;
+ case Keys.Right:
+ if (selected_node != null) {
+ if (!selected_node.IsExpanded)
+ selected_node.Expand ();
+ else {
+ ne = new OpenTreeNodeEnumerator (selected_node);
+ if (ne.MoveNext () && ne.MoveNext ())
+ SelectedNode = ne.CurrentNode;
+ }
+ }
+ break;
+ case Keys.Up:
+ if (selected_node != null) {
+ ne = new OpenTreeNodeEnumerator (selected_node);
+ if (ne.MovePrevious () && ne.MovePrevious ())
+ SelectedNode = ne.CurrentNode;
+ }
+ break;
+ case Keys.Down:
+ if (selected_node != null) {
+ ne = new OpenTreeNodeEnumerator (selected_node);
+ if (ne.MoveNext () && ne.MoveNext ())
+ SelectedNode = ne.CurrentNode;
+ }
+ break;
+ case Keys.Home:
+ if (root_node.Nodes.Count > 0) {
+ ne = new OpenTreeNodeEnumerator (root_node.Nodes [0]);
+ if (ne.MoveNext ())
+ SelectedNode = ne.CurrentNode;
+ }
+ break;
+ case Keys.End:
+ if (root_node.Nodes.Count > 0) {
+ ne = new OpenTreeNodeEnumerator (root_node.Nodes [0]);
+ while (ne.MoveNext ())
+ { }
+ SelectedNode = ne.CurrentNode;
+ }
+ break;
+ case Keys.PageDown:
+ if (selected_node != null) {
+ ne = new OpenTreeNodeEnumerator (selected_node);
+ int move = ViewportRectangle.Height / ItemHeight;
+ for (int i = 0; i < move && ne.MoveNext (); i++) {
+
+ }
+ SelectedNode = ne.CurrentNode;
+ }
+ break;
+ case Keys.PageUp:
+ if (selected_node != null) {
+ ne = new OpenTreeNodeEnumerator (selected_node);
+ int move = ViewportRectangle.Height / ItemHeight;
+ for (int i = 0; i < move && ne.MovePrevious (); i++)
+ { }
+ SelectedNode = ne.CurrentNode;
+ }
+ break;
+ case Keys.Multiply:
+ if (selected_node != null)
+ selected_node.ExpandAll ();
+ break;
+ }
+ base.OnKeyDown (e);
+
+ if (!e.Handled && checkboxes &&
+ selected_node != null &&
+ (e.KeyData & Keys.KeyCode) == Keys.Space) {
+ selected_node.check_reason = TreeViewAction.ByKeyboard;
+ selected_node.Checked = !selected_node.Checked;
+ e.Handled = true;
+ }
+ }
+
+ protected override void OnKeyPress (KeyPressEventArgs e)
+ {
+ base.OnKeyPress (e);
+ if (e.KeyChar == ' ')
+ e.Handled = true;
+ }
+
+ protected override void OnKeyUp (KeyEventArgs e)
+ {
+ base.OnKeyUp (e);
+ if ((e.KeyData & Keys.KeyCode) == Keys.Space)
+ e.Handled = true;
+ }
+
+ protected virtual void OnItemDrag (ItemDragEventArgs e)
+ {
+ if (ItemDrag != null)
+ ItemDrag (this, e);
+ }
+
+ protected internal virtual void OnAfterCheck (TreeViewEventArgs e) {
+ if (on_after_check != null)
+ on_after_check (this, e);
+ }
+
+ protected internal virtual void OnAfterCollapse (TreeViewEventArgs e) {
+ if (on_after_collapse != null)
+ on_after_collapse (this, e);
+ }
+
+ protected internal virtual void OnAfterExpand (TreeViewEventArgs e) {
+ if (on_after_expand != null)
+ on_after_expand (this, e);
+ }
+
+ protected virtual void OnAfterLabelEdit (NodeLabelEditEventArgs e) {
+ if (on_after_label_edit != null)
+ on_after_label_edit (this, e);
+ }
+
+ protected virtual void OnAfterSelect (TreeViewEventArgs e) {
+ if (on_after_select != null)
+ on_after_select (this, e);
+ }
+
+ protected internal virtual void OnBeforeCheck (TreeViewCancelEventArgs e) {
+ if (on_before_check != null)
+ on_before_check (this, e);
+ }
+
+ protected internal virtual void OnBeforeCollapse (TreeViewCancelEventArgs e) {
+ if (on_before_collapse != null)
+ on_before_collapse (this, e);
+ }
+
+ protected internal virtual void OnBeforeExpand (TreeViewCancelEventArgs e) {
+ if (on_before_expand != null)
+ on_before_expand (this, e);
+ }
+
+ protected virtual void OnBeforeLabelEdit (NodeLabelEditEventArgs e) {
+ if (on_before_label_edit != null)
+ on_before_label_edit (this, e);
+ }
+
+ protected virtual void OnBeforeSelect (TreeViewCancelEventArgs e) {
+ if (on_before_select != null)
+ on_before_select (this, e);
+ }
+
+ protected override void OnHandleCreated (EventArgs e) {
+ base.OnHandleCreated (e);
+
+ vbar = new ImplicitVScrollBar ();
+ hbar = new ImplicitHScrollBar ();
+
+ vbar.Visible = false;
+ hbar.Visible = false;
+ vbar.ValueChanged += new EventHandler (VScrollBarValueChanged);
+ hbar.ValueChanged += new EventHandler (HScrollBarValueChanged);
+
+ SuspendLayout ();
+ Controls.AddImplicit (vbar);
+ Controls.AddImplicit (hbar);
+ ResumeLayout ();
+ }
+
+ protected override void OnHandleDestroyed (EventArgs e) {
+ base.OnHandleDestroyed (e);
+ }
+
+ protected override void WndProc(ref Message m) {
+ switch ((Msg) m.Msg) {
+ case Msg.WM_PAINT: {
+ PaintEventArgs paint_event;
+
+ paint_event = XplatUI.PaintEventStart (Handle, true);
+ DoPaint (paint_event);
+ XplatUI.PaintEventEnd (Handle, true);
+ return;
+ }
+ case Msg.WM_LBUTTONDBLCLK:
+ int val = m.LParam.ToInt32();
+ DoubleClickHandler (null, new
+ MouseEventArgs (MouseButtons.Left,
+ 2, val & 0xffff,
+ (val>>16) & 0xffff, 0));
+ break;
+ }
+ base.WndProc (ref m);
+ }
+
+ #endregion // Protected Instance Methods
+
+ #region Internal & Private Methods and Properties
+ internal string LabelEditText {
+ get {
+ if (edit_text_box == null)
+ return String.Empty;
+ return edit_text_box.Text;
+ }
+ }
+
+ internal IntPtr CreateNodeHandle ()
+ {
+ return (IntPtr) handle_count++;
+ }
+
+ internal TreeNode NodeFromHandle (IntPtr handle)
+ {
+ // This method is called rarely, so instead of maintaining a table
+ // we just walk the tree nodes to find the matching handle
+ return NodeFromHandleRecursive (root_node, handle);
+ }
+
+ private TreeNode NodeFromHandleRecursive (TreeNode node, IntPtr handle)
+ {
+ if (node.handle == handle)
+ return node;
+ foreach (TreeNode child in node.Nodes) {
+ TreeNode match = NodeFromHandleRecursive (child, handle);
+ if (match != null)
+ return match;
+ }
+ return null;
+ }
+
+ // TODO: we shouldn't have to compute this on the fly
+ internal Rectangle ViewportRectangle {
+ get {
+ Rectangle res = ClientRectangle;
+
+ if (vbar != null && vbar.Visible)
+ res.Width -= vbar.Width;
+ if (hbar != null && hbar.Visible)
+ res.Height -= hbar.Height;
+ return res;
+ }
+ }
+
+ private TreeNode GetNodeAt (int y)
+ {
+ if (nodes.Count <= 0)
+ return null;
+
+ if (top_node == null)
+ top_node = nodes [0];
+
+ OpenTreeNodeEnumerator o = new OpenTreeNodeEnumerator (TopNode);
+ int move = y / ItemHeight;
+ for (int i = -1; i < move; i++) {
+ if (!o.MoveNext ())
+ return null;
+ }
+
+ return o.CurrentNode;
+ }
+
+ private bool IsTextArea (TreeNode node, int x)
+ {
+ return node != null && node.Bounds.Left <= x && node.Bounds.Right >= x;
+ }
+
+ private bool IsSelectableArea (TreeNode node, int x)
+ {
+ if (node == null)
+ return false;
+ int l = node.Bounds.Left;
+ if (ImageList != null)
+ l -= ImageList.ImageSize.Width;
+ return l <= x && node.Bounds.Right >= x;
+
+ }
+
+ private bool IsPlusMinusArea (TreeNode node, int x)
+ {
+ if (node.Nodes.Count == 0 || (node.parent == root_node && !show_root_lines))
+ return false;
+
+ int l = node.Bounds.Left + 5;
+
+ if (show_root_lines || node.Parent != null)
+ l -= indent;
+ if (ImageList != null)
+ l -= ImageList.ImageSize.Width + 3;
+ if (checkboxes)
+ l -= 19;
+ return (x > l && x < l + 8);
+ }
+
+ private bool IsCheckboxArea (TreeNode node, int x)
+ {
+ int l = node.Bounds.Left + 5;
+
+ if (show_root_lines || node.Parent != null)
+ l -= indent;
+ if (ImageList != null)
+ l -= ImageList.ImageSize.Width + 3;
+ return (x > l && x < l + 10);
+ }
+
+ internal void SetTop (TreeNode node)
+ {
+ OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (root_node);
+ int offset = 0;
+
+ while (walk.CurrentNode != node && walk.MoveNext ())
+ offset++;
+
+ vbar.Value = offset;
+ }
+
+ internal void SetBottom (TreeNode node)
+ {
+ OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (node);
+
+ int bottom = ViewportRectangle.Bottom;
+ int offset = 0;
+ while (walk.MovePrevious ()) {
+ if (walk.CurrentNode.Bounds.Bottom <= bottom)
+ break;
+ offset++;
+ }
+ vbar.Value += offset;
+ }
+
+ internal void UpdateBelow (TreeNode node)
+ {
+ if (update_stack > 0) {
+ update_needed = true;
+ return;
+ }
+
+ if (node == root_node) {
+ Refresh ();
+ return;
+ }
+
+ // We need to update the current node so the plus/minus block gets update too
+ Rectangle invalid = new Rectangle (0, node.Bounds.Top - 1,
+ Width, Height - node.Bounds.Top + 1);
+ Invalidate (invalid);
+ }
+
+ internal void UpdateNode (TreeNode node)
+ {
+ if (update_stack > 0) {
+ update_needed = true;
+ return;
+ }
+
+ if (node == root_node) {
+ Refresh ();
+ return;
+ }
+
+ Rectangle invalid = new Rectangle (0, node.Bounds.Top - 1, Width,
+ node.Bounds.Height + 1);
+ Invalidate (invalid);
+ }
+
+ internal void UpdateNodePlusMinus (TreeNode node)
+ {
+ if (update_stack > 0) {
+ update_needed = true;
+ return;
+ }
+
+ int l = node.Bounds.Left + 5;
+
+ if (show_root_lines || node.Parent != null)
+ l -= indent;
+ if (ImageList != null)
+ l -= ImageList.ImageSize.Width + 3;
+ if (checkboxes)
+ l -= 19;
+
+ Invalidate (new Rectangle (l, node.Bounds.Top, 8, node.Bounds.Height));
+ }
+
+ private void DoPaint (PaintEventArgs pe)
+ {
+ if (Width <= 0 || Height <= 0 || Visible == false)
+ return;
+
+ Draw (pe.ClipRectangle, pe.Graphics);
+ }
+
+ private void Draw (Rectangle clip, Graphics dc)
+ {
+ if (top_node == null && Nodes.Count > 0)
+ top_node = nodes [0];
+
+ if (selected_node == null && Nodes.Count > 0)
+ SelectedNode = nodes [0];
+
+ // Decide if we need a scrollbar
+ int old_open_node_count = open_node_count;
+
+ //Rectangle fill = ClientRectangle;
+ add_vscroll = false;
+ add_hscroll = false;
+
+ dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), clip);
+
+ Color dash_color = ControlPaint.Dark (BackColor);
+ if (dash_color == BackColor)
+ dash_color = ControlPaint.Light (BackColor);
+ dash = new Pen (dash_color, 1);
+ dash.DashStyle = DashStyle.Dot;
+
+ int depth = 0;
+ int item_height = ItemHeight;
+ int height = ClientRectangle.Height;
+
+ open_node_count = 0;
+ used_height = 0;
+ foreach (TreeNode node in nodes) {
+ DrawNode (node, dc, clip, ref depth, item_height, height);
+ depth = 0;
+ }
+
+ add_vscroll = (open_node_count * ItemHeight) > ClientRectangle.Height;
+
+ if (max_node_width > ClientRectangle.Width)
+ add_hscroll = true;
+
+ if (add_vscroll)
+ add_hscroll = max_node_width > ClientRectangle.Width - ThemeEngine.Current.VScrollBarDefaultSize.Width;
+ if (add_hscroll)
+ add_vscroll = (open_node_count * ItemHeight) > ClientRectangle.Height - ThemeEngine.Current.HScrollBarDefaultSize.Height;
+
+ if (add_hscroll) {
+ AddHorizontalScrollBar ();
+ } else if (hbar != null) {
+ hbar_offset = 0;
+ hbar.Visible = false;
+ }
+
+ if (add_vscroll) {
+ AddVerticalScrollBar (open_node_count, old_open_node_count != open_node_count);
+ } else if (vbar != null) {
+ vbar.Visible = false;
+ skipped_nodes = 0;
+ }
+
+ if (add_hscroll && add_vscroll) {
+ Rectangle corner = new Rectangle (hbar.Right, vbar.Bottom, vbar.Width, hbar.Height);
+ if (clip.IntersectsWith (corner))
+ dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorControl), corner);
+ }
+ }
+
+ private void DrawNodePlusMinus (TreeNode node, Graphics dc, int x, int middle)
+ {
+ dc.DrawRectangle (SystemPens.ControlDark, x, middle - 4, 8, 8);
+
+ if (node.IsExpanded) {
+ dc.DrawLine (SystemPens.ControlDarkDark, x + 2, middle, x + 6, middle);
+ } else {
+ dc.DrawLine (SystemPens.ControlDarkDark, x + 2, middle, x + 6, middle);
+ dc.DrawLine (SystemPens.ControlDarkDark, x + 4, middle - 2, x + 4, middle + 2);
+ }
+ }
+
+ private void DrawNodeCheckBox (TreeNode node, Graphics dc, int x, int middle)
+ {
+ using(Pen pen = new Pen (Color.Black, 2) )
+ dc.DrawRectangle (pen, x+ 3, middle - 4, 11, 11);
+
+ if (node.Checked) {
+ using(Pen check_pen = new Pen (Color.Black, 1)) {
+ dc.DrawLine (check_pen, x + 6, middle + 0, x + 8, middle + 3);
+ dc.DrawLine (check_pen, x + 6, middle + 1, x + 8, middle + 4);
+
+ dc.DrawLine (check_pen, x + 7, middle + 3, x + 13, middle - 2);
+ dc.DrawLine (check_pen, x + 7, middle + 4, x + 13, middle - 1);
+ }
+ }
+ }
+
+ private void DrawNodeLines (TreeNode node, Graphics dc, bool visible, Pen dash, int x, int y,
+ int middle, int item_height, int node_count)
+ {
+ int ladjust = 9; // left adjust
+ int radjust = 0; // right adjust
+
+ if (node_count > 0 && show_plus_minus)
+ ladjust = 13;
+ if (checkboxes)
+ radjust = 3;
+
+ dc.DrawLine (dash, x - indent + ladjust, middle, x + radjust, middle);
+
+ //if (!visible)
+ // return;
+
+ int ly = 0;
+ if (node.PrevNode != null) {
+ int prevadjust = (node.Nodes.Count > 0 && show_plus_minus ? (node.PrevNode.Nodes.Count == 0 ? 0 : 4) :
+ (node.PrevNode.Nodes.Count == 0 ? 0 : 4));
+ int myadjust = (node.Nodes.Count > 0 && show_plus_minus ? 4 : 0);
+ ly = node.PrevNode.Bounds.Bottom - (item_height / 2) + prevadjust;
+ dc.DrawLine (dash, x - indent + 9, middle - myadjust, x - indent + 9, ly);
+ } else if (node.Parent != null) {
+ int myadjust = (node.Nodes.Count > 0 && show_plus_minus ? 4 : 0);
+ ly = node.Parent.Bounds.Bottom + 1;
+ dc.DrawLine (dash, x - indent + 9, middle - myadjust, x - indent + 9, ly);
+ }
+ }
+
+ private void DrawNodeImage (TreeNode node, Graphics dc, Rectangle clip, int x, int y)
+ {
+ // Rectangle r = new Rectangle (x, y + 2, ImageList.ImageSize.Width, ImageList.ImageSize.Height);
+
+ if (!RectsIntersect (clip, x, y + 2, ImageList.ImageSize.Width, ImageList.ImageSize.Height))
+ return;
+
+ if (node.ImageIndex > -1 && ImageList != null && node.ImageIndex < ImageList.Images.Count) {
+ ImageList.Draw (dc, x, y + 2, ImageList.ImageSize.Width,
+ ImageList.ImageSize.Height, node.ImageIndex);
+ } else if (ImageIndex > -1 && ImageList != null && ImageIndex < ImageList.Images.Count) {
+ ImageList.Draw (dc, x, y + 2, ImageList.ImageSize.Width,
+ ImageList.ImageSize.Height, ImageIndex);
+ }
+ }
+
+ private void DrawEditNode (TreeNode node)
+ {
+ SuspendLayout ();
+
+ if (edit_text_box == null) {
+ edit_text_box = new FixedSizeTextBox ();
+ edit_text_box.BorderStyle = BorderStyle.FixedSingle;
+ edit_text_box.KeyUp += new KeyEventHandler (EditTextBoxKeyDown);
+ edit_text_box.Leave += new EventHandler (EditTextBoxLeave);
+ Controls.AddImplicit (edit_text_box);
+ }
+
+ edit_text_box.Bounds = node.Bounds;
+ edit_text_box.Width += 4;
+
+ edit_text_box.Text = node.Text;
+ edit_text_box.Visible = true;
+ edit_text_box.Focus ();
+ edit_text_box.SelectAll ();
+
+ ResumeLayout ();
+ }
+
+ private void EditTextBoxKeyDown (object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Return)
+ EndEdit ();
+ }
+
+ private void EditTextBoxLeave (object sender, EventArgs e)
+ {
+ EndEdit ();
+ }
+
+ private void EndEdit ()
+ {
+ edit_text_box.Visible = false;
+ edit_node.EndEdit (false);
+ UpdateNode(edit_node);
+ }
+
+ private void UpdateNodeBounds (TreeNode node, int x, int y, int item_height, Graphics dc)
+ {
+ Font font = node.NodeFont;
+ if (node.NodeFont == null)
+ font = Font;
+
+ if (node.NeedsWidth || update_node_bounds)
+ node.SetWidth ((int) dc.MeasureString (node.Text, font, 0,
+ string_format).Width + 3);
+ node.SetHeight (item_height);
+ node.SetPosition (x, y);
+ }
+
+ private void DrawSelectionAndFocus(TreeNode node, Graphics dc, Rectangle r)
+ {
+ if (Focused && focused_node == node) {
+ ControlPaint.DrawFocusRectangle (dc, r, ForeColor, BackColor);
+ }
+ r.Inflate(-1, -1);
+ if ((!HideSelection || Focused) && SelectedNode == node)
+ dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHighlight), r);
+ else
+ dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (node.BackColor), r);
+ }
+
+ private void DrawStaticNode (TreeNode node, Graphics dc)
+ {
+ if (!full_row_select)
+ DrawSelectionAndFocus(node, dc, node.Bounds);
+
+ Font font = node.NodeFont;
+ if (node.NodeFont == null)
+ font = Font;
+ Color text_color = ((Focused || !HideSelection) && SelectedNode == node ?
+ ThemeEngine.Current.ColorHighlightText : node.ForeColor);
+ dc.DrawString (node.Text, font,
+ ThemeEngine.Current.ResPool.GetSolidBrush (text_color),
+ node.Bounds, string_format);
+ }
+
+ private void DrawNode (TreeNode node, Graphics dc, Rectangle clip, ref int depth, int item_height, int max_height)
+ {
+ open_node_count++;
+ int x = (!show_root_lines && node.Parent != null ? depth - 1 : depth) * indent - hbar_offset;
+ int y = item_height * (open_node_count - skipped_nodes - 1);
+ bool visible = (y >= 0 && y < max_height);
+ int _n_count = node.nodes.Count;
+ int middle = y + (item_height / 2);
+
+ // The thing is totally out of the clipping rectangle
+ if (clip.Top > y + ItemHeight || clip.Bottom < y)
+ visible = false;
+
+ if (visible && full_row_select) {
+ Rectangle r = new Rectangle(1, y+2, ViewportRectangle.Width-2, item_height);
+ DrawSelectionAndFocus(node, dc, r);
+ }
+
+ if (show_root_lines || node.Parent != null) {
+ x += 5;
+ if (_n_count > 0) {
+ if (show_plus_minus && visible) {
+ DrawNodePlusMinus (node, dc, x, middle);
+ }
+ }
+ x += indent - 5;
+ }
+
+ int ox = x;
+
+ if (checkboxes) {
+ if (visible)
+ DrawNodeCheckBox (node, dc, ox, middle);
+ ox += 19;
+ }
+
+ if (show_lines)
+ DrawNodeLines (node, dc, visible, dash, x, y, middle, item_height, _n_count);
+
+ if (ImageList != null) {
+ if (visible)
+ DrawNodeImage (node, dc, clip, ox, y);
+ // MS leaves the space for the image if the ImageList is
+ // non null regardless of whether or not an image is drawn
+ ox += ImageList.ImageSize.Width + 3; // leave a little space so the text isn't against the image
+ }
+
+ UpdateNodeBounds (node, ox, y, item_height, dc);
+
+ bool bounds_in_clip = clip.IntersectsWith (node.Bounds) || full_row_select;
+ if (visible && bounds_in_clip) {
+ if (node.IsEditing)
+ DrawEditNode (node);
+ else
+ DrawStaticNode (node, dc);
+ }
+
+ if (node.Bounds.Right > max_node_width) {
+ max_node_width = node.Bounds.Right;
+ if (max_node_width > ClientRectangle.Width && !add_hscroll) {
+ max_height -= ItemHeight;
+ add_hscroll = true;
+ }
+ }
+
+ if (node.Bounds.Bottom > used_height)
+ used_height = node.Bounds.Bottom;
+
+ depth++;
+ if (node.IsExpanded) {
+ for (int i = 0; i < _n_count; i++) {
+ int tdepth = depth;
+ DrawNode (node.nodes [i], dc, clip, ref tdepth, item_height, max_height);
+ }
+ }
+
+ }
+
+ private void AddVerticalScrollBar (int total_nodes, bool count_changed)
+ {
+ vbar.Bounds = new Rectangle (ClientRectangle.Width - vbar.Width,
+ 0, vbar.Width, (add_hscroll ? Height - ThemeEngine.Current.HScrollBarDefaultSize.Height : Height));
+
+ if (count_changed) {
+ vbar.Maximum = total_nodes;
+ int height = ClientRectangle.Height;
+ vbar.LargeChange = height / ItemHeight;
+ }
+
+ vbar.Visible = true;
+ }
+
+ private void AddHorizontalScrollBar ()
+ {
+ hbar.Bounds = new Rectangle (ClientRectangle.Left,
+ ClientRectangle.Bottom - hbar.Height,
+ (add_vscroll ? Width - ThemeEngine.Current.VScrollBarDefaultSize.Width : Width), hbar.Height);
+
+ int width = ClientRectangle.Width;
+ if (vbar.Visible)
+ width -= vbar.Width;
+
+ hbar.SmallChange = 15;
+ hbar.LargeChange = 50;
+ int num_pixels = max_node_width - width;
+ hbar.Maximum = num_pixels + 50;
+ hbar.Visible = true;
+ }
+
+ private void SizeChangedHandler (object sender, EventArgs e)
+ {
+ SuspendLayout ();
+
+ if (max_node_width > ClientRectangle.Width && ClientRectangle.Width >= 0) {
+ add_hscroll = true;
+ AddHorizontalScrollBar ();
+ return;
+ }
+
+ if (used_height > ClientRectangle.Height && ClientRectangle.Height >= 0) {
+ add_vscroll = true;
+ AddVerticalScrollBar (open_node_count, true);
+ return;
+ }
+
+ if (vbar != null && vbar.Visible) {
+ int height = (hbar != null && hbar.Visible ? Height - hbar.Height : Height);
+ vbar.SetBounds (Right - vbar.Width, 0, 0, height, BoundsSpecified.X | BoundsSpecified.Height);
+ }
+
+ if (hbar != null && hbar.Visible) {
+ int width = (vbar != null && vbar.Visible ? Width - vbar.Width : Width);
+ hbar.SetBounds (0, Bottom - hbar.Height, width, 0, BoundsSpecified.Y | BoundsSpecified.Width);
+ }
+
+ ResumeLayout ();
+ }
+
+ private void VScrollBarValueChanged (object sender, EventArgs e)
+ {
+ SetVScrollPos (vbar.Value, null);
+ }
+
+ private void SetVScrollPos (int pos, TreeNode new_top)
+ {
+ if (pos < 0)
+ pos = 0;
+
+ if (skipped_nodes == pos)
+ return;
+
+ int old_skip = skipped_nodes;
+ skipped_nodes = pos;
+ int diff = old_skip - skipped_nodes;
+
+ // Determine the new top node if we have to
+ if (new_top == null) {
+ if (top_node == null)
+ top_node = nodes [0];
+
+ OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (TopNode);
+ if (diff < 0) {
+ for (int i = diff; i <= 0; i++)
+ walk.MoveNext ();
+ new_top = walk.CurrentNode;
+ } else {
+ for (int i = 0; i <= diff; i++)
+ walk.MovePrevious ();
+ new_top = walk.CurrentNode;
+ }
+ }
+
+ top_node = new_top;
+ int y_move = diff * ItemHeight;
+ XplatUI.ScrollWindow (Handle, ViewportRectangle, 0, y_move, false);
+ }
+
+ private void HScrollBarValueChanged(object sender, EventArgs e)
+ {
+ int old_offset = hbar_offset;
+ hbar_offset = hbar.Value;
+
+ if (hbar_offset < 0)
+ hbar_offset = 0;
+
+ XplatUI.ScrollWindow (Handle, ViewportRectangle, old_offset - hbar_offset, 0, false);
+ }
+
+ private void MouseWheelHandler(object sender, MouseEventArgs e) {
+ if (vbar == null || !vbar.Visible) {
+ return;
+ }
+
+ if (e.Delta < 0) {
+ vbar.Value = Math.Min(vbar.Value + SystemInformation.MouseWheelScrollLines, vbar.Maximum);
+ } else {
+ vbar.Value = Math.Max(0, vbar.Value - SystemInformation.MouseWheelScrollLines);
+ }
+ }
+
+ private void FontChangedHandler (object sender, EventArgs e)
+ {
+ update_node_bounds = true;
+ }
+
+ private void FocusChangedHandler (object sender, EventArgs e)
+ {
+ if (selected_node != null)
+ UpdateNode (selected_node);
+ }
+
+ private void MouseDownHandler (object sender, MouseEventArgs e)
+ {
+ TreeNode node = GetNodeAt (e.Y);
+ if (node == null)
+ return;
+
+ if (show_plus_minus && IsPlusMinusArea (node, e.X)) {
+ node.Toggle ();
+ return;
+ } else if (checkboxes && IsCheckboxArea (node, e.X)) {
+ node.check_reason = TreeViewAction.ByMouse;
+ node.Checked = !node.Checked;
+ UpdateNode(node);
+ return;
+ } else if (IsSelectableArea (node, e.X) || full_row_select) {
+ TreeNode old_selected = selected_node;
+ SelectedNode = node;
+ if (label_edit && e.Clicks == 1 && selected_node == old_selected) {
+ node.BeginEdit ();
+ if (edit_node != null) {
+ edit_node.EndEdit (false);
+ UpdateNode (edit_node);
+ }
+ edit_node = node;
+ UpdateNode (edit_node);
+ } else if (selected_node != focused_node) {
+ select_mmove = true;
+ }
+ }
+ }
+
+ private void MouseUpHandler (object sender, MouseEventArgs e) {
+
+ drag_begin_x = -1;
+ drag_begin_y = -1;
+
+ OnClick (EventArgs.Empty);
+
+ if (!select_mmove)
+ return;
+
+ select_mmove = false;
+
+ TreeViewCancelEventArgs ce = new TreeViewCancelEventArgs (selected_node, false, TreeViewAction.ByMouse);
+ OnBeforeSelect (ce);
+
+ Rectangle invalid;
+ if (!ce.Cancel) {
+ if (focused_node != null) {
+ invalid = Rectangle.Union (Bloat (focused_node.Bounds),
+ Bloat (selected_node.Bounds));
+ } else {
+ invalid = Bloat (selected_node.Bounds);
+ }
+ focused_node = selected_node;
+ OnAfterSelect (new TreeViewEventArgs (selected_node, TreeViewAction.ByMouse));
+
+ Invalidate (invalid);
+ } else {
+ selected_node = focused_node;
+ }
+
+
+ }
+
+ private void MouseMoveHandler (object sender, MouseEventArgs e) {
+
+ if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right) {
+ if (drag_begin_x == -1 && drag_begin_y == -1) {
+ drag_begin_x = e.X;
+ drag_begin_y = e.Y;
+ } else {
+ double rise = Math.Pow (drag_begin_x - e.X, 2);
+ double run = Math.Pow (drag_begin_y - e.Y, 2);
+ double move = Math.Sqrt (rise + run);
+ if (move > 3) {
+ TreeNode drag = GetNodeAtUseX (e.X, e.Y);
+
+ if (drag != null) {
+ OnItemDrag (new ItemDragEventArgs (e.Button, drag));
+ }
+ drag_begin_x = -1;
+ drag_begin_y = -1;
+ }
+ }
+
+ }
+ if(!select_mmove)
+ return;
+ TreeNode node = GetNodeAtUseX (e.X,e.Y);
+ if(node == selected_node)
+ return;
+
+ selected_node = focused_node;
+ select_mmove = false;
+ Refresh();
+ }
+
+ private void DoubleClickHandler (object sender, MouseEventArgs e) {
+ TreeNode node = GetNodeAtUseX (e.X,e.Y);
+ if(node != null) {
+ node.Toggle();
+ }
+ }
+
+
+ private bool RectsIntersect (Rectangle r, int left, int top, int width, int height)
+ {
+ return !((r.Left > left + width) || (r.Right < left) ||
+ (r.Top > top + height) || (r.Bottom < top));
+ }
+
+ #endregion // Internal & Private Methods and Properties
+
+ #region Events
+ public event ItemDragEventHandler ItemDrag;
+
+ public event TreeViewEventHandler AfterCheck {
+ add { on_after_check += value; }
+ remove { on_after_check -= value; }
+ }
+
+ public event TreeViewEventHandler AfterCollapse {
+ add { on_after_collapse += value; }
+ remove { on_after_collapse -= value; }
+ }
+
+ public event TreeViewEventHandler AfterExpand {
+ add { on_after_expand += value; }
+ remove { on_after_expand -= value; }
+ }
+
+ public event NodeLabelEditEventHandler AfterLabelEdit {
+ add { on_after_label_edit += value; }
+ remove { on_after_label_edit -= value; }
+ }
+
+ public event TreeViewEventHandler AfterSelect {
+ add { on_after_select += value; }
+ remove { on_after_select -= value; }
+ }
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public event EventHandler BackgroundImageChanged {
+ add { base.BackgroundImageChanged += value; }
+ remove { base.BackgroundImageChanged -= value; }
+ }
+
+ public event TreeViewCancelEventHandler BeforeCheck {
+ add { on_before_check += value; }
+ remove { on_before_check -= value; }
+ }
+
+ public event TreeViewCancelEventHandler BeforeCollapse {
+ add { on_before_collapse += value; }
+ remove { on_before_collapse -= value; }
+ }
+
+ public event TreeViewCancelEventHandler BeforeExpand {
+ add { on_before_expand += value; }
+ remove { on_before_expand -= value; }
+ }
+
+ public event NodeLabelEditEventHandler BeforeLabelEdit {
+ add { on_before_label_edit += value; }
+ remove { on_before_label_edit -= value; }
+ }
+
+ public event TreeViewCancelEventHandler BeforeSelect {
+ add { on_before_select += value; }
+ remove { on_before_select -= value; }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Browsable (false)]
+ public new event PaintEventHandler Paint {
+ add { base.Paint += value; }
+ remove { base.Paint -= value; }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Browsable (false)]
+ public new event EventHandler TextChanged {
+ add { base.TextChanged += value; }
+ remove { base.TextChanged -= value; }
+ }
+ #endregion // Events
+ }
+}
+