2008-03-27 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / TreeView.cs
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //      Jackson Harper (jackson@ximian.com)
24 //      Kazuki Oikawa (kazuki@panicode.com)
25
26 using System;
27 using System.Collections;
28 using System.ComponentModel;
29 using System.ComponentModel.Design;
30 using System.Drawing;
31 using System.Drawing.Drawing2D;
32 using System.Runtime.InteropServices;
33
34 namespace System.Windows.Forms {
35 #if NET_2_0
36         [ComVisible (true)]
37         [Docking (DockingBehavior.Ask)]
38         [ClassInterface (ClassInterfaceType.AutoDispatch)]
39 #endif
40         [DefaultProperty("Nodes")]
41         [DefaultEvent("AfterSelect")]
42         [Designer("System.Windows.Forms.Design.TreeViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
43         public class TreeView : Control {
44                 #region Fields
45                 private string path_separator = "\\";
46                 private int item_height = -1;
47                 private bool sorted;
48                 internal TreeNode root_node;
49                 internal bool nodes_added;
50                 private TreeNodeCollection nodes;
51
52                 private TreeViewAction selection_action;
53                 internal TreeNode selected_node;
54                 private TreeNode pre_selected_node;
55                 private TreeNode focused_node;
56                 internal TreeNode highlighted_node;
57                 private Rectangle mouse_rect;
58                 private bool select_mmove;
59
60                 private ImageList image_list;
61                 private int image_index = -1;
62                 private int selected_image_index = -1;
63
64 #if NET_2_0
65                 private string image_key;
66                 private bool is_hovering;
67                 private TreeNode mouse_click_node;
68                 private bool right_to_left_layout;
69                 private string selected_image_key;
70                 private bool show_node_tool_tips;
71                 private ImageList state_image_list;
72                 private TreeNode tooltip_currently_showing;
73                 private ToolTip tooltip_window;
74 #endif
75                 private bool full_row_select;
76                 private bool hot_tracking;
77                 private int indent = 19;
78
79                 private NodeLabelEditEventArgs edit_args;
80                 private LabelEditTextBox edit_text_box;
81                 internal TreeNode edit_node;
82                 
83                 private bool checkboxes;
84                 private bool label_edit;
85                 private bool scrollable = true;
86                 private bool show_lines = true;
87                 private bool show_root_lines = true;
88                 private bool show_plus_minus = true;
89                 private bool hide_selection = true;
90
91                 private int max_visible_order = -1;
92                 private VScrollBar vbar;
93                 private HScrollBar hbar;
94                 private bool vbar_bounds_set;
95                 private bool hbar_bounds_set;
96                 internal int skipped_nodes;
97                 internal int hbar_offset;
98                 
99                 private int update_stack;
100                 private bool update_needed;
101                 
102                 private Pen dash;
103                 private Color line_color;
104                 private StringFormat string_format;
105
106                 private int drag_begin_x = -1;
107                 private int drag_begin_y = -1;
108                 private long handle_count = 1;
109
110                 private TreeViewDrawMode draw_mode;
111
112 #if NET_2_0
113                 IComparer tree_view_node_sorter;
114 #endif
115                 #endregion      // Fields
116
117                 #region Public Constructors     
118                 public TreeView ()
119                 {
120                         vbar = new ImplicitVScrollBar ();
121                         hbar = new ImplicitHScrollBar ();
122
123                         InternalBorderStyle = BorderStyle.Fixed3D;
124                         base.background_color = ThemeEngine.Current.ColorWindow;
125                         base.foreground_color = ThemeEngine.Current.ColorWindowText;
126
127                         root_node = new TreeNode (this);
128                         root_node.Text = "ROOT NODE";
129                         nodes = new TreeNodeCollection (root_node);
130                         root_node.SetNodes (nodes);
131
132                         MouseDown += new MouseEventHandler (MouseDownHandler);
133                         MouseUp += new MouseEventHandler(MouseUpHandler);
134                         MouseMove += new MouseEventHandler(MouseMoveHandler);
135                         SizeChanged += new EventHandler (SizeChangedHandler);
136                         FontChanged += new EventHandler (FontChangedHandler);
137                         LostFocus += new EventHandler (LostFocusHandler);
138                         GotFocus += new EventHandler (GotFocusHandler);
139                         MouseWheel += new MouseEventHandler(MouseWheelHandler);
140                         VisibleChanged += new EventHandler (VisibleChangedHandler);
141
142                         SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
143 #if NET_2_0
144                                 | ControlStyles.UseTextForAccessibility
145 #endif
146                                 , false);
147
148                         string_format = new StringFormat ();
149                         string_format.LineAlignment = StringAlignment.Center;
150                         string_format.Alignment = StringAlignment.Center;
151
152                         vbar.Visible = false;
153                         hbar.Visible = false;
154                         vbar.ValueChanged += new EventHandler (VScrollBarValueChanged);
155                         hbar.ValueChanged += new EventHandler (HScrollBarValueChanged);
156
157                         SuspendLayout ();
158                         Controls.AddImplicit (vbar);
159                         Controls.AddImplicit (hbar);
160                         ResumeLayout ();
161                 }
162
163                 #endregion      // Public Constructors
164
165                 #region Public Instance Properties
166                 public override Color BackColor {
167                         get { return base.BackColor;}
168                         set {
169                                 base.BackColor = value;
170
171                                 CreateDashPen ();
172                                 Invalidate ();
173                         }
174                 }
175
176
177                 [Browsable(false)]
178                 [EditorBrowsable(EditorBrowsableState.Never)]
179                 public override Image BackgroundImage {
180                         get { return base.BackgroundImage; }
181                         set { base.BackgroundImage = value; }
182                 }
183
184                 [DefaultValue(BorderStyle.Fixed3D)]
185                 [DispId(-504)]
186                 public BorderStyle BorderStyle {
187                         get { return InternalBorderStyle; }
188                         set { InternalBorderStyle  = value; }
189                 }
190
191                 [DefaultValue(false)]
192                 public bool CheckBoxes {
193                         get { return checkboxes; }
194                         set {
195                                 if (value == checkboxes)
196                                         return;
197                                 checkboxes = value;
198
199                                 // Match a "bug" in the MS implementation where disabling checkboxes
200                                 // collapses the entire tree, but enabling them does not affect the
201                                 // state of the tree.
202                                 if (!checkboxes)
203                                         root_node.CollapseAllUncheck ();
204
205                                 Invalidate ();
206                         }
207                 }
208
209                 public override Color ForeColor {
210                         get { return base.ForeColor; }
211                         set { base.ForeColor = value; }
212                 }
213                 [DefaultValue(false)]
214                 public bool FullRowSelect {
215                         get { return full_row_select; }
216                         set {
217                                 if (value == full_row_select)
218                                         return;
219                                 full_row_select = value;
220                                 Invalidate ();
221                         }
222                 }
223                 [DefaultValue(true)]
224                 public bool HideSelection {
225                         get { return hide_selection; }
226                         set {
227                                 if (hide_selection == value)
228                                         return;
229                                 hide_selection = value;
230                                 Invalidate ();
231                         }
232                 }
233
234                 [DefaultValue(false)]
235                 public bool HotTracking {
236                         get { return hot_tracking; }
237                         set { hot_tracking = value; }
238                 }
239
240 #if NET_2_0
241                 [DefaultValue (-1)]
242                 [RelatedImageList ("ImageList")]
243                 [RefreshProperties (RefreshProperties.Repaint)]
244                 [TypeConverter (typeof (NoneExcludedImageIndexConverter))]
245 #else
246                 [DefaultValue (0)]
247                 [TypeConverter (typeof (TreeViewImageIndexConverter))]
248 #endif
249                 [Editor("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
250                 [Localizable(true)]
251                 public int ImageIndex {
252                         get { return image_index; }
253                         set {
254                                 if (value < -1) {
255                                         throw new ArgumentException ("'" + value + "' is not a valid value for 'value'. " +
256                                                 "'value' must be greater than or equal to 0.");
257                                 }
258                                 if (image_index == value)
259                                         return;
260                                 image_index = value;
261                                 Invalidate ();
262                         }
263                 }
264
265 #if NET_2_0
266                 [RefreshProperties (RefreshProperties.Repaint)]
267 #endif
268                 [DefaultValue(null)]
269                 public ImageList ImageList {
270                         get { return image_list; }
271                         set {
272                                 image_list = value;
273                                 Invalidate ();
274                         }
275                 }
276
277                 [Localizable(true)]
278                 public int Indent {
279                         get { return indent; }
280                         set {
281                                 if (indent == value)
282                                         return;
283                                 if (value > 32000) {
284                                         throw new ArgumentException ("'" + value + "' is not a valid value for 'Indent'. " +
285                                                 "'Indent' must be less than or equal to 32000");
286                                 }       
287                                 if (value < 0) {
288                                         throw new ArgumentException ("'" + value + "' is not a valid value for 'Indent'. " +
289                                                 "'Indent' must be greater than or equal to 0.");
290                                 }
291                                 indent = value;
292                                 Invalidate ();
293                         }
294                 }
295
296 #if !NET_2_0
297                 [Localizable(true)]
298 #endif
299                 public int ItemHeight {
300                         get {
301                                 if (item_height == -1)
302                                         return FontHeight + 3;
303                                 return item_height;
304                         }
305                         set {
306                                 if (value == item_height)
307                                         return;
308                                 item_height = value;
309                                 Invalidate ();
310                         }
311                 }
312
313                 internal int ActualItemHeight {
314                         get {
315                                 int res = ItemHeight;
316                                 if (ImageList != null && ImageList.ImageSize.Height > res)
317                                         res = ImageList.ImageSize.Height;
318                                 return res;
319                         }
320                 }
321
322                 [DefaultValue(false)]
323                 public bool LabelEdit {
324                         get { return label_edit; }
325                         set { label_edit = value; }
326                 }
327
328                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
329                 [MergableProperty(false)]
330                 [Localizable(true)]
331                 public TreeNodeCollection Nodes {
332                         get { return nodes; }
333                 }
334
335 #if NET_2_0
336                 [Browsable (false)]
337                 [EditorBrowsable (EditorBrowsableState.Never)]
338                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
339                 public new Padding Padding {
340                         get { return base.Padding; }
341                         set { base.Padding = value; }
342                 }
343 #endif
344
345                 [DefaultValue("\\")]
346                 public string PathSeparator {
347                         get { return path_separator; }
348                         set { path_separator = value; }
349                 }
350
351 #if NET_2_0
352                 [Localizable (true)]
353                 [DefaultValue (false)]
354                 public virtual bool RightToLeftLayout {
355                         get { return right_to_left_layout; }
356                         set { 
357                                 if (right_to_left_layout != value) {
358                                         right_to_left_layout = value;
359                                         OnRightToLeftLayoutChanged (EventArgs.Empty);   
360                                 }
361                         }
362                 }
363 #endif
364
365                 [DefaultValue(true)]
366                 public bool Scrollable {
367                         get { return scrollable; }
368                         set {
369                                 if (scrollable == value)
370                                         return;
371                                 scrollable = value;
372                                 UpdateScrollBars (false);
373                         }
374                 }
375
376 #if NET_2_0
377                 [DefaultValue (-1)]
378                 [RelatedImageList ("ImageList")]
379                 [TypeConverter (typeof (NoneExcludedImageIndexConverter))]
380 #else
381                 [DefaultValue (0)]
382                 [TypeConverter (typeof (TreeViewImageIndexConverter))]
383 #endif
384                 [Editor("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
385                 [Localizable(true)]
386                 public int SelectedImageIndex {
387                         get { return selected_image_index; }
388                         set {
389                                 if (value < -1) {
390                                         throw new ArgumentException ("'" + value + "' is not a valid value for 'value'. " +
391                                                 "'value' must be greater than or equal to 0.");
392                                 }
393                                 UpdateNode (SelectedNode);
394                         }
395                 }
396
397                 [Browsable(false)]
398                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
399                 public TreeNode SelectedNode {
400                         get {
401                                 if (!IsHandleCreated)
402                                         return pre_selected_node;
403                                 return selected_node;
404                         }
405                         set {
406                                 if (!IsHandleCreated) {
407                                         pre_selected_node = value;
408                                         return;
409                                 }
410
411                                 if (selected_node == value) {
412                                         selection_action = TreeViewAction.Unknown;
413                                         return;
414                                 }
415
416                                 if (value != null) {
417                                         TreeViewCancelEventArgs e = new TreeViewCancelEventArgs (value, false, selection_action);
418                                         OnBeforeSelect (e);
419
420                                         if (e.Cancel)
421                                                 return;
422                                 }
423
424                                 Rectangle invalid = Rectangle.Empty;
425
426                                 if (selected_node != null) {
427                                         invalid = Bloat (selected_node.Bounds);
428                                 }
429                                 if (focused_node != null) {
430                                         invalid = Rectangle.Union (invalid,
431                                                         Bloat (focused_node.Bounds));
432                                 }
433
434                                 if (value != null)
435                                         invalid = Rectangle.Union (invalid, Bloat (value.Bounds));
436
437                                 highlighted_node = value;
438                                 selected_node = value;
439                                 focused_node = value;
440
441                                 if (full_row_select || draw_mode != TreeViewDrawMode.Normal) {
442                                         invalid.X = 0;
443                                         invalid.Width = ViewportRectangle.Width;
444                                 }
445
446                                 if (invalid != Rectangle.Empty)
447                                         Invalidate (invalid);
448
449                                 // We ensure its visible after we update because
450                                 // scrolling is used for insure visible
451                                 if (selected_node != null)
452                                         selected_node.EnsureVisible ();
453
454                                 if (value != null) {
455                                         OnAfterSelect (new TreeViewEventArgs (value, TreeViewAction.Unknown));
456                                 }
457                                 selection_action = TreeViewAction.Unknown;
458                         }
459                 }
460
461                 private Rectangle Bloat (Rectangle rect)
462                 {
463                         rect.Y--;
464                         rect.X--;
465                         rect.Height += 2;
466                         rect.Width += 2;
467                         return rect;
468                 }
469
470                 [DefaultValue(true)]
471                 public bool ShowLines {
472                         get { return show_lines; }
473                         set {
474                                 if (show_lines == value)
475                                         return;
476                                 show_lines = value;
477                                 Invalidate ();
478                         }
479                 }
480
481 #if NET_2_0
482                 [DefaultValue (false)]
483                 public bool ShowNodeToolTips {
484                         get { return show_node_tool_tips; }
485                         set { show_node_tool_tips = value; }
486                 }
487 #endif
488
489                 [DefaultValue(true)]
490                 public bool ShowPlusMinus {
491                         get { return show_plus_minus; }
492                         set {
493                                 if (show_plus_minus == value)
494                                         return;
495                                 show_plus_minus = value;
496                                 Invalidate ();
497                         }
498                 }
499
500                 [DefaultValue(true)]
501                 public bool ShowRootLines {
502                         get { return show_root_lines; }
503                         set {
504                                 if (show_root_lines == value)
505                                         return;
506                                 show_root_lines = value;
507                                 Invalidate ();
508                         }
509                 }
510
511 #if NET_2_0
512                 [Browsable (false)]
513                 [EditorBrowsable (EditorBrowsableState.Never)]
514 #endif
515                 [DefaultValue(false)]
516                 public bool Sorted {
517                         get { return sorted; }
518                         set {
519 #if NET_2_0
520                                 if (sorted == value)
521                                         return;
522                                 sorted = value;
523                                 //LAMESPEC: The documentation says that setting this to true should sort alphabetically if TreeViewNodeSorter is set.
524                                 // There seems to be a bug in the Microsoft implementation.
525                                 if (sorted && tree_view_node_sorter == null) {
526                                         Sort (null);
527                                 }
528 #else
529                                 if (sorted != value)
530                                         sorted = value;
531                                 if (sorted) {
532                                         Sort (null);
533                                 }
534 #endif
535                         }
536                 }
537
538 #if NET_2_0
539                 [DefaultValue (null)]
540                 public ImageList StateImageList {
541                         get { return state_image_list; }
542                         set { 
543                                 state_image_list = value;
544                                 Invalidate ();
545                         }
546                 }
547 #endif
548
549                 [Browsable(false)]
550                 [EditorBrowsable(EditorBrowsableState.Never)]
551                 [Bindable(false)]
552                 public override string Text {
553                         get { return base.Text; }
554                         set { base.Text = value; }
555                 }
556
557                 [Browsable(false)]
558                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
559                 public TreeNode TopNode {
560                         get {
561                                 if (root_node.FirstNode == null)
562                                         return null;
563                                 OpenTreeNodeEnumerator one = new OpenTreeNodeEnumerator (root_node.FirstNode);
564                                 one.MoveNext ();
565                                 for (int i = 0; i < skipped_nodes; i++)
566                                         one.MoveNext ();
567                                 return one.CurrentNode;
568                         }
569 #if NET_2_0
570                         set {
571                                 SetTop (value);
572                         }
573 #endif
574                 }
575
576 #if NET_2_0
577                 [Browsable (false)]
578                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
579                 public IComparer TreeViewNodeSorter {
580                         get {
581                                 return tree_view_node_sorter;
582                         }
583                         set {
584                                 tree_view_node_sorter = value;
585                                 if (tree_view_node_sorter != null) {
586                                         Sort();
587                                         //LAMESPEC: The documentation says that setting this should set Sorted to false.
588                                         // There seems to be a bug in the Microsoft implementation.
589                                         sorted = true;
590                                 }
591                         }
592                 }
593 #endif
594
595                 [Browsable(false)]
596                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
597                 public int VisibleCount {
598                         get {
599                                 return ViewportRectangle.Height / ActualItemHeight;
600                         }
601                 }
602
603 #if NET_2_0
604                 /// According to MSDN this property has no effect on the treeview
605                 [EditorBrowsable (EditorBrowsableState.Never)]
606                 protected override bool DoubleBuffered {
607                         get { return base.DoubleBuffered; }
608                         set { base.DoubleBuffered = value; }
609                 }
610 #endif
611
612 #if NET_2_0
613                 [DefaultValue ("Color [Black]")]
614                 public
615 #else
616                 private
617 #endif
618                 Color LineColor {
619                         get {
620                                 if (line_color == Color.Empty) {
621                                         Color res = ControlPaint.Dark (BackColor);
622                                         if (res == BackColor)
623                                                 res = ControlPaint.Light (BackColor);
624                                         return res;
625                                 }
626                                 return line_color;
627                         }
628                         set {
629                                 line_color = value;
630                                 if (show_lines) {
631                                         CreateDashPen ();
632                                         Invalidate ();
633                                 }
634                         }
635                 }
636 #if NET_2_0
637                 [Localizable (true)]
638                 [DefaultValue ("")]
639                 [RelatedImageList ("ImageList")]
640                 [RefreshProperties (RefreshProperties.Repaint)]
641                 [TypeConverter (typeof (ImageKeyConverter))]
642                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
643                 public string ImageKey {
644                         get { return image_key; }
645                         set {
646                                 if (image_key == value)
647                                         return;
648                                 image_index = -1;
649                                 image_key = value;
650                                 Invalidate ();
651                         }
652                 }
653
654                 [Localizable (true)]
655                 [DefaultValue ("")]
656                 [RelatedImageList ("ImageList")]
657                 [RefreshProperties (RefreshProperties.Repaint)]
658                 [TypeConverter (typeof (ImageKeyConverter))]
659                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
660                 public string SelectedImageKey {
661                         get { return selected_image_key; }
662                         set {
663                                 if (selected_image_key == value)
664                                         return;
665                                 selected_image_index = -1;
666                                 selected_image_key = value;
667                                 UpdateNode (SelectedNode);
668                         }
669                 }
670 #endif
671
672 #if NET_2_0
673                 [Browsable (false)]
674                 [EditorBrowsable (EditorBrowsableState.Never)]
675                 public override ImageLayout BackgroundImageLayout {
676                         get { return base.BackgroundImageLayout; }
677                         set { base.BackgroundImageLayout = value; }
678                 }
679 #endif
680
681 #if NET_2_0
682                 [DefaultValue (TreeViewDrawMode.Normal)]
683                 public TreeViewDrawMode DrawMode {
684                         get { return draw_mode; }
685                         set { draw_mode = value; }
686                 }
687 #endif
688                 #endregion      // Public Instance Properties
689
690                 #region Protected Instance Properties
691                 protected override CreateParams CreateParams {
692                         get {
693                                 CreateParams cp = base.CreateParams;
694                                 return cp;
695                         }
696                 }
697
698                 protected override Size DefaultSize {
699                         get { return new Size (121, 97); }
700                 }
701
702                 #endregion      // Protected Instance Properties
703
704                 #region Public Instance Methods
705                 public void BeginUpdate ()
706                 {
707                         update_stack++;
708                 }
709
710                 public void EndUpdate ()
711                 {
712                         if (update_stack > 1) {
713                                 update_stack--;
714                         } else {
715                                 update_stack = 0;
716                                 if (update_needed) {
717                                         RecalculateVisibleOrder (root_node);
718                                         UpdateScrollBars (false);
719                                         //      if (SelectedNode != null)
720                                         //              SelectedNode.EnsureVisible ();
721                                         Invalidate (ViewportRectangle);
722                                         update_needed = false;
723                                 }
724                         }
725                 }
726
727 #if NET_2_0
728                 public  void Sort ()
729                 {
730                         Sort (Nodes.Count >= 2 ? tree_view_node_sorter : null);
731                 }
732 #endif
733
734                 void Sort (IComparer sorter) 
735                 {
736                         Nodes.Sort (sorter);
737                         RecalculateVisibleOrder (root_node);
738                         UpdateScrollBars (false);
739                         Invalidate ();
740                 }
741
742                 public void ExpandAll ()
743                 {
744                         BeginUpdate ();
745                         root_node.ExpandAll ();
746
747                         EndUpdate ();
748
749                         ///
750                         /// Everything below this is basically an emulation of a strange bug on MS
751                         /// where they don't always scroll to the last node on ExpandAll
752                         ///
753 #if NET_2_0
754                         if (!IsHandleCreated)
755                                 return;
756 #endif
757                         
758                         bool found = false;
759                         foreach (TreeNode child in Nodes) {
760                                 if (child.Nodes.Count > 0)
761                                         found = true;
762                         }
763                         
764                         if (!found)
765                                 return;
766
767                         if (IsHandleCreated && vbar.VisibleInternal) {
768                                 vbar.Value = vbar.Maximum - VisibleCount + 1;
769                         } else {
770                                 RecalculateVisibleOrder (root_node);
771                                 UpdateScrollBars (true);
772                                 SetTop (Nodes [Nodes.Count - 1]);
773                                 SelectedNode = Nodes [Nodes.Count - 1];
774                         }
775                 }
776
777                 
778                 public void CollapseAll ()
779                 {
780                         TreeNode walk = TopNode;
781                         
782                         while (walk.parent != root_node)
783                                 walk = walk.parent;
784
785                         BeginUpdate ();
786                         root_node.CollapseAll ();
787                         EndUpdate ();
788
789                         SetTop (walk);
790                 }
791
792                 public TreeNode GetNodeAt (Point pt) {
793                         return GetNodeAt (pt.Y);
794                 }
795
796                 public TreeNode GetNodeAt (int x, int y)
797                 {
798                         return GetNodeAt (y);
799                 }
800
801                 private TreeNode GetNodeAtUseX (int x, int y) {
802                         TreeNode node = GetNodeAt (y);
803                         if (node == null || !(IsTextArea (node, x) || full_row_select))
804                                 return null;
805                         return node;
806                                         
807                 }
808
809                 public int GetNodeCount (bool includeSubTrees) {
810                         return root_node.GetNodeCount (includeSubTrees);
811                 }
812
813 #if NET_2_0
814                 public TreeViewHitTestInfo HitTest (Point pt)
815                 {
816                         return HitTest (pt.X, pt.Y);
817                 }
818                 
819                 public TreeViewHitTestInfo HitTest (int x, int y)
820                 {
821                         TreeNode n = GetNodeAt (y);
822                         
823                         if (n == null)
824                                 return new TreeViewHitTestInfo (null, TreeViewHitTestLocations.None);
825                                 
826                         if (IsTextArea (n, x))
827                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.Label);
828                         else if (IsPlusMinusArea (n, x))
829                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.PlusMinus);
830                         else if ((checkboxes || n.StateImage != null) && IsCheckboxArea (n, x))
831                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.StateImage);
832                         else if (x > n.Bounds.Right)
833                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.RightOfLabel);
834                         else if (IsImage (n, x))
835                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.Image);
836                         else
837                                 return new TreeViewHitTestInfo (null, TreeViewHitTestLocations.Indent);
838                 }
839 #endif
840
841                 public override string ToString () {
842                         int count = Nodes.Count;
843                         if (count <= 0)
844                                 return String.Concat (base.ToString (), "Node Count: 0");
845                         return String.Concat (base.ToString (), "Node Count: ", count, " Nodes[0]: ", Nodes [0]);
846                                                 
847                 }
848
849                 #endregion      // Public Instance Methods
850
851                 #region Protected Instance Methods
852                 protected override void CreateHandle () {
853                         base.CreateHandle ();
854                         RecalculateVisibleOrder (root_node);
855                         UpdateScrollBars (false);
856
857                         if (pre_selected_node != null)
858                                 SelectedNode = pre_selected_node;
859                 }
860
861                 protected override void Dispose (bool disposing) {
862                         if (disposing)
863                                 image_list = null;
864
865                         base.Dispose (disposing);
866                 }
867
868                 protected OwnerDrawPropertyBag GetItemRenderStyles (TreeNode node, int state) {
869                         return node.prop_bag;
870                 }
871
872                 protected override bool IsInputKey (Keys keyData)
873                 {
874                         if (IsHandleCreated && (keyData & Keys.Alt) == 0) {
875                                 switch (keyData & Keys.KeyCode) {
876                                 case Keys.Left:
877                                 case Keys.Up:
878                                 case Keys.Right:
879                                 case Keys.Down:
880                                         return true;
881                                 case Keys.Enter:
882                                 case Keys.Escape:
883                                 case Keys.Prior:
884                                 case Keys.Next:
885                                 case Keys.End:
886                                 case Keys.Home:
887                                         if (edit_node != null)
888                                                 return true;
889                                                 
890                                         break;
891                                 }
892                         }
893                         return base.IsInputKey (keyData);
894                 }
895
896                 protected override void OnKeyDown (KeyEventArgs e)
897                 {
898                         OpenTreeNodeEnumerator ne;
899
900                         switch (e.KeyData & Keys.KeyCode) {
901                         case Keys.Add:
902                                 if (selected_node != null && selected_node.IsExpanded)
903                                         selected_node.Expand ();
904                                 break;
905                         case Keys.Subtract:
906                                 if (selected_node != null && selected_node.IsExpanded)
907                                         selected_node.Collapse ();
908                                 break;
909                         case Keys.Left:
910                                 if (selected_node != null) {
911                                         if (selected_node.IsExpanded && selected_node.Nodes.Count > 0)
912                                                 selected_node.Collapse ();
913                                         else {
914                                                 TreeNode parent = selected_node.Parent;
915                                                 if (parent != null) {
916                                                         selection_action = TreeViewAction.ByKeyboard;
917                                                         SelectedNode = parent;
918                                                 }
919                                         }
920                                 }
921                                 break;
922                         case Keys.Right:
923                                 if (selected_node != null) {
924                                         if (!selected_node.IsExpanded)
925                                                 selected_node.Expand ();
926                                         else {
927                                                 TreeNode child = selected_node.FirstNode;
928                                                 if (child != null)
929                                                         SelectedNode = child;
930                                         }
931                                 }
932                                 break;
933                         case Keys.Up:
934                                 if (selected_node != null) {
935                                         ne = new OpenTreeNodeEnumerator (selected_node);
936                                         if (ne.MovePrevious () && ne.MovePrevious ()) {
937                                                 selection_action = TreeViewAction.ByKeyboard;
938                                                 SelectedNode = ne.CurrentNode;
939                                         }
940                                 }
941                                 break;
942                         case Keys.Down:
943                                 if (selected_node != null) {
944                                         ne = new OpenTreeNodeEnumerator (selected_node);
945                                         if (ne.MoveNext () && ne.MoveNext ()) {
946                                                 selection_action = TreeViewAction.ByKeyboard;
947                                                 SelectedNode = ne.CurrentNode;
948                                         }
949                                 }
950                                 break;
951                         case Keys.Home:
952                                 if (root_node.Nodes.Count > 0) {
953                                         ne = new OpenTreeNodeEnumerator (root_node.Nodes [0]);
954                                         if (ne.MoveNext ()) {
955                                                 selection_action = TreeViewAction.ByKeyboard;
956                                                 SelectedNode = ne.CurrentNode;
957                                         }
958                                 }
959                                 break;
960                         case Keys.End:
961                                 if (root_node.Nodes.Count > 0) {
962                                         ne = new OpenTreeNodeEnumerator (root_node.Nodes [0]);
963                                         while (ne.MoveNext ())
964                                         { }
965                                         selection_action = TreeViewAction.ByKeyboard;
966                                         SelectedNode = ne.CurrentNode;
967                                 }
968                                 break;
969                         case Keys.PageDown:
970                                 if (selected_node != null) {
971                                         ne = new OpenTreeNodeEnumerator (selected_node);
972                                         int move = VisibleCount;
973                                         for (int i = 0; i < move && ne.MoveNext (); i++) {
974                                                 
975                                         }
976                                         selection_action = TreeViewAction.ByKeyboard;
977                                         SelectedNode = ne.CurrentNode;
978                                 }
979                                 break;
980                         case Keys.PageUp:
981                                 if (selected_node != null) {
982                                         ne = new OpenTreeNodeEnumerator (selected_node);
983                                         int move = VisibleCount;
984                                         for (int i = 0; i < move && ne.MovePrevious (); i++)
985                                         { }
986                                         selection_action = TreeViewAction.ByKeyboard;
987                                         SelectedNode = ne.CurrentNode;
988                                 }
989                                 break;
990                         case Keys.Multiply:
991                                 if (selected_node != null)
992                                         selected_node.ExpandAll ();
993                                 break;
994                         }
995                         base.OnKeyDown (e);
996
997                         if (!e.Handled && checkboxes &&
998                              selected_node != null &&
999                             (e.KeyData & Keys.KeyCode) == Keys.Space) {
1000                                 selected_node.check_reason = TreeViewAction.ByKeyboard;
1001                                 selected_node.Checked = !selected_node.Checked;         
1002                                 e.Handled = true;
1003                         }
1004                 }
1005
1006                 protected override void OnKeyPress (KeyPressEventArgs e)
1007                 {
1008                         base.OnKeyPress (e);
1009                         if (e.KeyChar == ' ')
1010                                 e.Handled = true;
1011                 }
1012
1013                 protected override void OnKeyUp (KeyEventArgs e)
1014                 {
1015                         base.OnKeyUp (e);
1016                         if ((e.KeyData & Keys.KeyCode) == Keys.Space)
1017                                 e.Handled = true;
1018                 }
1019
1020 #if NET_2_0
1021                 protected override void OnMouseHover (EventArgs e)
1022                 {
1023                         base.OnMouseHover (e);
1024                         
1025                         is_hovering = true;
1026
1027                         TreeNode tn = GetNodeAt (PointToClient (MousePosition));
1028
1029                         if (tn != null)
1030                                 MouseEnteredItem (tn);
1031                 }
1032
1033                 protected override void OnMouseLeave (EventArgs e)
1034                 {
1035                         base.OnMouseLeave (e);
1036                         
1037                         is_hovering = false;
1038                         
1039                         if (tooltip_currently_showing != null)
1040                                 MouseLeftItem (tooltip_currently_showing);
1041                 }
1042                 
1043                 protected virtual void OnNodeMouseClick (TreeNodeMouseClickEventArgs e)
1044                 {
1045                         TreeNodeMouseClickEventHandler eh = (TreeNodeMouseClickEventHandler)(Events[NodeMouseClickEvent]);
1046                         if (eh != null)
1047                                 eh (this, e);
1048                 }
1049
1050                 protected virtual void OnNodeMouseDoubleClick (TreeNodeMouseClickEventArgs e)
1051                 {
1052                         TreeNodeMouseClickEventHandler eh = (TreeNodeMouseClickEventHandler)(Events[NodeMouseDoubleClickEvent]);
1053                         if (eh != null)
1054                                 eh (this, e);
1055                 }
1056                 
1057                 protected virtual void OnNodeMouseHover (TreeNodeMouseHoverEventArgs e)
1058                 {
1059                         TreeNodeMouseHoverEventHandler eh = (TreeNodeMouseHoverEventHandler)(Events[NodeMouseHoverEvent]);
1060                         if (eh != null)
1061                                 eh (this, e);
1062                 }
1063 #endif
1064
1065                 protected virtual void OnItemDrag (ItemDragEventArgs e)
1066                 {
1067                         ItemDragEventHandler eh = (ItemDragEventHandler)(Events [ItemDragEvent]);
1068                         if (eh != null)
1069                                 eh (this, e);
1070                 }
1071
1072 #if NET_2_0
1073                 protected virtual void OnDrawNode(DrawTreeNodeEventArgs e) {
1074                         DrawTreeNodeEventHandler eh = (DrawTreeNodeEventHandler)(Events[DrawNodeEvent]);
1075                         if (eh != null)
1076                                 eh(this, e);
1077                 }
1078                 
1079                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1080                 protected virtual void OnRightToLeftLayoutChanged (EventArgs e) {
1081                         EventHandler eh = (EventHandler)(Events[RightToLeftLayoutChangedEvent]);
1082                         if (eh != null)
1083                                 eh (this, e);
1084                 }
1085 #endif
1086
1087                 protected internal virtual void OnAfterCheck (TreeViewEventArgs e) {
1088                         TreeViewEventHandler eh = (TreeViewEventHandler)(Events [AfterCheckEvent]);
1089                         if (eh != null)
1090                                 eh (this, e);
1091                 }
1092
1093                 protected internal virtual void OnAfterCollapse (TreeViewEventArgs e) {
1094                         TreeViewEventHandler eh = (TreeViewEventHandler)(Events [AfterCollapseEvent]);
1095                         if (eh != null)
1096                                 eh (this, e);
1097                 }
1098
1099                 protected internal virtual void OnAfterExpand (TreeViewEventArgs e) {
1100                         TreeViewEventHandler eh = (TreeViewEventHandler)(Events [AfterExpandEvent]);
1101                         if (eh != null)
1102                                 eh (this, e);
1103                 }
1104
1105                 protected virtual void OnAfterLabelEdit (NodeLabelEditEventArgs e) {
1106                         NodeLabelEditEventHandler eh = (NodeLabelEditEventHandler)(Events [AfterLabelEditEvent]);
1107                         if (eh != null)
1108                                 eh (this, e);
1109                 }
1110
1111                 protected virtual void OnAfterSelect (TreeViewEventArgs e) {
1112                         TreeViewEventHandler eh = (TreeViewEventHandler)(Events [AfterSelectEvent]);
1113                         if (eh != null)
1114                                 eh (this, e);
1115                 }
1116
1117                 protected internal virtual void OnBeforeCheck (TreeViewCancelEventArgs e) {
1118                         TreeViewCancelEventHandler eh = (TreeViewCancelEventHandler)(Events [BeforeCheckEvent]);
1119                         if (eh != null)
1120                                 eh (this, e);
1121                 }
1122
1123                 protected internal virtual void OnBeforeCollapse (TreeViewCancelEventArgs e) {
1124                         TreeViewCancelEventHandler eh = (TreeViewCancelEventHandler)(Events [BeforeCollapseEvent]);
1125                         if (eh != null)
1126                                 eh (this, e);
1127                 }
1128
1129                 protected internal virtual void OnBeforeExpand (TreeViewCancelEventArgs e) {
1130                         TreeViewCancelEventHandler eh = (TreeViewCancelEventHandler)(Events [BeforeExpandEvent]);
1131                         if (eh != null)
1132                                 eh (this, e);
1133                 }
1134
1135                 protected virtual void OnBeforeLabelEdit (NodeLabelEditEventArgs e) {
1136                         NodeLabelEditEventHandler eh = (NodeLabelEditEventHandler)(Events [BeforeLabelEditEvent]);
1137                         if (eh != null)
1138                                 eh (this, e);
1139                 }
1140
1141                 protected virtual void OnBeforeSelect (TreeViewCancelEventArgs e) {
1142                         TreeViewCancelEventHandler eh = (TreeViewCancelEventHandler)(Events [BeforeSelectEvent]);
1143                         if (eh != null)
1144                                 eh (this, e);
1145                 }
1146
1147                 protected override void OnHandleCreated (EventArgs e) {
1148                         base.OnHandleCreated (e);
1149                 }
1150
1151                 protected override void OnHandleDestroyed (EventArgs e) {
1152                         base.OnHandleDestroyed (e);
1153                 }
1154
1155                 protected override void WndProc(ref Message m) {
1156                         switch ((Msg) m.Msg) {
1157
1158                         case Msg.WM_LBUTTONDBLCLK:
1159                                 int val = m.LParam.ToInt32();
1160                                 DoubleClickHandler (null, new
1161                                                 MouseEventArgs (MouseButtons.Left,
1162                                                                 2, val & 0xffff,
1163                                                                 (val>>16) & 0xffff, 0));
1164                                         break;
1165 #if NET_2_0
1166                                 case Msg.WM_CONTEXTMENU:
1167                                         if (WmContextMenu (ref m))
1168                                                 return;
1169                                                 
1170                                         break;
1171 #endif
1172                         }
1173                         base.WndProc (ref m);
1174                 }
1175
1176                 #endregion      // Protected Instance Methods
1177
1178                 #region Internal & Private Methods and Properties
1179                 internal override bool ScaleChildrenInternal {
1180                         get { return false; }
1181                 }
1182
1183                 internal IntPtr CreateNodeHandle ()
1184                 {
1185                         return (IntPtr) handle_count++;
1186                 }
1187
1188                 // According to MSDN docs, for these to be raised, 
1189                 // the click must occur over a TreeNode
1190                 internal override void HandleClick (int clicks, MouseEventArgs me)
1191                 {
1192                         if (GetNodeAt (me.Location) != null) {
1193                                 if ((clicks > 1) && GetStyle (ControlStyles.StandardDoubleClick)) {
1194 #if !NET_2_0
1195                                         OnDoubleClick(EventArgs.Empty);
1196                                 } else {
1197                                         OnClick(EventArgs.Empty);
1198 #else
1199                                         OnDoubleClick (me);
1200                                         OnMouseDoubleClick (me);
1201                                 } else {
1202                                         OnClick (me);
1203                                         OnMouseClick (me);
1204 #endif
1205                                 }
1206                         }
1207                 }
1208                 
1209                 internal override bool IsInputCharInternal (char charCode)
1210                 {
1211                         return true;
1212                 }
1213
1214                 internal TreeNode NodeFromHandle (IntPtr handle)
1215                 {
1216                         // This method is called rarely, so instead of maintaining a table
1217                         // we just walk the tree nodes to find the matching handle
1218                         return NodeFromHandleRecursive (root_node,  handle);
1219                 }
1220
1221                 private TreeNode NodeFromHandleRecursive (TreeNode node, IntPtr handle)
1222                 {
1223                         if (node.handle == handle)
1224                                 return node;
1225                         foreach (TreeNode child in node.Nodes) {
1226                                 TreeNode match = NodeFromHandleRecursive (child, handle);
1227                                 if (match != null)
1228                                         return match;
1229                         }
1230                         return null;
1231                 }
1232
1233                 internal Rectangle ViewportRectangle {
1234                         get {
1235                                 Rectangle res = ClientRectangle;
1236
1237                                 if (vbar != null && vbar.Visible)
1238                                         res.Width -= vbar.Width;
1239                                 if (hbar != null && hbar.Visible)
1240                                         res.Height -= hbar.Height;
1241                                 return res;
1242                         }
1243                 }
1244
1245                 private TreeNode GetNodeAt (int y)
1246                 {
1247                         if (nodes.Count <= 0)
1248                                 return null;
1249
1250                         OpenTreeNodeEnumerator o = new OpenTreeNodeEnumerator (TopNode);
1251                         int move = y / ActualItemHeight;
1252                         for (int i = -1; i < move; i++) {
1253                                 if (!o.MoveNext ())
1254                                         return null;
1255                         }
1256
1257                         return o.CurrentNode;
1258                 }
1259
1260                 private bool IsTextArea (TreeNode node, int x)
1261                 {
1262                         return node != null && node.Bounds.Left <= x && node.Bounds.Right >= x;
1263                 }
1264
1265                 private bool IsSelectableArea (TreeNode node, int x)
1266                 {
1267                         if (node == null)
1268                                 return false;
1269                         int l = node.Bounds.Left;
1270                         if (ImageList != null)
1271                                 l -= ImageList.ImageSize.Width;
1272                         return l <= x && node.Bounds.Right >= x;
1273                                 
1274                 }
1275
1276                 private bool IsPlusMinusArea (TreeNode node, int x)
1277                 {
1278                         if (node.Nodes.Count == 0 || (node.parent == root_node && !show_root_lines))
1279                                 return false;
1280
1281                         int l = node.Bounds.Left + 5;
1282
1283                         if (show_root_lines || node.Parent != null)
1284                                 l -= indent;
1285                         if (ImageList != null)
1286                                 l -= ImageList.ImageSize.Width + 3;
1287                         if (checkboxes)
1288                                 l -= 19;
1289 #if NET_2_0
1290                         // StateImage is basically a custom checkbox
1291                         else if (node.StateImage != null)
1292                                 l -= 19;
1293 #endif
1294                         return (x > l && x < l + 8);
1295                 }
1296
1297                 private bool IsCheckboxArea (TreeNode node, int x)
1298                 {
1299                         int l = CheckBoxLeft (node);
1300                         return (x > l && x < l + 10);
1301                 }
1302
1303 #if NET_2_0
1304                 private bool IsImage (TreeNode node, int x)
1305                 {
1306                         if (ImageList == null)
1307                                 return false;
1308                                 
1309                         int l = node.Bounds.Left;
1310
1311                         l -= ImageList.ImageSize.Width + 5;
1312                         
1313                         if (x >= l && x <= (l + ImageList.ImageSize.Width + 5))
1314                                 return true;
1315                                 
1316                         return false;
1317                 }
1318 #endif
1319                 
1320                 private int CheckBoxLeft (TreeNode node)
1321                 {
1322                         int l = node.Bounds.Left + 5;
1323
1324                         if (show_root_lines || node.Parent != null)
1325                                 l -= indent;
1326                         if (ImageList != null)
1327                                 l -= ImageList.ImageSize.Width + 3;
1328
1329                         return l;
1330                 }
1331
1332                 internal void RecalculateVisibleOrder (TreeNode start)
1333                 {
1334                         if (update_stack > 0)
1335                                 return;
1336
1337                         int order;
1338                         if (start == null) {
1339                                 start = root_node;
1340                                 order = 0;
1341                         } else
1342                                 order = start.visible_order;
1343
1344                         
1345                         
1346                         OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (start);
1347                         while (walk.MoveNext ()) {
1348                                 walk.CurrentNode.visible_order = order;
1349                                 order++;
1350                         }
1351
1352                         max_visible_order = order;
1353                 }
1354
1355                 internal void SetTop (TreeNode node)
1356                 {
1357                         int order = 0;
1358                         if (node != null)
1359                                 order = Math.Max (0, node.visible_order - 1);
1360
1361                         if (!vbar.is_visible) {
1362                                 skipped_nodes = order;
1363                                 return;
1364                         }
1365
1366                         vbar.Value = Math.Min (order, vbar.Maximum - VisibleCount + 1);
1367                 }
1368
1369                 internal void SetBottom (TreeNode node)
1370                 {
1371                         if (!vbar.is_visible)
1372                                 return;
1373
1374                         OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (node);
1375
1376                         int bottom = ViewportRectangle.Bottom;
1377                         int offset = 0;
1378                         while (walk.MovePrevious ()) {
1379                                 if (walk.CurrentNode.Bounds.Bottom <= bottom)
1380                                         break;
1381                                 offset++;
1382                         }
1383
1384                         int nv = vbar.Value + offset;
1385                         if (vbar.Value + offset < vbar.Maximum) {
1386                                 vbar.Value = nv;
1387                         } else {
1388 #if DEBUG
1389                                 Console.Error.WriteLine ("setting bottom to value greater then maximum ({0}, {1})",
1390                                                 nv, vbar.Maximum);
1391 #endif
1392                         }
1393                                 
1394                 }
1395
1396                 internal void UpdateBelow (TreeNode node)
1397                 {
1398                         if (update_stack > 0) {
1399                                 update_needed = true;
1400                                 return;
1401                         }
1402
1403                         if (node == root_node) {
1404                                 Invalidate (ViewportRectangle);
1405                                 return;
1406                         }
1407                                 
1408                         // We need to update the current node so the plus/minus block gets update too
1409                         int top = Math.Max (node.Bounds.Top - 1, 0);
1410                         Rectangle invalid = new Rectangle (0, top,
1411                                         Width, Height - top);
1412                         Invalidate (invalid);
1413                 }
1414
1415                 internal void UpdateNode (TreeNode node)
1416                 {
1417                         if (node == null)
1418                                 return;
1419
1420                         if (update_stack > 0) {
1421                                 update_needed = true;
1422                                 return;
1423                         }
1424
1425                         if (node == root_node) {
1426                                 Invalidate ();
1427                                 return;
1428                         }
1429
1430                         Rectangle invalid = new Rectangle (0, node.Bounds.Top - 1, Width,
1431                                         node.Bounds.Height + 1);
1432                         Invalidate (invalid);
1433                 }
1434
1435                 internal void UpdateNodePlusMinus (TreeNode node)
1436                 {
1437                         if (update_stack > 0) {
1438                                 update_needed = true;
1439                                 return;
1440                         }
1441
1442                         int l = node.Bounds.Left + 5;
1443
1444                         if (show_root_lines || node.Parent != null)
1445                                 l -= indent;
1446                         if (ImageList != null)
1447                                 l -= ImageList.ImageSize.Width + 3;
1448                         if (checkboxes)
1449                                 l -= 19;
1450
1451                         Invalidate (new Rectangle (l, node.Bounds.Top, 8, node.Bounds.Height));
1452                 }
1453
1454                 internal override void OnPaintInternal (PaintEventArgs pe)
1455                 {
1456                         Draw (pe.ClipRectangle, pe.Graphics);
1457                 }
1458
1459                 internal void CreateDashPen ()
1460                 {
1461                         dash = new Pen (LineColor, 1);
1462                         dash.DashStyle = DashStyle.Dot;
1463                 }
1464
1465                 private void Draw (Rectangle clip, Graphics dc)
1466                 {
1467                         dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), clip);
1468
1469                         if (dash == null)
1470                                 CreateDashPen ();
1471
1472                         Rectangle viewport = ViewportRectangle;
1473                         Rectangle original_clip = clip;
1474                         if (clip.Bottom > viewport.Bottom)
1475                                 clip.Height = viewport.Bottom - clip.Top;
1476
1477                         OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (TopNode);
1478                         while (walk.MoveNext ()) {
1479                                 TreeNode current = walk.CurrentNode;
1480
1481                                 // Haven't gotten to visible nodes yet
1482                                 if (current.GetY () + ActualItemHeight < clip.Top)
1483                                         continue;
1484
1485                                 // Past the visible nodes
1486                                 if (current.GetY () > clip.Bottom)
1487                                         break;
1488
1489                                 DrawTreeNode (current, dc, clip);
1490                         }
1491
1492                         if (hbar.Visible && vbar.Visible) {
1493                                 Rectangle corner = new Rectangle (hbar.Right, vbar.Bottom, vbar.Width, hbar.Height);
1494                                 if (original_clip.IntersectsWith (corner))
1495                                         dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorControl),
1496                                                         corner);
1497                         }
1498                 }
1499
1500                 private void DrawNodePlusMinus (TreeNode node, Graphics dc, int x, int middle)
1501                 {
1502                         int height = ActualItemHeight - 2;
1503                         dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), (x + 4) - (height / 2), node.GetY() + 1, height, height);
1504                         
1505                         dc.DrawRectangle (SystemPens.ControlDarkDark, x, middle - 4, 8, 8);
1506
1507                         if (node.IsExpanded) {
1508                                 dc.DrawLine (SystemPens.ControlDarkDark, x + 2, middle, x + 6, middle); 
1509                         } else {
1510                                 dc.DrawLine (SystemPens.ControlDarkDark, x + 2, middle, x + 6, middle);
1511                                 dc.DrawLine (SystemPens.ControlDarkDark, x + 4, middle - 2, x + 4, middle + 2);
1512                         }
1513                 }
1514
1515 #if NET_2_0
1516                 private void DrawNodeState (TreeNode node, Graphics dc, int x, int y)
1517                 {
1518                         if (node.Checked) {
1519                                 if (StateImageList.Images[1] != null)
1520                                         dc.DrawImage (StateImageList.Images[1], new Rectangle (x, y, 16, 16));
1521                         } else {
1522                                 if (StateImageList.Images[0] != null)
1523                                         dc.DrawImage (StateImageList.Images[0], new Rectangle (x, y, 16, 16));
1524                         }
1525                 }
1526 #endif
1527
1528                 private void DrawNodeCheckBox (TreeNode node, Graphics dc, int x, int middle)
1529                 {
1530                         Pen pen = ThemeEngine.Current.ResPool.GetSizedPen(Color.Black, 2);
1531                                 dc.DrawRectangle (pen, x + 3, middle - 4, 11, 11);
1532
1533                         if (node.Checked) {
1534                                 Pen check_pen = ThemeEngine.Current.ResPool.GetPen(Color.Black);
1535                                 
1536                                 int check_size = 5;
1537                                 int lineWidth = 3;
1538                                 
1539                                 Rectangle rect = new Rectangle (x + 5, middle - 2, check_size, check_size);
1540                                 
1541                                 for (int i = 0; i < lineWidth; i++) {
1542                                         dc.DrawLine (check_pen, rect.Left + 1, rect.Top + lineWidth + i, rect.Left + 3, rect.Top + 5 + i);
1543                                         dc.DrawLine (check_pen, rect.Left + 3, rect.Top + 5 + i, rect.Left + 7, rect.Top + 1 + i);
1544                                 }
1545                         }
1546                 }
1547
1548                 private void DrawNodeLines (TreeNode node, Graphics dc, Rectangle clip, Pen dash, int x, int y, int middle)
1549                 {
1550                         int ladjust = 9;
1551                         int radjust = 0;
1552
1553                         if (node.nodes.Count > 0 && show_plus_minus)
1554                                 ladjust = 13;
1555                         if (checkboxes)
1556                                 radjust = 3;
1557
1558                         dc.DrawLine (dash, x - indent + ladjust, middle, x + radjust, middle);
1559
1560                         if (node.PrevNode != null || node.Parent != null) {
1561                                 ladjust = 9;
1562                                 dc.DrawLine (dash, x - indent + ladjust, node.Bounds.Top,
1563                                                 x - indent + ladjust, middle - (show_plus_minus && node.Nodes.Count > 0 ? 4 : 0));
1564                         }
1565
1566                         if (node.NextNode != null) {
1567                                 ladjust = 9;
1568                                 dc.DrawLine (dash, x - indent + ladjust, middle + (show_plus_minus && node.Nodes.Count > 0 ? 4 : 0),
1569                                                 x - indent + ladjust, node.Bounds.Bottom);
1570                                 
1571                         }
1572
1573                         ladjust = 0;
1574                         if (show_plus_minus)
1575                                 ladjust = 9;
1576                         TreeNode parent = node.Parent;
1577                         while (parent != null) {
1578                                 if (parent.NextNode != null) {
1579                                         int px = parent.GetLinesX () - indent + ladjust;
1580                                         dc.DrawLine (dash, px, node.Bounds.Top, px, node.Bounds.Bottom);
1581                                 }
1582                                 parent = parent.Parent;
1583                         }
1584                 }
1585
1586                 private void DrawNodeImage (TreeNode node, Graphics dc, Rectangle clip, int x, int y)
1587                 {
1588                         // Rectangle r = new Rectangle (x, y + 2, ImageList.ImageSize.Width, ImageList.ImageSize.Height);
1589
1590                         if (!RectsIntersect (clip, x, y, ImageList.ImageSize.Width, ImageList.ImageSize.Height))
1591                                 return;
1592
1593                         if (ImageList == null)
1594                                 return;
1595
1596                         int use_index = -1;
1597
1598                         if (!node.IsSelected) {
1599                                 if (node.ImageIndex > -1 && node.ImageIndex < ImageList.Images.Count) {
1600                                         use_index = node.ImageIndex;
1601                                 } else if (ImageIndex > -1 && ImageIndex < ImageList.Images.Count) {
1602                                         use_index = ImageIndex;
1603                                 }
1604                         } else {
1605                                 if (node.SelectedImageIndex > -1 && node.SelectedImageIndex < ImageList.Images.Count) {
1606                                         use_index = node.SelectedImageIndex;
1607                                 } else if (SelectedImageIndex > -1 && SelectedImageIndex < ImageList.Images.Count) {
1608                                         use_index = SelectedImageIndex;
1609                                 }
1610                         }
1611
1612 #if NET_2_0
1613
1614                         if (!node.IsSelected) {
1615                                 if (use_index == -1 && !String.IsNullOrEmpty (node.ImageKey)) {
1616                                         use_index = image_list.Images.IndexOfKey (node.ImageKey);
1617                                 }
1618
1619                                 if (use_index == -1 && !String.IsNullOrEmpty (ImageKey)) {
1620                                         use_index = image_list.Images.IndexOfKey (ImageKey);
1621                                 }
1622                         } else {
1623                                 if (use_index == -1 && !String.IsNullOrEmpty (node.SelectedImageKey)) {
1624                                         use_index = image_list.Images.IndexOfKey (node.SelectedImageKey);
1625                                 }
1626
1627                                 if (use_index == -1 && !String.IsNullOrEmpty (SelectedImageKey)) {
1628                                         use_index = image_list.Images.IndexOfKey (SelectedImageKey);
1629                                 }
1630                         }
1631 #endif
1632
1633                         if (use_index == -1 && ImageList.Images.Count > 0) {
1634                                 use_index = 0;
1635                         }
1636
1637                         if (use_index != -1) {
1638                                 ImageList.Draw (dc, x, y, ImageList.ImageSize.Width, 
1639                                                 ImageList.ImageSize.Height, use_index);
1640                         }
1641                 }
1642
1643                 private void LabelEditFinished (object sender, EventArgs e)
1644                 {
1645                         EndEdit (edit_node);
1646                 }
1647
1648                 internal void BeginEdit (TreeNode node)
1649                 {
1650                         if (edit_node != null)
1651                                 EndEdit (edit_node);
1652
1653                         if (edit_text_box == null) {
1654                                 edit_text_box = new LabelEditTextBox ();
1655                                 edit_text_box.BorderStyle = BorderStyle.FixedSingle;
1656                                 edit_text_box.Visible = false;
1657                                 edit_text_box.EditingCancelled += new EventHandler (LabelEditCancelled);
1658                                 edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
1659                                 edit_text_box.TextChanged += new EventHandler (LabelTextChanged);
1660                                 Controls.Add (edit_text_box);
1661                         }
1662
1663                         node.EnsureVisible ();
1664
1665                         edit_text_box.Bounds = node.Bounds;
1666                         edit_text_box.Text = node.Text;
1667                         edit_text_box.Visible = true;
1668                         edit_text_box.Focus ();
1669                         edit_text_box.SelectAll ();
1670
1671                         edit_args = new NodeLabelEditEventArgs (node);
1672                         OnBeforeLabelEdit (edit_args);
1673
1674                         edit_node = node;
1675                         
1676                         if (edit_args.CancelEdit) {
1677                                 edit_node = null;
1678                                 EndEdit (node);
1679                         }
1680                 }
1681
1682                 private void LabelEditCancelled (object sender, EventArgs e)
1683                 {
1684                         edit_args.SetLabel (null);
1685                         EndEdit (edit_node);
1686                 }
1687
1688                 private void LabelTextChanged (object sender, EventArgs e)
1689                 {
1690                         int width = TextRenderer.MeasureTextInternal (edit_text_box.Text, edit_text_box.Font, false).Width + 4;
1691                         edit_text_box.Width = width;
1692
1693                         if (edit_args != null)
1694                                 edit_args.SetLabel (edit_text_box.Text);
1695                 }
1696
1697                 internal void EndEdit (TreeNode node)
1698                 {
1699                         if (edit_text_box != null && edit_text_box.Visible) {
1700                                 edit_text_box.Visible = false;
1701                                 Focus ();
1702                         }
1703
1704                         //
1705                         // If we get a call to BeginEdit from any AfterLabelEdit handler,
1706                         // the focus seems to always remain in the TreeView. This call seems
1707                         // to synchronize the focus events - I don't like it but it works
1708                         //
1709                         Application.DoEvents ();
1710
1711                         if (edit_node != null && edit_node == node) {
1712                                 edit_node = null;
1713
1714                                 NodeLabelEditEventArgs e = new NodeLabelEditEventArgs (edit_args.Node, edit_args.Label);
1715
1716                                 OnAfterLabelEdit (e);
1717
1718                                 if (e.CancelEdit)
1719                                         return;
1720
1721                                 if (e.Label != null)
1722                                         e.Node.Text = e.Label;
1723                         }
1724                         
1725                         // EndEdit ends editing even if not called on the editing node
1726                         edit_node = null;
1727                         UpdateNode (node);
1728                 }
1729
1730                 internal void CancelEdit (TreeNode node)
1731                 {
1732                         edit_args.SetLabel (null);
1733                         
1734                         if (edit_text_box != null && edit_text_box.Visible) {
1735                                 edit_text_box.Visible = false;
1736                                 Focus ();
1737                         }
1738
1739                         edit_node = null;
1740                         UpdateNode (node);
1741                 }
1742
1743                 internal int GetNodeWidth (TreeNode node)
1744                 {
1745                         Font font = node.NodeFont;
1746                         if (node.NodeFont == null)
1747                                 font = Font;
1748                         return (int)TextRenderer.MeasureString (node.Text, font, 0, string_format).Width + 3;
1749                 }
1750
1751                 private void DrawSelectionAndFocus(TreeNode node, Graphics dc, Rectangle r)
1752                 {
1753                         if (Focused && focused_node == node && !full_row_select) {
1754                                 ControlPaint.DrawFocusRectangle (dc, r, ForeColor, BackColor);
1755                         }
1756                         if (draw_mode != TreeViewDrawMode.Normal)
1757                                 return;
1758
1759                         r.Inflate (-1, -1);
1760                         if (Focused && node == highlighted_node) {
1761                                 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHighlight), r);
1762                         } else if (!hide_selection && node == highlighted_node) {
1763                                 dc.FillRectangle (SystemBrushes.Control, r);
1764                         } else {
1765                                 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (node.BackColor), r);
1766                         }
1767                 }
1768                  
1769                 private void DrawStaticNode (TreeNode node, Graphics dc)
1770                 {
1771                         if (!full_row_select || show_lines)
1772                                 DrawSelectionAndFocus(node, dc, node.Bounds);
1773
1774                         
1775                         Font font = node.NodeFont;
1776                         if (node.NodeFont == null)
1777                                 font = Font;
1778                         Color text_color = (Focused && node == highlighted_node ?
1779                                         ThemeEngine.Current.ColorHighlightText : node.ForeColor);
1780                         if (text_color.IsEmpty)
1781                                 text_color = ForeColor;
1782                         dc.DrawString (node.Text, font,
1783                                         ThemeEngine.Current.ResPool.GetSolidBrush (text_color),
1784                                         node.Bounds, string_format);
1785                 }
1786
1787                 private void DrawTreeNode (TreeNode node, Graphics dc, Rectangle clip)
1788                 {
1789                         int child_count = node.nodes.Count;
1790                         int y = node.GetY ();
1791                         int middle = y + (ActualItemHeight / 2);
1792
1793                         if (full_row_select && !show_lines) {
1794                                 Rectangle r = new Rectangle (1, y, ViewportRectangle.Width - 2, ActualItemHeight);
1795                                 DrawSelectionAndFocus (node, dc, r);
1796                         }
1797
1798                         if (draw_mode == TreeViewDrawMode.Normal || draw_mode == TreeViewDrawMode.OwnerDrawText) {
1799                                 if ((show_root_lines || node.Parent != null) && show_plus_minus && child_count > 0)
1800                                         DrawNodePlusMinus (node, dc, node.GetLinesX () - Indent + 5, middle);
1801
1802 #if NET_2_0
1803                                 if (checkboxes && state_image_list == null)
1804                                         DrawNodeCheckBox (node, dc, CheckBoxLeft (node) - 3, middle);
1805
1806                                 if (checkboxes && state_image_list != null)
1807                                         DrawNodeState (node, dc, CheckBoxLeft (node) - 3, y);
1808
1809                                 if (!checkboxes && node.StateImage != null)
1810                                         dc.DrawImage (node.StateImage, new Rectangle (CheckBoxLeft (node) - 3, y, 16, 16));
1811 #else
1812                                 if (checkboxes)
1813                                         DrawNodeCheckBox (node, dc, CheckBoxLeft (node) - 3, middle);
1814 #endif
1815
1816                                 if (show_lines)
1817                                         DrawNodeLines (node, dc, clip, dash, node.GetLinesX (), y, middle);
1818
1819                                 if (ImageList != null)
1820                                         DrawNodeImage (node, dc, clip, node.GetImageX (), y);
1821                         }
1822
1823                         
1824 #if NET_2_0
1825                         if (draw_mode != TreeViewDrawMode.Normal) {
1826                                 dc.FillRectangle (Brushes.White, node.Bounds);
1827                                 TreeNodeStates tree_node_state = TreeNodeStates.Default;;
1828                                 if (node.IsSelected)
1829                                         tree_node_state = TreeNodeStates.Selected;
1830                                 if (node.Checked)
1831                                         tree_node_state |= TreeNodeStates.Checked;
1832                                 if (node == focused_node)
1833                                         tree_node_state |= TreeNodeStates.Focused;
1834                                 Rectangle node_bounds = node.Bounds;
1835                                 if (draw_mode == TreeViewDrawMode.OwnerDrawText) {
1836                                         node_bounds.X += 3;
1837                                         node_bounds.Y += 1;
1838                                 } else {
1839                                         node_bounds.X = 0;
1840                                         node_bounds.Width = Width;
1841                                 }
1842
1843                                 DrawTreeNodeEventArgs e = new DrawTreeNodeEventArgs (dc, node, node_bounds, tree_node_state);
1844
1845                                 OnDrawNode (e);                         
1846                                 if (!e.DrawDefault)
1847                                         return;
1848                         }
1849 #endif
1850
1851                         if (!node.IsEditing)
1852                                 DrawStaticNode (node, dc);
1853                 }
1854
1855                 internal void UpdateScrollBars (bool force)
1856                 {
1857                         if (!force && (IsDisposed || update_stack > 0 || !IsHandleCreated || !Visible))
1858                                 return;
1859
1860                         bool vert = false;
1861                         bool horz = false;
1862                         int height = -1;
1863                         int width = -1;
1864
1865                         if (scrollable) {
1866                                 OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (root_node);
1867                                 
1868                                 while (walk.MoveNext ()) {
1869                                         int r = walk.CurrentNode.Bounds.Right;
1870                                         int b = walk.CurrentNode.Bounds.Bottom;
1871
1872                                         if (r > width)
1873                                                 width = r;
1874                                         if (b > height)
1875                                                 height = b;
1876                                 }
1877
1878                                 // Remove scroll adjustments
1879                                 if (nodes.Count > 0)
1880                                         height -= nodes [0].Bounds.Top;
1881                                 width += hbar_offset;
1882
1883                                 if (height > ClientRectangle.Height) {
1884                                         vert = true;
1885
1886                                         if (width > ClientRectangle.Width - SystemInformation.VerticalScrollBarWidth)
1887                                                 horz = true;
1888                                 } else if (width > ClientRectangle.Width) {
1889                                         horz = true;
1890                                 }
1891
1892                                 if (!vert && horz && height > ClientRectangle.Height - SystemInformation.HorizontalScrollBarHeight)
1893                                         vert = true;
1894                         }
1895
1896                         if (vert) {
1897                                 int visible_height = horz ? ClientRectangle.Height - hbar.Height : ClientRectangle.Height;
1898                                 vbar.SetValues (Math.Max (0, max_visible_order - 2), visible_height / ActualItemHeight);
1899                                 /*
1900                                 vbar.Maximum = max_visible_order;
1901                                 vbar.LargeChange = ClientRectangle.Height / ItemHeight;
1902                                 */
1903
1904                                 if (!vbar_bounds_set) {
1905                                         vbar.Bounds = new Rectangle (ClientRectangle.Width - vbar.Width, 0, vbar.Width,
1906                                                         ClientRectangle.Height -
1907                                                         (horz ? SystemInformation.VerticalScrollBarWidth : 0));
1908                                         vbar_bounds_set = true;
1909
1910                                         // We need to recalc the hbar if the vbar is now visible
1911                                         hbar_bounds_set = false;
1912                                 }
1913
1914                                 
1915                                 vbar.Visible = true;
1916                                 if (skipped_nodes > 0) {
1917                                         int skip = Math.Min (skipped_nodes, vbar.Maximum - VisibleCount + 1);
1918                                         skipped_nodes = 0;
1919                                         vbar.Value = skip;
1920                                         skipped_nodes = skip;
1921                                 }
1922                         } else {
1923                                 skipped_nodes = 0;
1924                                 RecalculateVisibleOrder (root_node);
1925                                 vbar.Visible = false;
1926                                 vbar_bounds_set = false;
1927                         }
1928
1929                         if (horz) {
1930                                 hbar.SetValues (width + 1, ClientRectangle.Width - (vert ? SystemInformation.VerticalScrollBarWidth : 0));
1931                                 /*
1932                                 hbar.LargeChange = ClientRectangle.Width;
1933                                 hbar.Maximum = width + 1;
1934                                 */
1935
1936                                 if (!hbar_bounds_set) {
1937                                         hbar.Bounds = new Rectangle (0, ClientRectangle.Height - hbar.Height,
1938                                                         ClientRectangle.Width - (vert ? SystemInformation.VerticalScrollBarWidth : 0),
1939                                                         hbar.Height);
1940                                         hbar_bounds_set = true;
1941                                 }
1942                                 hbar.Visible = true;
1943                         } else {
1944                                 hbar_offset = 0;
1945                                 hbar.Visible = false;
1946                                 hbar_bounds_set = false;
1947                         }
1948                 }
1949
1950                 private void SizeChangedHandler (object sender, EventArgs e)
1951                 {
1952                         if (IsHandleCreated) {
1953                                 if (max_visible_order == -1)
1954                                         RecalculateVisibleOrder (root_node);
1955                                 UpdateScrollBars (false);
1956                         }
1957
1958                         if (vbar.Visible) {
1959                                 vbar.Bounds = new Rectangle (ClientRectangle.Width - vbar.Width, 0, vbar.Width,
1960                                                 ClientRectangle.Height - (hbar.Visible ? SystemInformation.HorizontalScrollBarHeight : 0));
1961                         }
1962
1963                         if (hbar.Visible) {
1964                                 hbar.Bounds = new Rectangle (0, ClientRectangle.Height - hbar.Height,
1965                                                 ClientRectangle.Width - (vbar.Visible ? SystemInformation.VerticalScrollBarWidth : 0), hbar.Height);
1966                         }
1967                 }
1968
1969                 private void VScrollBarValueChanged (object sender, EventArgs e)
1970                 {
1971                         EndEdit (edit_node);
1972
1973                         SetVScrollPos (vbar.Value, null);
1974                 }
1975
1976                 private void SetVScrollPos (int pos, TreeNode new_top)
1977                 {
1978                         if (pos < 0)
1979                                 pos = 0;
1980
1981                         if (skipped_nodes == pos)
1982                                 return;
1983
1984                         int diff = skipped_nodes - pos;
1985                         skipped_nodes = pos;
1986
1987                         if (!IsHandleCreated)
1988                                 return;
1989
1990                         int y_move = diff * ActualItemHeight;
1991                         XplatUI.ScrollWindow (Handle, ViewportRectangle, 0, y_move, false);
1992                 }
1993
1994                 /*private void SetVScrollTop (TreeNode new_top)
1995                 {
1996                         vbar.Value = new_top.visible_order - VisibleCount;
1997                 }*/
1998
1999                 private void HScrollBarValueChanged(object sender, EventArgs e)
2000                 {
2001                         EndEdit (edit_node);
2002
2003                         int old_offset = hbar_offset;
2004                         hbar_offset = hbar.Value;
2005
2006                         if (hbar_offset < 0) {
2007                                 hbar_offset = 0;
2008                         }
2009
2010                         XplatUI.ScrollWindow (Handle, ViewportRectangle, old_offset - hbar_offset, 0, false);
2011                 }
2012
2013                 internal void ExpandBelow (TreeNode node, int count_to_next)
2014                 {
2015                         if (update_stack > 0) {
2016                                 update_needed = true;
2017                                 return;
2018                         }
2019
2020                         // If node Bottom is less than 0, the node is above and not visible,
2021                         // and we need to scroll the entire viewport
2022                         int node_bottom = node.Bounds.Bottom >= 0 ? node.Bounds.Bottom : 0;
2023                         Rectangle below = new Rectangle (0, node_bottom, ViewportRectangle.Width,
2024                                         ViewportRectangle.Height - node_bottom);
2025
2026                         int amount = count_to_next * ActualItemHeight;
2027
2028                         if (amount > 0)
2029                                 XplatUI.ScrollWindow (Handle, below, 0, amount, false);
2030
2031                         if (show_plus_minus) {
2032                                 Invalidate (new Rectangle (0, node.GetY (), Width, ActualItemHeight));
2033                         }
2034                 }
2035
2036                 internal void CollapseBelow (TreeNode node, int count_to_next)
2037                 {
2038                         if (update_stack > 0) {
2039                                 update_needed = true;
2040                                 return;
2041                         }
2042
2043                         Rectangle below = new Rectangle (0, node.Bounds.Bottom, ViewportRectangle.Width,
2044                                         ViewportRectangle.Height - node.Bounds.Bottom);
2045
2046                         int amount = count_to_next * ActualItemHeight;
2047
2048                         if (amount > 0)
2049                                 XplatUI.ScrollWindow (Handle, below, 0, -amount, false);
2050
2051                         if (show_plus_minus) {
2052                                 Invalidate (new Rectangle (0, node.GetY (), Width, ActualItemHeight));
2053                         }
2054                 }
2055
2056                 private void MouseWheelHandler(object sender, MouseEventArgs e) {
2057
2058                         if (vbar == null || !vbar.is_visible) {
2059                                 return;
2060                         }
2061
2062                         if (e.Delta < 0) {
2063                                 vbar.Value = Math.Min(vbar.Value + SystemInformation.MouseWheelScrollLines, vbar.Maximum - VisibleCount + 1);
2064                         } else {
2065                                 vbar.Value = Math.Max(0, vbar.Value - SystemInformation.MouseWheelScrollLines);
2066                         }
2067                 }
2068
2069                 private void VisibleChangedHandler (object sender, EventArgs e)
2070                 {
2071                         if (Visible) {
2072                                 UpdateScrollBars (false);
2073                         }
2074                 }
2075
2076                 private void FontChangedHandler (object sender, EventArgs e)
2077                 {
2078                         if (IsHandleCreated) {
2079                                 TreeNode top = TopNode;
2080                                 InvalidateNodeWidthRecursive (root_node);
2081
2082                                 SetTop (top);
2083                         }
2084                 }
2085
2086                 private void InvalidateNodeWidthRecursive (TreeNode node)
2087                 {
2088                         node.InvalidateWidth ();
2089                         foreach (TreeNode child in node.Nodes) {
2090                                 InvalidateNodeWidthRecursive (child);
2091                         }
2092                 }
2093
2094                 private void GotFocusHandler (object sender, EventArgs e)
2095                 {
2096                         if (selected_node == null) {
2097                                 if (pre_selected_node != null) {
2098                                         SelectedNode = pre_selected_node;
2099                                         return;
2100                                 }
2101                                 
2102                                 SelectedNode = TopNode;
2103                         
2104                         } else if (selected_node != null)
2105                                 UpdateNode (selected_node);
2106                 }
2107
2108                 private void LostFocusHandler (object sender, EventArgs e)
2109                 {
2110                         UpdateNode (SelectedNode);
2111                 }
2112
2113                 private void MouseDownHandler (object sender, MouseEventArgs e)
2114                 {
2115                         if (e.Button == MouseButtons.Right)
2116                                 Focus ();
2117
2118                         TreeNode node = GetNodeAt (e.Y);
2119                         if (node == null)
2120                                 return;
2121
2122 #if NET_2_0
2123                         mouse_click_node = node;
2124 #endif
2125
2126                         if (show_plus_minus && IsPlusMinusArea (node, e.X)) {
2127                                 node.Toggle ();
2128                                 return;
2129                         } else if (checkboxes && IsCheckboxArea (node, e.X)) {
2130                                 node.check_reason = TreeViewAction.ByMouse;
2131                                 node.Checked = !node.Checked;
2132                                 UpdateNode(node);
2133                                 return;
2134                         } else if (IsSelectableArea (node, e.X) || full_row_select) {
2135                                 TreeNode old_highlighted = highlighted_node;
2136                                 highlighted_node = node;
2137                                 if (label_edit && e.Clicks == 1 && highlighted_node == old_highlighted) {
2138                                         BeginEdit (node);
2139                                 } else if (highlighted_node != focused_node) {
2140                                         Size ds = SystemInformation.DragSize;
2141                                         mouse_rect.X = e.X - ds.Width;
2142                                         mouse_rect.Y = e.Y - ds.Height;
2143                                         mouse_rect.Width = ds.Width * 2;
2144                                         mouse_rect.Height = ds.Height * 2;
2145
2146                                         select_mmove = true;
2147                                 }
2148
2149                                 Invalidate (highlighted_node.Bounds);
2150                                 if (old_highlighted != null)
2151                                         Invalidate (Bloat (old_highlighted.Bounds));
2152                         } 
2153                 }
2154
2155                 private void MouseUpHandler (object sender, MouseEventArgs e) {
2156 #if NET_2_0
2157                         TreeNode node = GetNodeAt (e.Y);
2158                         
2159                         if (node != null && node == mouse_click_node) {
2160                                 if (e.Clicks == 2)
2161                                         OnNodeMouseDoubleClick (new TreeNodeMouseClickEventArgs (node, e.Button, e.Clicks, e.X, e.Y));
2162                                 else
2163                                         OnNodeMouseClick (new TreeNodeMouseClickEventArgs (node, e.Button, e.Clicks, e.X, e.Y));
2164                         }
2165                         
2166                         mouse_click_node = null;
2167 #endif
2168
2169                         drag_begin_x = -1;
2170                         drag_begin_y = -1;
2171
2172                         if (!select_mmove)
2173                                 return;
2174
2175                         select_mmove = false;
2176
2177                         if (e.Button == MouseButtons.Right && selected_node != null) {
2178                                 Invalidate (highlighted_node.Bounds);
2179                                 highlighted_node = selected_node;
2180                                 Invalidate (selected_node.Bounds);
2181                                 return;
2182                         }
2183
2184                         TreeViewCancelEventArgs ce = new TreeViewCancelEventArgs (highlighted_node, false, TreeViewAction.ByMouse);
2185                         OnBeforeSelect (ce);
2186
2187                         Rectangle invalid;
2188                         if (!ce.Cancel) {
2189                                 TreeNode prev_focused_node = focused_node;
2190                                 TreeNode prev_highlighted_node = highlighted_node;
2191                                 
2192                                 selected_node = highlighted_node;
2193                                 focused_node = highlighted_node;
2194                                 OnAfterSelect (new TreeViewEventArgs (selected_node, TreeViewAction.ByMouse));
2195
2196                                 if (prev_focused_node != null) {
2197                                         invalid = Rectangle.Union (Bloat (prev_focused_node.Bounds),
2198                                                         Bloat (prev_highlighted_node.Bounds));
2199                                 } else {
2200                                         invalid = Bloat (prev_highlighted_node.Bounds);
2201                                 }
2202
2203                                 if (full_row_select || draw_mode != TreeViewDrawMode.Normal) {
2204                                         invalid.X = 0;
2205                                         invalid.Width = ViewportRectangle.Width;
2206                                 }
2207
2208                                 Invalidate (invalid);
2209                         } else {
2210                                 highlighted_node = focused_node;
2211                                 selected_node = focused_node;
2212                         }
2213                 }
2214
2215                 private void MouseMoveHandler (object sender, MouseEventArgs e) {
2216 #if NET_2_0
2217                         // XXX - This should use HitTest and only fire when we are over
2218                         // the important parts of a node, not things like gridlines or
2219                         // whitespace
2220                         TreeNode tn = GetNodeAt (e.Location);
2221                         
2222                         if (tn != tooltip_currently_showing)
2223                                 MouseLeftItem (tooltip_currently_showing);
2224                                 
2225                         if (tn != null && tn != tooltip_currently_showing)
2226                                 MouseEnteredItem (tn);
2227 #endif
2228                         
2229                         if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right) {
2230                                 if (drag_begin_x == -1 && drag_begin_y == -1) {
2231                                         drag_begin_x = e.X;
2232                                         drag_begin_y = e.Y;
2233                                 } else {
2234                                         double rise = Math.Pow (drag_begin_x - e.X, 2);
2235                                         double run = Math.Pow (drag_begin_y - e.Y, 2);
2236                                         double move = Math.Sqrt (rise + run);
2237                                         if (move > 3) {
2238                                                 TreeNode drag = GetNodeAtUseX (e.X, e.Y);
2239                                                 
2240                                                 if (drag != null) {
2241                                                         OnItemDrag (new ItemDragEventArgs (e.Button, drag));
2242                                                 }
2243                                                 drag_begin_x = -1;
2244                                                 drag_begin_y = -1;
2245                                         }
2246                                 }
2247                                 
2248                         }
2249
2250                         // If there is enough movement before the mouse comes up,
2251                         // selection is reverted back to the originally selected node
2252                         if (!select_mmove || mouse_rect.Contains (e.X, e.Y))
2253                                 return;
2254
2255                         Invalidate (highlighted_node.Bounds);
2256                         Invalidate (selected_node.Bounds);
2257                         Invalidate (focused_node.Bounds);
2258
2259                         highlighted_node = selected_node;
2260                         focused_node = selected_node;
2261
2262                         select_mmove = false;
2263                 }
2264
2265                 private void DoubleClickHandler (object sender, MouseEventArgs e) {
2266                         TreeNode node = GetNodeAtUseX (e.X,e.Y);
2267                         if(node != null) {
2268                                 node.Toggle();
2269                         }
2270                 }
2271
2272                 
2273                 private bool RectsIntersect (Rectangle r, int left, int top, int width, int height)
2274                 {
2275                         return !((r.Left > left + width) || (r.Right < left) ||
2276                                         (r.Top > top + height) || (r.Bottom < top));
2277                 }
2278
2279 #if NET_2_0
2280                 // Return true if message was handled, false to send it to base
2281                 private bool WmContextMenu (ref Message m)
2282                 {
2283                         Point pt;
2284                         TreeNode tn;
2285                         
2286                         pt = new Point (LowOrder ((int)m.LParam.ToInt32 ()), HighOrder ((int)m.LParam.ToInt32 ()));
2287
2288                         // This means it's a keyboard menu request
2289                         if (pt.X == -1 || pt.Y == -1) {
2290                                 tn = SelectedNode;
2291                                 
2292                                 if (tn == null)
2293                                         return false;
2294                                 
2295                                 pt = new Point (tn.Bounds.Left, tn.Bounds.Top + (tn.Bounds.Height / 2));
2296                         } else {
2297                                 pt = PointToClient (pt);
2298                                 
2299                                 tn = GetNodeAt (pt);
2300
2301                                 if (tn == null)
2302                                         return false;
2303                         }
2304                         
2305                         // At this point, we have a valid TreeNode
2306                         if (tn.ContextMenu != null) {
2307                                 tn.ContextMenu.Show (this, pt);
2308                                 return true;
2309                         } else if (tn.ContextMenuStrip != null) {
2310                                 tn.ContextMenuStrip.Show (this, pt);
2311                                 return true;
2312                         }
2313                         
2314                         // The node we found did not have its own menu, let the parent try to display its menu
2315                         return false;
2316                 }
2317 #endif
2318
2319                 #region Stuff for ToolTips
2320 #if NET_2_0
2321                 private void MouseEnteredItem (TreeNode item)
2322                 {
2323                         tooltip_currently_showing = item;
2324                         
2325                         if (!is_hovering)
2326                                 return;
2327
2328                         if (ShowNodeToolTips && !string.IsNullOrEmpty (tooltip_currently_showing.ToolTipText))
2329                                 ToolTipWindow.Present (this, tooltip_currently_showing.ToolTipText);
2330
2331                         OnNodeMouseHover (new TreeNodeMouseHoverEventArgs (tooltip_currently_showing));
2332                 }
2333
2334                 private void MouseLeftItem (TreeNode item)
2335                 {
2336                         ToolTipWindow.Hide (this);
2337                         tooltip_currently_showing = null;
2338                 }
2339
2340                 private ToolTip ToolTipWindow {
2341                         get {
2342                                 if (tooltip_window == null)
2343                                         tooltip_window = new ToolTip ();
2344
2345                                 return tooltip_window;
2346                         }
2347                 }
2348 #endif
2349                 #endregion
2350                 
2351                 #endregion      // Internal & Private Methods and Properties
2352
2353                 #region Events
2354                 static object ItemDragEvent = new object ();
2355                 static object AfterCheckEvent = new object ();
2356                 static object AfterCollapseEvent = new object ();
2357                 static object AfterExpandEvent = new object ();
2358                 static object AfterLabelEditEvent = new object ();
2359                 static object AfterSelectEvent = new object ();
2360                 static object BeforeCheckEvent = new object ();
2361                 static object BeforeCollapseEvent = new object ();
2362                 static object BeforeExpandEvent = new object ();
2363                 static object BeforeLabelEditEvent = new object ();
2364                 static object BeforeSelectEvent = new object ();
2365 #if NET_2_0
2366                 static object DrawNodeEvent = new object ();
2367                 static object NodeMouseClickEvent = new object ();
2368                 static object NodeMouseDoubleClickEvent = new object();
2369                 static object NodeMouseHoverEvent = new object ();
2370                 static object RightToLeftLayoutChangedEvent = new object ();
2371 #endif
2372
2373                 public event ItemDragEventHandler ItemDrag {
2374                         add { Events.AddHandler (ItemDragEvent, value); }
2375                         remove { Events.RemoveHandler (ItemDragEvent, value); }
2376                 }
2377
2378                 public event TreeViewEventHandler AfterCheck {
2379                         add { Events.AddHandler (AfterCheckEvent, value); }
2380                         remove { Events.RemoveHandler (AfterCheckEvent, value); }
2381                 }
2382
2383                 public event TreeViewEventHandler AfterCollapse {
2384                         add { Events.AddHandler (AfterCollapseEvent, value); }
2385                         remove { Events.RemoveHandler (AfterCollapseEvent, value); }
2386                 }
2387
2388                 public event TreeViewEventHandler AfterExpand {
2389                         add { Events.AddHandler (AfterExpandEvent, value); }
2390                         remove { Events.RemoveHandler (AfterExpandEvent, value); }
2391                 }
2392
2393                 public event NodeLabelEditEventHandler AfterLabelEdit {
2394                         add { Events.AddHandler (AfterLabelEditEvent, value); }
2395                         remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
2396                 }
2397
2398                 public event TreeViewEventHandler AfterSelect {
2399                         add { Events.AddHandler (AfterSelectEvent, value); }
2400                         remove { Events.RemoveHandler (AfterSelectEvent, value); }
2401                 }
2402
2403                 public event TreeViewCancelEventHandler BeforeCheck {
2404                         add { Events.AddHandler (BeforeCheckEvent, value); }
2405                         remove { Events.RemoveHandler (BeforeCheckEvent, value); }
2406                 }
2407
2408                 public event TreeViewCancelEventHandler BeforeCollapse {
2409                         add { Events.AddHandler (BeforeCollapseEvent, value); }
2410                         remove { Events.RemoveHandler (BeforeCollapseEvent, value); }
2411                 }
2412
2413                 public event TreeViewCancelEventHandler BeforeExpand {
2414                         add { Events.AddHandler (BeforeExpandEvent, value); }
2415                         remove { Events.RemoveHandler (BeforeExpandEvent, value); }
2416                 }
2417
2418                 public event NodeLabelEditEventHandler BeforeLabelEdit {
2419                         add { Events.AddHandler (BeforeLabelEditEvent, value); }
2420                         remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
2421                 }
2422
2423                 public event TreeViewCancelEventHandler BeforeSelect {
2424                         add { Events.AddHandler (BeforeSelectEvent, value); }
2425                         remove { Events.RemoveHandler (BeforeSelectEvent, value); }
2426                 }
2427
2428 #if NET_2_0
2429                 public event DrawTreeNodeEventHandler DrawNode {
2430                         add { Events.AddHandler (DrawNodeEvent, value); }
2431                         remove { Events.RemoveHandler (DrawNodeEvent, value); }
2432                 }
2433
2434                 public event TreeNodeMouseClickEventHandler NodeMouseClick {
2435                         add { Events.AddHandler (NodeMouseClickEvent, value); }
2436                         remove { Events.RemoveHandler (NodeMouseClickEvent, value); }
2437                 }
2438
2439
2440                 public event TreeNodeMouseClickEventHandler NodeMouseDoubleClick {
2441                         add { Events.AddHandler (NodeMouseDoubleClickEvent, value); }
2442                         remove { Events.RemoveHandler (NodeMouseDoubleClickEvent, value); }
2443                 }
2444                 
2445                 public event TreeNodeMouseHoverEventHandler NodeMouseHover {
2446                         add { Events.AddHandler (NodeMouseHoverEvent, value); }
2447                         remove { Events.RemoveHandler (NodeMouseHoverEvent, value); }
2448                 }
2449                 
2450                 public event EventHandler RightToLeftLayoutChanged {
2451                         add { Events.AddHandler (RightToLeftLayoutChangedEvent, value); }
2452                         remove { Events.RemoveHandler (RightToLeftLayoutChangedEvent, value); }
2453                 }
2454 #endif
2455
2456                 [Browsable (false)]
2457                 [EditorBrowsable (EditorBrowsableState.Never)]  
2458                 public new event EventHandler BackgroundImageChanged {
2459                         add { base.BackgroundImageChanged += value; }
2460                         remove { base.BackgroundImageChanged -= value; }
2461                 }
2462
2463 #if NET_2_0
2464                 [Browsable (false)]
2465                 [EditorBrowsable (EditorBrowsableState.Never)]
2466                 public new event EventHandler BackgroundImageLayoutChanged {
2467                         add { base.BackgroundImageLayoutChanged += value; }
2468                         remove { base.BackgroundImageLayoutChanged -= value; }
2469                 }
2470
2471                 [Browsable (false)]
2472                 [EditorBrowsable (EditorBrowsableState.Never)]
2473                 public new event EventHandler PaddingChanged {
2474                         add { base.PaddingChanged += value; }
2475                         remove { base.PaddingChanged -= value; }
2476                 }
2477 #endif
2478
2479                 [EditorBrowsable (EditorBrowsableState.Never)]  
2480                 [Browsable (false)]
2481                 public new event PaintEventHandler Paint {
2482                         add { base.Paint += value; }
2483                         remove { base.Paint -= value; }
2484                 }
2485
2486                 [EditorBrowsable (EditorBrowsableState.Never)]  
2487                 [Browsable (false)]
2488                 public new event EventHandler TextChanged {
2489                         add { base.TextChanged += value; }
2490                         remove { base.TextChanged -= value; }
2491                 }
2492                 #endregion      // Events
2493         }
2494 }
2495
2496