f097064523d4f4ecfe8fcb150c3322e964e7b1f2
[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                 private TreeNode selected_node;
54                 private TreeNode pre_selected_node;
55                 private TreeNode focused_node;
56                 private 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 = 0;
107                 private int drag_begin_y = 0;
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                         InternalBorderStyle = BorderStyle.Fixed3D;
121                         base.background_color = ThemeEngine.Current.ColorWindow;
122                         base.foreground_color = ThemeEngine.Current.ColorWindowText;
123
124                         root_node = new TreeNode (this);
125                         root_node.Text = "ROOT NODE";
126                         nodes = new TreeNodeCollection (root_node);
127                         root_node.SetNodes (nodes);
128
129                         MouseDown += new MouseEventHandler (MouseDownHandler);
130                         MouseUp += new MouseEventHandler(MouseUpHandler);
131                         MouseMove += new MouseEventHandler(MouseMoveHandler);
132                         SizeChanged += new EventHandler (SizeChangedHandler);
133                         FontChanged += new EventHandler (FontChangedHandler);
134                         LostFocus += new EventHandler (LostFocusHandler);
135                         GotFocus += new EventHandler (GotFocusHandler);
136                         MouseWheel += new MouseEventHandler(MouseWheelHandler);
137                         VisibleChanged += new EventHandler (VisibleChangedHandler);
138
139                         SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
140 #if NET_2_0
141                                 | ControlStyles.UseTextForAccessibility
142 #endif
143                                 , false);
144
145                         string_format = new StringFormat ();
146                         string_format.LineAlignment = StringAlignment.Center;
147                         string_format.Alignment = StringAlignment.Center;
148
149                         vbar = new ImplicitVScrollBar ();
150                         hbar = new ImplicitHScrollBar ();
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) {
768                                 vbar.Value = vbar.Maximum - VisibleCount + 1;
769                         } else {
770                                 RecalculateVisibleOrder (root_node);
771                                 UpdateScrollBars (true);
772                                 SetTop (Nodes [Nodes.Count - 1]);
773                         }
774                 }
775
776                 
777                 public void CollapseAll ()
778                 {
779                         TreeNode walk = TopNode;
780                         
781                         while (walk.parent != root_node)
782                                 walk = walk.parent;
783
784                         BeginUpdate ();
785                         root_node.CollapseAll ();
786                         EndUpdate ();
787
788                         SetTop (walk);
789                 }
790
791                 public TreeNode GetNodeAt (Point pt) {
792                         return GetNodeAt (pt.Y);
793                 }
794
795                 public TreeNode GetNodeAt (int x, int y)
796                 {
797                         return GetNodeAt (y);
798                 }
799
800                 private TreeNode GetNodeAtUseX (int x, int y) {
801                         TreeNode node = GetNodeAt (y);
802                         if (node == null || !(IsTextArea (node, x) || full_row_select))
803                                 return null;
804                         return node;
805                                         
806                 }
807
808                 public int GetNodeCount (bool include_subtrees) {
809                         return root_node.GetNodeCount (include_subtrees);
810                 }
811
812 #if NET_2_0
813                 public TreeViewHitTestInfo HitTest (Point pt)
814                 {
815                         return HitTest (pt.X, pt.Y);
816                 }
817                 
818                 public TreeViewHitTestInfo HitTest (int x, int y)
819                 {
820                         TreeNode n = GetNodeAt (y);
821                         
822                         if (n == null)
823                                 return new TreeViewHitTestInfo (null, TreeViewHitTestLocations.None);
824                                 
825                         if (IsTextArea (n, x))
826                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.Label);
827                         else if (IsPlusMinusArea (n, x))
828                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.PlusMinus);
829                         else if (checkboxes && IsCheckboxArea (n, x))
830                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.StateImage);
831                         else if (x > n.Bounds.Right)
832                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.RightOfLabel);
833                         else if (IsImage (n, x))
834                                 return new TreeViewHitTestInfo (n, TreeViewHitTestLocations.Image);
835                         else
836                                 return new TreeViewHitTestInfo (null, TreeViewHitTestLocations.Indent);
837                 }
838 #endif
839
840                 public override string ToString () {
841                         int count = Nodes.Count;
842                         if (count <= 0)
843                                 return String.Concat (base.ToString (), "Node Count: 0");
844                         return String.Concat (base.ToString (), "Node Count: ", count, " Nodes[0]: ", Nodes [0]);
845                                                 
846                 }
847
848                 #endregion      // Public Instance Methods
849
850                 #region Protected Instance Methods
851                 protected override void CreateHandle () {
852                         base.CreateHandle ();
853                         RecalculateVisibleOrder (root_node);
854                         UpdateScrollBars (false);
855
856                         if (pre_selected_node != null)
857                                 SelectedNode = pre_selected_node;
858                 }
859
860                 protected override void Dispose (bool disposing) {
861                         if (disposing)
862                                 image_list = null;
863
864                         base.Dispose (disposing);
865                 }
866
867                 protected OwnerDrawPropertyBag GetItemRenderStyles (TreeNode node, int state) {
868                         return node.prop_bag;
869                 }
870
871                 protected override bool IsInputKey (Keys key_data)
872                 {
873                         if (IsHandleCreated && (key_data & Keys.Alt) == 0) {
874                                 switch (key_data & Keys.KeyCode) {
875                                 case Keys.Left:
876                                 case Keys.Up:
877                                 case Keys.Right:
878                                 case Keys.Down:
879                                         return true;
880                                 case Keys.Enter:
881                                 case Keys.Escape:
882                                 case Keys.Prior:
883                                 case Keys.Next:
884                                 case Keys.End:
885                                 case Keys.Home:
886                                         if (edit_node != null)
887                                                 return true;
888                                                 
889                                         break;
890                                 }
891                         }
892                         return base.IsInputKey (key_data);
893                 }
894
895                 protected override void OnKeyDown (KeyEventArgs e)
896                 {
897                         OpenTreeNodeEnumerator ne;
898
899                         switch (e.KeyData & Keys.KeyCode) {
900                         case Keys.Add:
901                                 if (selected_node != null && selected_node.IsExpanded)
902                                         selected_node.Expand ();
903                                 break;
904                         case Keys.Subtract:
905                                 if (selected_node != null && selected_node.IsExpanded)
906                                         selected_node.Collapse ();
907                                 break;
908                         case Keys.Left:
909                                 if (selected_node != null) {
910                                         if (selected_node.IsExpanded)
911                                                 selected_node.Collapse ();
912                                         else {
913                                                 TreeNode parent = selected_node.Parent;
914                                                 if (parent != null) {
915                                                         selection_action = TreeViewAction.ByKeyboard;
916                                                         SelectedNode = parent;
917                                                 }
918                                         }
919                                 }
920                                 break;
921                         case Keys.Right:
922                                 if (selected_node != null) {
923                                         if (!selected_node.IsExpanded)
924                                                 selected_node.Expand ();
925                                         else {
926                                                 TreeNode child = selected_node.FirstNode;
927                                                 if (child != null)
928                                                         SelectedNode = child;
929                                         }
930                                 }
931                                 break;
932                         case Keys.Up:
933                                 if (selected_node != null) {
934                                         ne = new OpenTreeNodeEnumerator (selected_node);
935                                         if (ne.MovePrevious () && ne.MovePrevious ()) {
936                                                 selection_action = TreeViewAction.ByKeyboard;
937                                                 SelectedNode = ne.CurrentNode;
938                                         }
939                                 }
940                                 break;
941                         case Keys.Down:
942                                 if (selected_node != null) {
943                                         ne = new OpenTreeNodeEnumerator (selected_node);
944                                         if (ne.MoveNext () && ne.MoveNext ()) {
945                                                 selection_action = TreeViewAction.ByKeyboard;
946                                                 SelectedNode = ne.CurrentNode;
947                                         }
948                                 }
949                                 break;
950                         case Keys.Home:
951                                 if (root_node.Nodes.Count > 0) {
952                                         ne = new OpenTreeNodeEnumerator (root_node.Nodes [0]);
953                                         if (ne.MoveNext ()) {
954                                                 selection_action = TreeViewAction.ByKeyboard;
955                                                 SelectedNode = ne.CurrentNode;
956                                         }
957                                 }
958                                 break;
959                         case Keys.End:
960                                 if (root_node.Nodes.Count > 0) {
961                                         ne = new OpenTreeNodeEnumerator (root_node.Nodes [0]);
962                                         while (ne.MoveNext ())
963                                         { }
964                                         selection_action = TreeViewAction.ByKeyboard;
965                                         SelectedNode = ne.CurrentNode;
966                                 }
967                                 break;
968                         case Keys.PageDown:
969                                 if (selected_node != null) {
970                                         ne = new OpenTreeNodeEnumerator (selected_node);
971                                         int move = VisibleCount;
972                                         for (int i = 0; i < move && ne.MoveNext (); i++) {
973                                                 
974                                         }
975                                         selection_action = TreeViewAction.ByKeyboard;
976                                         SelectedNode = ne.CurrentNode;
977                                 }
978                                 break;
979                         case Keys.PageUp:
980                                 if (selected_node != null) {
981                                         ne = new OpenTreeNodeEnumerator (selected_node);
982                                         int move = VisibleCount;
983                                         for (int i = 0; i < move && ne.MovePrevious (); i++)
984                                         { }
985                                         selection_action = TreeViewAction.ByKeyboard;
986                                         SelectedNode = ne.CurrentNode;
987                                 }
988                                 break;
989                         case Keys.Multiply:
990                                 if (selected_node != null)
991                                         selected_node.ExpandAll ();
992                                 break;
993                         }
994                         base.OnKeyDown (e);
995
996                         if (!e.Handled && checkboxes &&
997                              selected_node != null &&
998                             (e.KeyData & Keys.KeyCode) == Keys.Space) {
999                                 selected_node.check_reason = TreeViewAction.ByKeyboard;
1000                                 selected_node.Checked = !selected_node.Checked;         
1001                                 e.Handled = true;
1002                         }
1003                 }
1004
1005                 protected override void OnKeyPress (KeyPressEventArgs e)
1006                 {
1007                         base.OnKeyPress (e);
1008                         if (e.KeyChar == ' ')
1009                                 e.Handled = true;
1010                 }
1011
1012                 protected override void OnKeyUp (KeyEventArgs e)
1013                 {
1014                         base.OnKeyUp (e);
1015                         if ((e.KeyData & Keys.KeyCode) == Keys.Space)
1016                                 e.Handled = true;
1017                 }
1018
1019 #if NET_2_0
1020                 protected override void OnMouseHover (EventArgs e)
1021                 {
1022                         base.OnMouseHover (e);
1023                         
1024                         is_hovering = true;
1025
1026                         TreeNode tn = GetNodeAt (PointToClient (MousePosition));
1027
1028                         if (tn != null)
1029                                 MouseEnteredItem (tn);
1030                 }
1031
1032                 protected override void OnMouseLeave (EventArgs e)
1033                 {
1034                         base.OnMouseLeave (e);
1035                         
1036                         is_hovering = false;
1037                         
1038                         if (tooltip_currently_showing != null)
1039                                 MouseLeftItem (tooltip_currently_showing);
1040                 }
1041                 
1042                 protected virtual void OnNodeMouseClick (TreeNodeMouseClickEventArgs e)
1043                 {
1044                         TreeNodeMouseClickEventHandler eh = (TreeNodeMouseClickEventHandler)(Events[NodeMouseClickEvent]);
1045                         if (eh != null)
1046                                 eh (this, e);
1047                 }
1048
1049                 protected virtual void OnNodeMouseDoubleClick (TreeNodeMouseClickEventArgs e)
1050                 {
1051                         TreeNodeMouseClickEventHandler eh = (TreeNodeMouseClickEventHandler)(Events[NodeMouseDoubleClickEvent]);
1052                         if (eh != null)
1053                                 eh (this, e);
1054                 }
1055                 
1056                 protected virtual void OnNodeMouseHover (TreeNodeMouseHoverEventArgs e)
1057                 {
1058                         TreeNodeMouseHoverEventHandler eh = (TreeNodeMouseHoverEventHandler)(Events[NodeMouseHoverEvent]);
1059                         if (eh != null)
1060                                 eh (this, e);
1061                 }
1062 #endif
1063
1064                 protected virtual void OnItemDrag (ItemDragEventArgs e)
1065                 {
1066                         ItemDragEventHandler eh = (ItemDragEventHandler)(Events [ItemDragEvent]);
1067                         if (eh != null)
1068                                 eh (this, e);
1069                 }
1070
1071 #if NET_2_0
1072                 protected virtual void OnDrawNode(DrawTreeNodeEventArgs e) {
1073                         DrawTreeNodeEventHandler eh = (DrawTreeNodeEventHandler)(Events[DrawNodeEvent]);
1074                         if (eh != null)
1075                                 eh(this, e);
1076                 }
1077                 
1078                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1079                 protected virtual void OnRightToLeftLayoutChanged (EventArgs e) {
1080                         EventHandler eh = (EventHandler)(Events[RightToLeftLayoutChangedEvent]);
1081                         if (eh != null)
1082                                 eh (this, e);
1083                 }
1084 #endif
1085
1086                 protected internal virtual void OnAfterCheck (TreeViewEventArgs e) {
1087                         TreeViewEventHandler eh = (TreeViewEventHandler)(Events [AfterCheckEvent]);
1088                         if (eh != null)
1089                                 eh (this, e);
1090                 }
1091
1092                 protected internal virtual void OnAfterCollapse (TreeViewEventArgs e) {
1093                         TreeViewEventHandler eh = (TreeViewEventHandler)(Events [AfterCollapseEvent]);
1094                         if (eh != null)
1095                                 eh (this, e);
1096                 }
1097
1098                 protected internal virtual void OnAfterExpand (TreeViewEventArgs e) {
1099                         TreeViewEventHandler eh = (TreeViewEventHandler)(Events [AfterExpandEvent]);
1100                         if (eh != null)
1101                                 eh (this, e);
1102                 }
1103
1104                 protected virtual void OnAfterLabelEdit (NodeLabelEditEventArgs e) {
1105                         NodeLabelEditEventHandler eh = (NodeLabelEditEventHandler)(Events [AfterLabelEditEvent]);
1106                         if (eh != null)
1107                                 eh (this, e);
1108                 }
1109
1110                 protected virtual void OnAfterSelect (TreeViewEventArgs e) {
1111                         TreeViewEventHandler eh = (TreeViewEventHandler)(Events [AfterSelectEvent]);
1112                         if (eh != null)
1113                                 eh (this, e);
1114                 }
1115
1116                 protected internal virtual void OnBeforeCheck (TreeViewCancelEventArgs e) {
1117                         TreeViewCancelEventHandler eh = (TreeViewCancelEventHandler)(Events [BeforeCheckEvent]);
1118                         if (eh != null)
1119                                 eh (this, e);
1120                 }
1121
1122                 protected internal virtual void OnBeforeCollapse (TreeViewCancelEventArgs e) {
1123                         TreeViewCancelEventHandler eh = (TreeViewCancelEventHandler)(Events [BeforeCollapseEvent]);
1124                         if (eh != null)
1125                                 eh (this, e);
1126                 }
1127
1128                 protected internal virtual void OnBeforeExpand (TreeViewCancelEventArgs e) {
1129                         TreeViewCancelEventHandler eh = (TreeViewCancelEventHandler)(Events [BeforeExpandEvent]);
1130                         if (eh != null)
1131                                 eh (this, e);
1132                 }
1133
1134                 protected virtual void OnBeforeLabelEdit (NodeLabelEditEventArgs e) {
1135                         NodeLabelEditEventHandler eh = (NodeLabelEditEventHandler)(Events [BeforeLabelEditEvent]);
1136                         if (eh != null)
1137                                 eh (this, e);
1138                 }
1139
1140                 protected virtual void OnBeforeSelect (TreeViewCancelEventArgs e) {
1141                         TreeViewCancelEventHandler eh = (TreeViewCancelEventHandler)(Events [BeforeSelectEvent]);
1142                         if (eh != null)
1143                                 eh (this, e);
1144                 }
1145
1146                 protected override void OnHandleCreated (EventArgs e) {
1147                         base.OnHandleCreated (e);
1148                 }
1149
1150                 protected override void OnHandleDestroyed (EventArgs e) {
1151                         base.OnHandleDestroyed (e);
1152                 }
1153
1154                 protected override void WndProc(ref Message m) {
1155                         switch ((Msg) m.Msg) {
1156
1157                         case Msg.WM_LBUTTONDBLCLK:
1158                                 int val = m.LParam.ToInt32();
1159                                 DoubleClickHandler (null, new
1160                                                 MouseEventArgs (MouseButtons.Left,
1161                                                                 2, val & 0xffff,
1162                                                                 (val>>16) & 0xffff, 0));
1163                                         break;
1164 #if NET_2_0
1165                                 case Msg.WM_CONTEXTMENU:
1166                                         if (WmContextMenu (ref m))
1167                                                 return;
1168                                                 
1169                                         break;
1170 #endif
1171                         }
1172                         base.WndProc (ref m);
1173                 }
1174
1175                 #endregion      // Protected Instance Methods
1176
1177                 #region Internal & Private Methods and Properties
1178                 internal IntPtr CreateNodeHandle ()
1179                 {
1180                         return (IntPtr) handle_count++;
1181                 }
1182
1183                 // According to MSDN docs, for these to be raised, 
1184                 // the click must occur over a TreeNode
1185                 internal override void HandleClick (int clicks, MouseEventArgs me)
1186                 {
1187                         if (GetNodeAt (me.Location) != null) {
1188                                 if ((clicks > 1) && GetStyle (ControlStyles.StandardDoubleClick)) {
1189 #if !NET_2_0
1190                                         OnDoubleClick(EventArgs.Empty);
1191                                 } else {
1192                                         OnClick(EventArgs.Empty);
1193 #else
1194                                         OnDoubleClick (me);
1195                                         OnMouseDoubleClick (me);
1196                                 } else {
1197                                         OnClick (me);
1198                                         OnMouseClick (me);
1199 #endif
1200                                 }
1201                         }
1202                 }
1203                 
1204                 internal override bool IsInputCharInternal (char charCode)
1205                 {
1206                         return true;
1207                 }
1208
1209                 internal TreeNode NodeFromHandle (IntPtr handle)
1210                 {
1211                         // This method is called rarely, so instead of maintaining a table
1212                         // we just walk the tree nodes to find the matching handle
1213                         return NodeFromHandleRecursive (root_node,  handle);
1214                 }
1215
1216                 private TreeNode NodeFromHandleRecursive (TreeNode node, IntPtr handle)
1217                 {
1218                         if (node.handle == handle)
1219                                 return node;
1220                         foreach (TreeNode child in node.Nodes) {
1221                                 TreeNode match = NodeFromHandleRecursive (child, handle);
1222                                 if (match != null)
1223                                         return match;
1224                         }
1225                         return null;
1226                 }
1227
1228                 internal Rectangle ViewportRectangle {
1229                         get {
1230                                 Rectangle res = ClientRectangle;
1231
1232                                 if (vbar != null && vbar.Visible)
1233                                         res.Width -= vbar.Width;
1234                                 if (hbar != null && hbar.Visible)
1235                                         res.Height -= hbar.Height;
1236                                 return res;
1237                         }
1238                 }
1239
1240                 private TreeNode GetNodeAt (int y)
1241                 {
1242                         if (nodes.Count <= 0)
1243                                 return null;
1244
1245                         OpenTreeNodeEnumerator o = new OpenTreeNodeEnumerator (TopNode);
1246                         int move = y / ActualItemHeight;
1247                         for (int i = -1; i < move; i++) {
1248                                 if (!o.MoveNext ())
1249                                         return null;
1250                         }
1251
1252                         return o.CurrentNode;
1253                 }
1254
1255                 private bool IsTextArea (TreeNode node, int x)
1256                 {
1257                         return node != null && node.Bounds.Left <= x && node.Bounds.Right >= x;
1258                 }
1259
1260                 private bool IsSelectableArea (TreeNode node, int x)
1261                 {
1262                         if (node == null)
1263                                 return false;
1264                         int l = node.Bounds.Left;
1265                         if (ImageList != null)
1266                                 l -= ImageList.ImageSize.Width;
1267                         return l <= x && node.Bounds.Right >= x;
1268                                 
1269                 }
1270
1271                 private bool IsPlusMinusArea (TreeNode node, int x)
1272                 {
1273                         if (node.Nodes.Count == 0 || (node.parent == root_node && !show_root_lines))
1274                                 return false;
1275
1276                         int l = node.Bounds.Left + 5;
1277
1278                         if (show_root_lines || node.Parent != null)
1279                                 l -= indent;
1280                         if (ImageList != null)
1281                                 l -= ImageList.ImageSize.Width + 3;
1282                         if (checkboxes)
1283                                 l -= 19;
1284                         return (x > l && x < l + 8);
1285                 }
1286
1287                 private bool IsCheckboxArea (TreeNode node, int x)
1288                 {
1289                         int l = CheckBoxLeft (node);
1290                         return (x > l && x < l + 10);
1291                 }
1292
1293                 private bool IsImage (TreeNode node, int x)
1294                 {
1295                         if (ImageList == null)
1296                                 return false;
1297                                 
1298                         int l = node.Bounds.Left;
1299
1300                         l -= ImageList.ImageSize.Width + 5;
1301                         
1302                         if (x >= l && x <= (l + ImageList.ImageSize.Width + 5))
1303                                 return true;
1304                                 
1305                         return false;
1306                 }
1307                 
1308                 private int CheckBoxLeft (TreeNode node)
1309                 {
1310                         int l = node.Bounds.Left + 5;
1311
1312                         if (show_root_lines || node.Parent != null)
1313                                 l -= indent;
1314                         if (ImageList != null)
1315                                 l -= ImageList.ImageSize.Width + 3;
1316
1317                         return l;
1318                 }
1319
1320                 internal void RecalculateVisibleOrder (TreeNode start)
1321                 {
1322                         if (update_stack > 0)
1323                                 return;
1324
1325                         int order;
1326                         if (start == null) {
1327                                 start = root_node;
1328                                 order = 0;
1329                         } else
1330                                 order = start.visible_order;
1331
1332                         
1333                         
1334                         OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (start);
1335                         while (walk.MoveNext ()) {
1336                                 walk.CurrentNode.visible_order = order;
1337                                 order++;
1338                         }
1339
1340                         max_visible_order = order;
1341                 }
1342
1343                 internal void SetTop (TreeNode node)
1344                 {
1345                         int order = 0;
1346                         if (node != null)
1347                                 order = Math.Max (0, node.visible_order - 1);
1348
1349                         if (!vbar.is_visible) {
1350                                 skipped_nodes = order;
1351                                 return;
1352                         }
1353
1354                         vbar.Value = Math.Min (order, vbar.Maximum - VisibleCount + 1);
1355                 }
1356
1357                 internal void SetBottom (TreeNode node)
1358                 {
1359                         if (!vbar.is_visible)
1360                                 return;
1361
1362                         OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (node);
1363
1364                         int bottom = ViewportRectangle.Bottom;
1365                         int offset = 0;
1366                         while (walk.MovePrevious ()) {
1367                                 if (walk.CurrentNode.Bounds.Bottom <= bottom)
1368                                         break;
1369                                 offset++;
1370                         }
1371
1372                         int nv = vbar.Value + offset;
1373                         if (vbar.Value + offset < vbar.Maximum) {
1374                                 vbar.Value = nv;
1375                         } else {
1376 #if DEBUG
1377                                 Console.Error.WriteLine ("setting bottom to value greater then maximum ({0}, {1})",
1378                                                 nv, vbar.Maximum);
1379 #endif
1380                         }
1381                                 
1382                 }
1383
1384                 internal void UpdateBelow (TreeNode node)
1385                 {
1386                         if (update_stack > 0) {
1387                                 update_needed = true;
1388                                 return;
1389                         }
1390
1391                         if (node == root_node) {
1392                                 Invalidate (ViewportRectangle);
1393                                 return;
1394                         }
1395                                 
1396                         // We need to update the current node so the plus/minus block gets update too
1397                         int top = Math.Max (node.Bounds.Top - 1, 0);
1398                         Rectangle invalid = new Rectangle (0, top,
1399                                         Width, Height - top);
1400                         Invalidate (invalid);
1401                 }
1402
1403                 internal void UpdateNode (TreeNode node)
1404                 {
1405                         if (node == null)
1406                                 return;
1407
1408                         if (update_stack > 0) {
1409                                 update_needed = true;
1410                                 return;
1411                         }
1412
1413                         if (node == root_node) {
1414                                 Invalidate ();
1415                                 return;
1416                         }
1417
1418                         Rectangle invalid = new Rectangle (0, node.Bounds.Top - 1, Width,
1419                                         node.Bounds.Height + 1);
1420                         Invalidate (invalid);
1421                 }
1422
1423                 internal void UpdateNodePlusMinus (TreeNode node)
1424                 {
1425                         if (update_stack > 0) {
1426                                 update_needed = true;
1427                                 return;
1428                         }
1429
1430                         int l = node.Bounds.Left + 5;
1431
1432                         if (show_root_lines || node.Parent != null)
1433                                 l -= indent;
1434                         if (ImageList != null)
1435                                 l -= ImageList.ImageSize.Width + 3;
1436                         if (checkboxes)
1437                                 l -= 19;
1438
1439                         Invalidate (new Rectangle (l, node.Bounds.Top, 8, node.Bounds.Height));
1440                 }
1441
1442                 internal override void OnPaintInternal (PaintEventArgs pe)
1443                 {
1444                         Draw (pe.ClipRectangle, pe.Graphics);
1445                 }
1446
1447                 internal void CreateDashPen ()
1448                 {
1449                         dash = new Pen (LineColor, 1);
1450                         dash.DashStyle = DashStyle.Dot;
1451                 }
1452
1453                 private void Draw (Rectangle clip, Graphics dc)
1454                 {
1455                         dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), clip);
1456
1457                         if (dash == null)
1458                                 CreateDashPen ();
1459
1460                         Rectangle viewport = ViewportRectangle;
1461                         Rectangle original_clip = clip;
1462                         if (clip.Bottom > viewport.Bottom)
1463                                 clip.Height = viewport.Bottom - clip.Top;
1464
1465                         OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (TopNode);
1466                         while (walk.MoveNext ()) {
1467                                 TreeNode current = walk.CurrentNode;
1468
1469                                 // Haven't gotten to visible nodes yet
1470                                 if (current.GetY () + ActualItemHeight < clip.Top)
1471                                         continue;
1472
1473                                 // Past the visible nodes
1474                                 if (current.GetY () > clip.Bottom)
1475                                         break;
1476
1477                                 DrawTreeNode (current, dc, clip);
1478                         }
1479
1480                         if (hbar.Visible && vbar.Visible) {
1481                                 Rectangle corner = new Rectangle (hbar.Right, vbar.Bottom, vbar.Width, hbar.Height);
1482                                 if (original_clip.IntersectsWith (corner))
1483                                         dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorControl),
1484                                                         corner);
1485                         }
1486                 }
1487
1488                 private void DrawNodePlusMinus (TreeNode node, Graphics dc, int x, int middle)
1489                 {
1490                         int height = ActualItemHeight - 2;
1491                         dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), (x + 4) - (height / 2), node.GetY() + 1, height, height);
1492                         
1493                         dc.DrawRectangle (SystemPens.ControlDarkDark, x, middle - 4, 8, 8);
1494
1495                         if (node.IsExpanded) {
1496                                 dc.DrawLine (SystemPens.ControlDarkDark, x + 2, middle, x + 6, middle); 
1497                         } else {
1498                                 dc.DrawLine (SystemPens.ControlDarkDark, x + 2, middle, x + 6, middle);
1499                                 dc.DrawLine (SystemPens.ControlDarkDark, x + 4, middle - 2, x + 4, middle + 2);
1500                         }
1501                 }
1502
1503 #if NET_2_0
1504                 private void DrawNodeState (TreeNode node, Graphics dc, int x, int y)
1505                 {
1506                         if (node.Checked) {
1507                                 if (StateImageList.Images[1] != null)
1508                                         dc.DrawImage (StateImageList.Images[1], new Rectangle (x, y, 16, 16));
1509                         } else {
1510                                 if (StateImageList.Images[0] != null)
1511                                         dc.DrawImage (StateImageList.Images[0], new Rectangle (x, y, 16, 16));
1512                         }
1513                 }
1514 #endif
1515
1516                 private void DrawNodeCheckBox (TreeNode node, Graphics dc, int x, int middle)
1517                 {
1518                         Pen pen = ThemeEngine.Current.ResPool.GetSizedPen(Color.Black, 2);
1519                                 dc.DrawRectangle (pen, x + 3, middle - 4, 11, 11);
1520
1521                         if (node.Checked) {
1522                                 Pen check_pen = ThemeEngine.Current.ResPool.GetPen(Color.Black);
1523                                 
1524                                 int check_size = 5;
1525                                 int lineWidth = 3;
1526                                 
1527                                 Rectangle rect = new Rectangle (x + 5, middle - 2, check_size, check_size);
1528                                 
1529                                 for (int i = 0; i < lineWidth; i++) {
1530                                         dc.DrawLine (check_pen, rect.Left + 1, rect.Top + lineWidth + i, rect.Left + 3, rect.Top + 5 + i);
1531                                         dc.DrawLine (check_pen, rect.Left + 3, rect.Top + 5 + i, rect.Left + 7, rect.Top + 1 + i);
1532                                 }
1533                         }
1534                 }
1535
1536                 private void DrawNodeLines (TreeNode node, Graphics dc, Rectangle clip, Pen dash, int x, int y, int middle)
1537                 {
1538                         int ladjust = 9;
1539                         int radjust = 0;
1540
1541                         if (node.nodes.Count > 0 && show_plus_minus)
1542                                 ladjust = 13;
1543                         if (checkboxes)
1544                                 radjust = 3;
1545
1546                         dc.DrawLine (dash, x - indent + ladjust, middle, x + radjust, middle);
1547
1548                         if (node.PrevNode != null || node.Parent != null) {
1549                                 ladjust = 9;
1550                                 dc.DrawLine (dash, x - indent + ladjust, node.Bounds.Top,
1551                                                 x - indent + ladjust, middle - (show_plus_minus && node.Nodes.Count > 0 ? 4 : 0));
1552                         }
1553
1554                         if (node.NextNode != null) {
1555                                 ladjust = 9;
1556                                 dc.DrawLine (dash, x - indent + ladjust, middle + (show_plus_minus && node.Nodes.Count > 0 ? 4 : 0),
1557                                                 x - indent + ladjust, node.Bounds.Bottom);
1558                                 
1559                         }
1560
1561                         ladjust = 0;
1562                         if (show_plus_minus)
1563                                 ladjust = 9;
1564                         TreeNode parent = node.Parent;
1565                         while (parent != null) {
1566                                 if (parent.NextNode != null) {
1567                                         int px = parent.GetLinesX () - indent + ladjust;
1568                                         dc.DrawLine (dash, px, node.Bounds.Top, px, node.Bounds.Bottom);
1569                                 }
1570                                 parent = parent.Parent;
1571                         }
1572                 }
1573
1574                 private void DrawNodeImage (TreeNode node, Graphics dc, Rectangle clip, int x, int y)
1575                 {
1576                         // Rectangle r = new Rectangle (x, y + 2, ImageList.ImageSize.Width, ImageList.ImageSize.Height);
1577
1578                         if (!RectsIntersect (clip, x, y, ImageList.ImageSize.Width, ImageList.ImageSize.Height))
1579                                 return;
1580
1581                         if (ImageList == null)
1582                                 return;
1583
1584                         int use_index = -1;
1585
1586                         if (!node.IsSelected) {
1587                                 if (node.ImageIndex > -1 && node.ImageIndex < ImageList.Images.Count) {
1588                                         use_index = node.ImageIndex;
1589                                 } else if (ImageIndex > -1 && ImageIndex < ImageList.Images.Count) {
1590                                         use_index = ImageIndex;
1591                                 }
1592                         } else {
1593                                 if (node.SelectedImageIndex > -1 && node.SelectedImageIndex < ImageList.Images.Count) {
1594                                         use_index = node.SelectedImageIndex;
1595                                 } else if (SelectedImageIndex > -1 && SelectedImageIndex < ImageList.Images.Count) {
1596                                         use_index = SelectedImageIndex;
1597                                 }
1598                         }
1599
1600 #if NET_2_0
1601
1602                         if (!node.IsSelected) {
1603                                 if (use_index == -1 && !String.IsNullOrEmpty (node.ImageKey)) {
1604                                         use_index = image_list.Images.IndexOfKey (node.ImageKey);
1605                                 }
1606
1607                                 if (use_index == -1 && !String.IsNullOrEmpty (ImageKey)) {
1608                                         use_index = image_list.Images.IndexOfKey (ImageKey);
1609                                 }
1610                         } else {
1611                                 if (use_index == -1 && !String.IsNullOrEmpty (node.SelectedImageKey)) {
1612                                         use_index = image_list.Images.IndexOfKey (node.SelectedImageKey);
1613                                 }
1614
1615                                 if (use_index == -1 && !String.IsNullOrEmpty (SelectedImageKey)) {
1616                                         use_index = image_list.Images.IndexOfKey (SelectedImageKey);
1617                                 }
1618                         }
1619 #endif
1620
1621                         if (use_index == -1 && ImageList.Images.Count > 0) {
1622                                 use_index = 0;
1623                         }
1624
1625                         if (use_index != -1) {
1626                                 ImageList.Draw (dc, x, y, ImageList.ImageSize.Width, 
1627                                                 ImageList.ImageSize.Height, use_index);
1628                         }
1629                 }
1630
1631                 private void LabelEditFinished (object sender, EventArgs e)
1632                 {
1633                         EndEdit (edit_node);
1634                 }
1635
1636                 internal void BeginEdit (TreeNode node)
1637                 {
1638                         if (edit_node != null)
1639                                 EndEdit (edit_node);
1640
1641                         if (edit_text_box == null) {
1642                                 edit_text_box = new LabelEditTextBox ();
1643                                 edit_text_box.BorderStyle = BorderStyle.FixedSingle;
1644                                 edit_text_box.Visible = false;
1645                                 edit_text_box.EditingCancelled += new EventHandler (LabelEditCancelled);
1646                                 edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
1647                                 edit_text_box.TextChanged += new EventHandler (LabelTextChanged);
1648                                 Controls.Add (edit_text_box);
1649                         }
1650
1651                         node.EnsureVisible ();
1652
1653                         edit_text_box.Bounds = node.Bounds;
1654                         edit_text_box.Text = node.Text;
1655                         edit_text_box.Visible = true;
1656                         edit_text_box.Focus ();
1657                         edit_text_box.SelectAll ();
1658
1659                         edit_args = new NodeLabelEditEventArgs (node);
1660                         OnBeforeLabelEdit (edit_args);
1661
1662                         edit_node = node;
1663                         
1664                         if (edit_args.CancelEdit) {
1665                                 edit_node = null;
1666                                 EndEdit (node);
1667                         }
1668                 }
1669
1670                 private void LabelEditCancelled (object sender, EventArgs e)
1671                 {
1672                         edit_args.SetLabel (null);
1673                         EndEdit (edit_node);
1674                 }
1675
1676                 private void LabelTextChanged (object sender, EventArgs e)
1677                 {
1678                         int width = TextRenderer.MeasureTextInternal (edit_text_box.Text, edit_text_box.Font, false).Width + 4;
1679                         edit_text_box.Width = width;
1680
1681                         if (edit_args != null)
1682                                 edit_args.SetLabel (edit_text_box.Text);
1683                 }
1684
1685                 internal void EndEdit (TreeNode node)
1686                 {
1687                         if (edit_text_box != null && edit_text_box.Visible) {
1688                                 edit_text_box.Visible = false;
1689                                 Focus ();
1690                         }
1691
1692                         if (edit_node != null && edit_node == node) {
1693                                 NodeLabelEditEventArgs e = new NodeLabelEditEventArgs (edit_args.Node, edit_args.Label);
1694
1695                                 OnAfterLabelEdit (e);
1696
1697                                 if (e.CancelEdit)
1698                                         return;
1699
1700                                 if (e.Label != null)
1701                                         edit_node.Text = e.Label;
1702                         }
1703                         
1704                         edit_node = null;
1705                         UpdateNode (node);
1706                 }
1707
1708                 internal void CancelEdit (TreeNode node)
1709                 {
1710                         edit_args.SetLabel (null);
1711                         
1712                         if (edit_text_box != null && edit_text_box.Visible) {
1713                                 edit_text_box.Visible = false;
1714                                 Focus ();
1715                         }
1716
1717                         edit_node = null;
1718                         UpdateNode (node);
1719                 }
1720
1721                 internal int GetNodeWidth (TreeNode node)
1722                 {
1723                         Font font = node.NodeFont;
1724                         if (node.NodeFont == null)
1725                                 font = Font;
1726                         return (int)TextRenderer.MeasureString (node.Text, font, 0, string_format).Width + 3;
1727                 }
1728
1729                 private void DrawSelectionAndFocus(TreeNode node, Graphics dc, Rectangle r)
1730                 {
1731                         if (Focused && focused_node == node && !full_row_select) {
1732                                 ControlPaint.DrawFocusRectangle (dc, r, ForeColor, BackColor);
1733                         }
1734                         if (draw_mode != TreeViewDrawMode.Normal)
1735                                 return;
1736
1737                         r.Inflate (-1, -1);
1738                         if (Focused && node == highlighted_node) {
1739                                 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHighlight), r);
1740                         } else if (!hide_selection && node == highlighted_node) {
1741                                 dc.FillRectangle (SystemBrushes.Control, r);
1742                         } else {
1743                                 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (node.BackColor), r);
1744                         }
1745                 }
1746                  
1747                 private void DrawStaticNode (TreeNode node, Graphics dc)
1748                 {
1749                         if (!full_row_select || show_lines)
1750                                 DrawSelectionAndFocus(node, dc, node.Bounds);
1751
1752                         
1753                         Font font = node.NodeFont;
1754                         if (node.NodeFont == null)
1755                                 font = Font;
1756                         Color text_color = (Focused && node == highlighted_node ?
1757                                         ThemeEngine.Current.ColorHighlightText : node.ForeColor);
1758                         if (text_color.IsEmpty)
1759                                 text_color = ForeColor;
1760                         dc.DrawString (node.Text, font,
1761                                         ThemeEngine.Current.ResPool.GetSolidBrush (text_color),
1762                                         node.Bounds, string_format);
1763                 }
1764
1765                 private void DrawTreeNode (TreeNode node, Graphics dc, Rectangle clip)
1766                 {
1767                         int child_count = node.nodes.Count;
1768                         int y = node.GetY ();
1769                         int middle = y + (ActualItemHeight / 2);
1770
1771                         if (full_row_select && !show_lines) {
1772                                 Rectangle r = new Rectangle (1, y, ViewportRectangle.Width - 2, ActualItemHeight);
1773                                 DrawSelectionAndFocus (node, dc, r);
1774                         }
1775
1776                         if (draw_mode == TreeViewDrawMode.Normal || draw_mode == TreeViewDrawMode.OwnerDrawText) {
1777                                 if ((show_root_lines || node.Parent != null) && show_plus_minus && child_count > 0)
1778                                         DrawNodePlusMinus (node, dc, node.GetLinesX () - Indent + 5, middle);
1779
1780 #if NET_2_0
1781                                 if (checkboxes && state_image_list == null)
1782                                         DrawNodeCheckBox (node, dc, CheckBoxLeft (node) - 3, middle);
1783
1784                                 if (checkboxes && state_image_list != null)
1785                                         DrawNodeState (node, dc, CheckBoxLeft (node) - 3, y);
1786
1787                                 if (!checkboxes && node.StateImage != null)
1788                                         dc.DrawImage (node.StateImage, new Rectangle (CheckBoxLeft (node) - 3, y, 16, 16));
1789 #else
1790                                 if (checkboxes)
1791                                         DrawNodeCheckBox (node, dc, CheckBoxLeft (node) - 3, middle);
1792 #endif
1793
1794                                 if (show_lines)
1795                                         DrawNodeLines (node, dc, clip, dash, node.GetLinesX (), y, middle);
1796
1797                                 if (ImageList != null)
1798                                         DrawNodeImage (node, dc, clip, node.GetImageX (), y);
1799                         }
1800
1801                         
1802 #if NET_2_0
1803                         if (draw_mode != TreeViewDrawMode.Normal) {
1804                                 dc.FillRectangle (Brushes.White, node.Bounds);
1805                                 TreeNodeStates tree_node_state = TreeNodeStates.Default;;
1806                                 if (node.IsSelected)
1807                                         tree_node_state = TreeNodeStates.Selected;
1808                                 if (node.Checked)
1809                                         tree_node_state |= TreeNodeStates.Checked;
1810                                 if (node == focused_node)
1811                                         tree_node_state |= TreeNodeStates.Focused;
1812                                 Rectangle node_bounds = node.Bounds;
1813                                 if (draw_mode == TreeViewDrawMode.OwnerDrawText) {
1814                                         node_bounds.X += 3;
1815                                         node_bounds.Y += 1;
1816                                 } else {
1817                                         node_bounds.X = 0;
1818                                         node_bounds.Width = Width;
1819                                 }
1820
1821                                 DrawTreeNodeEventArgs e = new DrawTreeNodeEventArgs (dc, node, node_bounds, tree_node_state);
1822
1823                                 OnDrawNode (e);                         
1824                                 if (!e.DrawDefault)
1825                                         return;
1826                         }
1827 #endif
1828
1829                         if (!node.IsEditing)
1830                                 DrawStaticNode (node, dc);
1831                 }
1832
1833                 internal void UpdateScrollBars (bool force)
1834                 {
1835                         if (!force && (IsDisposed || update_stack > 0 || !IsHandleCreated || !Visible))
1836                                 return;
1837
1838                         bool vert = false;
1839                         bool horz = false;
1840                         int height = -1;
1841                         int width = -1;
1842
1843                         if (scrollable) {
1844                                 OpenTreeNodeEnumerator walk = new OpenTreeNodeEnumerator (root_node);
1845                                 
1846                                 while (walk.MoveNext ()) {
1847                                         int r = walk.CurrentNode.Bounds.Right;
1848                                         int b = walk.CurrentNode.Bounds.Bottom;
1849
1850                                         if (r > width)
1851                                                 width = r;
1852                                         if (b > height)
1853                                                 height = b;
1854                                 }
1855
1856                                 // Remove scroll adjustments
1857                                 if (nodes.Count > 0)
1858                                         height -= nodes [0].Bounds.Top;
1859                                 width += hbar_offset;
1860
1861                                 if (height > ClientRectangle.Height) {
1862                                         vert = true;
1863
1864                                         if (width > ClientRectangle.Width - SystemInformation.VerticalScrollBarWidth)
1865                                                 horz = true;
1866                                 } else if (width > ClientRectangle.Width) {
1867                                         horz = true;
1868                                 }
1869
1870                                 if (!vert && horz && height > ClientRectangle.Height - SystemInformation.HorizontalScrollBarHeight)
1871                                         vert = true;
1872                         }
1873
1874                         if (vert) {
1875                                 int visible_height = horz ? ClientRectangle.Height - hbar.Height : ClientRectangle.Height;
1876                                 vbar.SetValues (Math.Max (0, max_visible_order - 2), visible_height / ActualItemHeight);
1877                                 /*
1878                                 vbar.Maximum = max_visible_order;
1879                                 vbar.LargeChange = ClientRectangle.Height / ItemHeight;
1880                                 */
1881
1882                                 if (!vbar_bounds_set) {
1883                                         vbar.Bounds = new Rectangle (ClientRectangle.Width - vbar.Width, 0, vbar.Width,
1884                                                         ClientRectangle.Height -
1885                                                         (horz ? SystemInformation.VerticalScrollBarWidth : 0));
1886                                         vbar_bounds_set = true;
1887
1888                                         // We need to recalc the hbar if the vbar is now visible
1889                                         hbar_bounds_set = false;
1890                                 }
1891
1892                                 
1893                                 vbar.Visible = true;
1894                                 if (skipped_nodes > 0) {
1895                                         int skip = Math.Min (skipped_nodes, vbar.Maximum - VisibleCount + 1);
1896                                         skipped_nodes = 0;
1897                                         vbar.Value = skip;
1898                                         skipped_nodes = skip;
1899                                 }
1900                         } else {
1901                                 skipped_nodes = 0;
1902                                 RecalculateVisibleOrder (root_node);
1903                                 vbar.Visible = false;
1904                                 vbar_bounds_set = false;
1905                         }
1906
1907                         if (horz) {
1908                                 hbar.SetValues (width + 1, ClientRectangle.Width - (vert ? SystemInformation.VerticalScrollBarWidth : 0));
1909                                 /*
1910                                 hbar.LargeChange = ClientRectangle.Width;
1911                                 hbar.Maximum = width + 1;
1912                                 */
1913
1914                                 if (!hbar_bounds_set) {
1915                                         hbar.Bounds = new Rectangle (0, ClientRectangle.Height - hbar.Height,
1916                                                         ClientRectangle.Width - (vert ? SystemInformation.VerticalScrollBarWidth : 0),
1917                                                         hbar.Height);
1918                                         hbar_bounds_set = true;
1919                                 }
1920                                 hbar.Visible = true;
1921                         } else {
1922                                 hbar_offset = 0;
1923                                 hbar.Visible = false;
1924                                 hbar_bounds_set = false;
1925                         }
1926                 }
1927
1928                 private void SizeChangedHandler (object sender, EventArgs e)
1929                 {
1930                         if (IsHandleCreated) {
1931                                 if (max_visible_order == -1)
1932                                         RecalculateVisibleOrder (root_node);
1933                                 UpdateScrollBars (false);
1934                         }
1935
1936                         if (vbar.Visible) {
1937                                 vbar.Bounds = new Rectangle (ClientRectangle.Width - vbar.Width, 0, vbar.Width,
1938                                                 ClientRectangle.Height - (hbar.Visible ? SystemInformation.HorizontalScrollBarHeight : 0));
1939                         }
1940
1941                         if (hbar.Visible) {
1942                                 hbar.Bounds = new Rectangle (0, ClientRectangle.Height - hbar.Height,
1943                                                 ClientRectangle.Width - (vbar.Visible ? SystemInformation.VerticalScrollBarWidth : 0), hbar.Height);
1944                         }
1945                 }
1946
1947                 private void VScrollBarValueChanged (object sender, EventArgs e)
1948                 {
1949                         EndEdit (edit_node);
1950
1951                         SetVScrollPos (vbar.Value, null);
1952                 }
1953
1954                 private void SetVScrollPos (int pos, TreeNode new_top)
1955                 {
1956                         if (pos < 0)
1957                                 pos = 0;
1958
1959                         if (skipped_nodes == pos)
1960                                 return;
1961
1962                         int diff = skipped_nodes - pos;
1963                         skipped_nodes = pos;
1964
1965                         if (!IsHandleCreated)
1966                                 return;
1967
1968                         int y_move = diff * ActualItemHeight;
1969                         XplatUI.ScrollWindow (Handle, ViewportRectangle, 0, y_move, false);
1970                 }
1971
1972                 /*private void SetVScrollTop (TreeNode new_top)
1973                 {
1974                         vbar.Value = new_top.visible_order - VisibleCount;
1975                 }*/
1976
1977                 private void HScrollBarValueChanged(object sender, EventArgs e)
1978                 {
1979                         EndEdit (edit_node);
1980
1981                         int old_offset = hbar_offset;
1982                         hbar_offset = hbar.Value;
1983
1984                         if (hbar_offset < 0) {
1985                                 hbar_offset = 0;
1986                         }
1987
1988                         XplatUI.ScrollWindow (Handle, ViewportRectangle, old_offset - hbar_offset, 0, false);
1989                 }
1990
1991                 internal void ExpandBelow (TreeNode node, int count_to_next)
1992                 {
1993                         if (update_stack > 0) {
1994                                 update_needed = true;
1995                                 return;
1996                         }
1997
1998                         Rectangle below = new Rectangle (0, node.Bounds.Bottom, ViewportRectangle.Width,
1999                                         ViewportRectangle.Height - node.Bounds.Bottom);
2000
2001                         int amount = count_to_next * ActualItemHeight;
2002
2003                         if (amount > 0)
2004                                 XplatUI.ScrollWindow (Handle, below, 0, amount, false);
2005
2006                         if (show_plus_minus) {
2007                                 Invalidate (new Rectangle (0, node.GetY (), Width, ActualItemHeight));
2008                         }
2009                 }
2010
2011                 internal void CollapseBelow (TreeNode node, int count_to_next)
2012                 {
2013                         if (update_stack > 0) {
2014                                 update_needed = true;
2015                                 return;
2016                         }
2017
2018                         Rectangle below = new Rectangle (0, node.Bounds.Bottom, ViewportRectangle.Width,
2019                                         ViewportRectangle.Height - node.Bounds.Bottom);
2020
2021                         int amount = count_to_next * ActualItemHeight;
2022
2023                         if (amount > 0)
2024                                 XplatUI.ScrollWindow (Handle, below, 0, -amount, false);
2025
2026                         if (show_plus_minus) {
2027                                 Invalidate (new Rectangle (0, node.GetY (), Width, ActualItemHeight));
2028                         }
2029                 }
2030
2031                 private void MouseWheelHandler(object sender, MouseEventArgs e) {
2032
2033                         if (vbar == null || !vbar.is_visible) {
2034                                 return;
2035                         }
2036
2037                         if (e.Delta < 0) {
2038                                 vbar.Value = Math.Min(vbar.Value + SystemInformation.MouseWheelScrollLines, vbar.Maximum - VisibleCount + 1);
2039                         } else {
2040                                 vbar.Value = Math.Max(0, vbar.Value - SystemInformation.MouseWheelScrollLines);
2041                         }
2042                 }
2043
2044                 private void VisibleChangedHandler (object sender, EventArgs e)
2045                 {
2046                         if (Visible) {
2047                                 UpdateScrollBars (false);
2048                         }
2049                 }
2050
2051                 private void FontChangedHandler (object sender, EventArgs e)
2052                 {
2053                         if (IsHandleCreated) {
2054                                 TreeNode top = TopNode;
2055                                 InvalidateNodeWidthRecursive (root_node);
2056
2057                                 SetTop (top);
2058                         }
2059                 }
2060
2061                 private void InvalidateNodeWidthRecursive (TreeNode node)
2062                 {
2063                         node.InvalidateWidth ();
2064                         foreach (TreeNode child in node.Nodes) {
2065                                 InvalidateNodeWidthRecursive (child);
2066                         }
2067                 }
2068
2069                 private void GotFocusHandler (object sender, EventArgs e)
2070                 {
2071                         if (selected_node == null) {
2072                                 if (pre_selected_node != null) {
2073                                         SelectedNode = pre_selected_node;
2074                                         return;
2075                                 }
2076                                 
2077                                 SelectedNode = TopNode;
2078                         
2079                         } else if (selected_node != null)
2080                                 UpdateNode (selected_node);
2081                 }
2082
2083                 private void LostFocusHandler (object sender, EventArgs e)
2084                 {
2085                         UpdateNode (SelectedNode);
2086                 }
2087
2088                 private void MouseDownHandler (object sender, MouseEventArgs e)
2089                 {
2090                         if (e.Button == MouseButtons.Right)
2091                                 Focus ();
2092
2093                         TreeNode node = GetNodeAt (e.Y);
2094                         if (node == null)
2095                                 return;
2096
2097 #if NET_2_0
2098                         mouse_click_node = node;
2099 #endif
2100
2101                         if (show_plus_minus && IsPlusMinusArea (node, e.X)) {
2102                                 node.Toggle ();
2103                                 return;
2104                         } else if (checkboxes && IsCheckboxArea (node, e.X)) {
2105                                 node.check_reason = TreeViewAction.ByMouse;
2106                                 node.Checked = !node.Checked;
2107                                 UpdateNode(node);
2108                                 return;
2109                         } else if (IsSelectableArea (node, e.X) || full_row_select) {
2110                                 TreeNode old_highlighted = highlighted_node;
2111                                 highlighted_node = node;
2112                                 if (label_edit && e.Clicks == 1 && highlighted_node == old_highlighted) {
2113                                         BeginEdit (node);
2114                                 } else if (highlighted_node != focused_node) {
2115                                         Size ds = SystemInformation.DragSize;
2116                                         mouse_rect.X = e.X - ds.Width;
2117                                         mouse_rect.Y = e.Y - ds.Height;
2118                                         mouse_rect.Width = ds.Width * 2;
2119                                         mouse_rect.Height = ds.Height * 2;
2120
2121                                         select_mmove = true;
2122                                 }
2123
2124                                 Invalidate (highlighted_node.Bounds);
2125                                 if (old_highlighted != null)
2126                                         Invalidate (Bloat (old_highlighted.Bounds));
2127                         } 
2128                 }
2129
2130                 private void MouseUpHandler (object sender, MouseEventArgs e) {
2131 #if NET_2_0
2132                         TreeNode node = GetNodeAt (e.Y);
2133                         
2134                         if (node != null && node == mouse_click_node) {
2135                                 if (e.Clicks == 2)
2136                                         OnNodeMouseDoubleClick (new TreeNodeMouseClickEventArgs (node, e.Button, e.Clicks, e.X, e.Y));
2137                                 else
2138                                         OnNodeMouseClick (new TreeNodeMouseClickEventArgs (node, e.Button, e.Clicks, e.X, e.Y));
2139                         }
2140                         
2141                         mouse_click_node = null;
2142 #endif
2143
2144                         drag_begin_x = -1;
2145                         drag_begin_y = -1;
2146
2147                         if (!select_mmove)
2148                                 return;
2149
2150                         select_mmove = false;
2151
2152                         if (e.Button == MouseButtons.Right && selected_node != null) {
2153                                 Invalidate (highlighted_node.Bounds);
2154                                 highlighted_node = selected_node;
2155                                 Invalidate (selected_node.Bounds);
2156                                 return;
2157                         }
2158
2159                         TreeViewCancelEventArgs ce = new TreeViewCancelEventArgs (highlighted_node, false, TreeViewAction.ByMouse);
2160                         OnBeforeSelect (ce);
2161
2162                         Rectangle invalid;
2163                         if (!ce.Cancel) {
2164                                 TreeNode prev_focused_node = focused_node;
2165                                 TreeNode prev_highlighted_node = highlighted_node;
2166                                 
2167                                 selected_node = highlighted_node;
2168                                 focused_node = highlighted_node;
2169                                 OnAfterSelect (new TreeViewEventArgs (selected_node, TreeViewAction.ByMouse));
2170
2171                                 if (prev_focused_node != null) {
2172                                         invalid = Rectangle.Union (Bloat (prev_focused_node.Bounds),
2173                                                         Bloat (prev_highlighted_node.Bounds));
2174                                 } else {
2175                                         invalid = Bloat (prev_highlighted_node.Bounds);
2176                                 }
2177
2178                                 if (full_row_select || draw_mode != TreeViewDrawMode.Normal) {
2179                                         invalid.X = 0;
2180                                         invalid.Width = ViewportRectangle.Width;
2181                                 }
2182
2183                                 Invalidate (invalid);
2184                         } else {
2185                                 highlighted_node = focused_node;
2186                                 selected_node = focused_node;
2187                         }
2188                 }
2189
2190                 private void MouseMoveHandler (object sender, MouseEventArgs e) {
2191 #if NET_2_0
2192                         // XXX - This should use HitTest and only fire when we are over
2193                         // the important parts of a node, not things like gridlines or
2194                         // whitespace
2195                         TreeNode tn = GetNodeAt (e.Location);
2196                         
2197                         if (tn != tooltip_currently_showing)
2198                                 MouseLeftItem (tooltip_currently_showing);
2199                                 
2200                         if (tn != null && tn != tooltip_currently_showing)
2201                                 MouseEnteredItem (tn);
2202 #endif
2203                         
2204                         if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right) {
2205                                 if (drag_begin_x == -1 && drag_begin_y == -1) {
2206                                         drag_begin_x = e.X;
2207                                         drag_begin_y = e.Y;
2208                                 } else {
2209                                         double rise = Math.Pow (drag_begin_x - e.X, 2);
2210                                         double run = Math.Pow (drag_begin_y - e.Y, 2);
2211                                         double move = Math.Sqrt (rise + run);
2212                                         if (move > 3) {
2213                                                 TreeNode drag = GetNodeAtUseX (e.X, e.Y);
2214                                                 
2215                                                 if (drag != null) {
2216                                                         OnItemDrag (new ItemDragEventArgs (e.Button, drag));
2217                                                 }
2218                                                 drag_begin_x = -1;
2219                                                 drag_begin_y = -1;
2220                                         }
2221                                 }
2222                                 
2223                         }
2224
2225                         // If there is enough movement before the mouse comes up,
2226                         // selection is reverted back to the originally selected node
2227                         if (!select_mmove || mouse_rect.Contains (e.X, e.Y))
2228                                 return;
2229
2230                         Invalidate (highlighted_node.Bounds);
2231                         Invalidate (selected_node.Bounds);
2232                         Invalidate (focused_node.Bounds);
2233
2234                         highlighted_node = selected_node;
2235                         focused_node = selected_node;
2236
2237                         select_mmove = false;
2238                 }
2239
2240                 private void DoubleClickHandler (object sender, MouseEventArgs e) {
2241                         TreeNode node = GetNodeAtUseX (e.X,e.Y);
2242                         if(node != null) {
2243                                 node.Toggle();
2244                         }
2245                 }
2246
2247                 
2248                 private bool RectsIntersect (Rectangle r, int left, int top, int width, int height)
2249                 {
2250                         return !((r.Left > left + width) || (r.Right < left) ||
2251                                         (r.Top > top + height) || (r.Bottom < top));
2252                 }
2253
2254 #if NET_2_0
2255                 // Return true if message was handled, false to send it to base
2256                 private bool WmContextMenu (ref Message m)
2257                 {
2258                         Point pt;
2259                         TreeNode tn;
2260                         
2261                         pt = new Point (LowOrder ((int)m.LParam.ToInt32 ()), HighOrder ((int)m.LParam.ToInt32 ()));
2262
2263                         // This means it's a keyboard menu request
2264                         if (pt.X == -1 || pt.Y == -1) {
2265                                 tn = SelectedNode;
2266                                 
2267                                 if (tn == null)
2268                                         return false;
2269                                 
2270                                 pt = new Point (tn.Bounds.Left, tn.Bounds.Top + (tn.Bounds.Height / 2));
2271                         } else {
2272                                 pt = PointToClient (pt);
2273                                 
2274                                 tn = GetNodeAt (pt);
2275
2276                                 if (tn == null)
2277                                         return false;
2278                         }
2279                         
2280                         // At this point, we have a valid TreeNode
2281                         if (tn.ContextMenu != null) {
2282                                 tn.ContextMenu.Show (this, pt);
2283                                 return true;
2284                         } else if (tn.ContextMenuStrip != null) {
2285                                 tn.ContextMenuStrip.Show (this, pt);
2286                                 return true;
2287                         }
2288                         
2289                         // The node we found did not have its own menu, let the parent try to display its menu
2290                         return false;
2291                 }
2292 #endif
2293
2294                 #region Stuff for ToolTips
2295 #if NET_2_0
2296                 private void MouseEnteredItem (TreeNode item)
2297                 {
2298                         tooltip_currently_showing = item;
2299                         
2300                         if (!is_hovering)
2301                                 return;
2302
2303                         if (ShowNodeToolTips && !string.IsNullOrEmpty (tooltip_currently_showing.ToolTipText))
2304                                 ToolTipWindow.Present (this, tooltip_currently_showing.ToolTipText);
2305
2306                         OnNodeMouseHover (new TreeNodeMouseHoverEventArgs (tooltip_currently_showing));
2307                 }
2308
2309                 private void MouseLeftItem (TreeNode item)
2310                 {
2311                         ToolTipWindow.Hide (this);
2312                         tooltip_currently_showing = null;
2313                 }
2314
2315                 private ToolTip ToolTipWindow {
2316                         get {
2317                                 if (tooltip_window == null)
2318                                         tooltip_window = new ToolTip ();
2319
2320                                 return tooltip_window;
2321                         }
2322                 }
2323 #endif
2324                 #endregion
2325                 
2326                 #endregion      // Internal & Private Methods and Properties
2327
2328                 #region Events
2329                 static object ItemDragEvent = new object ();
2330                 static object AfterCheckEvent = new object ();
2331                 static object AfterCollapseEvent = new object ();
2332                 static object AfterExpandEvent = new object ();
2333                 static object AfterLabelEditEvent = new object ();
2334                 static object AfterSelectEvent = new object ();
2335                 static object BeforeCheckEvent = new object ();
2336                 static object BeforeCollapseEvent = new object ();
2337                 static object BeforeExpandEvent = new object ();
2338                 static object BeforeLabelEditEvent = new object ();
2339                 static object BeforeSelectEvent = new object ();
2340 #if NET_2_0
2341                 static object DrawNodeEvent = new object ();
2342                 static object NodeMouseClickEvent = new object ();
2343                 static object NodeMouseDoubleClickEvent = new object();
2344                 static object NodeMouseHoverEvent = new object ();
2345                 static object RightToLeftLayoutChangedEvent = new object ();
2346 #endif
2347
2348                 public event ItemDragEventHandler ItemDrag {
2349                         add { Events.AddHandler (ItemDragEvent, value); }
2350                         remove { Events.RemoveHandler (ItemDragEvent, value); }
2351                 }
2352
2353                 public event TreeViewEventHandler AfterCheck {
2354                         add { Events.AddHandler (AfterCheckEvent, value); }
2355                         remove { Events.RemoveHandler (AfterCheckEvent, value); }
2356                 }
2357
2358                 public event TreeViewEventHandler AfterCollapse {
2359                         add { Events.AddHandler (AfterCollapseEvent, value); }
2360                         remove { Events.RemoveHandler (AfterCollapseEvent, value); }
2361                 }
2362
2363                 public event TreeViewEventHandler AfterExpand {
2364                         add { Events.AddHandler (AfterExpandEvent, value); }
2365                         remove { Events.RemoveHandler (AfterExpandEvent, value); }
2366                 }
2367
2368                 public event NodeLabelEditEventHandler AfterLabelEdit {
2369                         add { Events.AddHandler (AfterLabelEditEvent, value); }
2370                         remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
2371                 }
2372
2373                 public event TreeViewEventHandler AfterSelect {
2374                         add { Events.AddHandler (AfterSelectEvent, value); }
2375                         remove { Events.RemoveHandler (AfterSelectEvent, value); }
2376                 }
2377
2378                 public event TreeViewCancelEventHandler BeforeCheck {
2379                         add { Events.AddHandler (BeforeCheckEvent, value); }
2380                         remove { Events.RemoveHandler (BeforeCheckEvent, value); }
2381                 }
2382
2383                 public event TreeViewCancelEventHandler BeforeCollapse {
2384                         add { Events.AddHandler (BeforeCollapseEvent, value); }
2385                         remove { Events.RemoveHandler (BeforeCollapseEvent, value); }
2386                 }
2387
2388                 public event TreeViewCancelEventHandler BeforeExpand {
2389                         add { Events.AddHandler (BeforeExpandEvent, value); }
2390                         remove { Events.RemoveHandler (BeforeExpandEvent, value); }
2391                 }
2392
2393                 public event NodeLabelEditEventHandler BeforeLabelEdit {
2394                         add { Events.AddHandler (BeforeLabelEditEvent, value); }
2395                         remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
2396                 }
2397
2398                 public event TreeViewCancelEventHandler BeforeSelect {
2399                         add { Events.AddHandler (BeforeSelectEvent, value); }
2400                         remove { Events.RemoveHandler (BeforeSelectEvent, value); }
2401                 }
2402
2403 #if NET_2_0
2404                 public event DrawTreeNodeEventHandler DrawNode {
2405                         add { Events.AddHandler (DrawNodeEvent, value); }
2406                         remove { Events.RemoveHandler (DrawNodeEvent, value); }
2407                 }
2408
2409                 public event TreeNodeMouseClickEventHandler NodeMouseClick {
2410                         add { Events.AddHandler (NodeMouseClickEvent, value); }
2411                         remove { Events.RemoveHandler (NodeMouseClickEvent, value); }
2412                 }
2413
2414
2415                 public event TreeNodeMouseClickEventHandler NodeMouseDoubleClick {
2416                         add { Events.AddHandler (NodeMouseDoubleClickEvent, value); }
2417                         remove { Events.RemoveHandler (NodeMouseDoubleClickEvent, value); }
2418                 }
2419                 
2420                 public event TreeNodeMouseHoverEventHandler NodeMouseHover {
2421                         add { Events.AddHandler (NodeMouseHoverEvent, value); }
2422                         remove { Events.RemoveHandler (NodeMouseHoverEvent, value); }
2423                 }
2424                 
2425                 public event EventHandler RightToLeftLayoutChanged {
2426                         add { Events.AddHandler (RightToLeftLayoutChangedEvent, value); }
2427                         remove { Events.RemoveHandler (RightToLeftLayoutChangedEvent, value); }
2428                 }
2429 #endif
2430
2431                 [Browsable (false)]
2432                 [EditorBrowsable (EditorBrowsableState.Never)]  
2433                 public new event EventHandler BackgroundImageChanged {
2434                         add { base.BackgroundImageChanged += value; }
2435                         remove { base.BackgroundImageChanged -= value; }
2436                 }
2437
2438 #if NET_2_0
2439                 [Browsable (false)]
2440                 [EditorBrowsable (EditorBrowsableState.Never)]
2441                 public new event EventHandler BackgroundImageLayoutChanged {
2442                         add { base.BackgroundImageLayoutChanged += value; }
2443                         remove { base.BackgroundImageLayoutChanged -= value; }
2444                 }
2445
2446                 [Browsable (false)]
2447                 [EditorBrowsable (EditorBrowsableState.Never)]
2448                 public new event EventHandler PaddingChanged {
2449                         add { base.PaddingChanged += value; }
2450                         remove { base.PaddingChanged -= value; }
2451                 }
2452 #endif
2453
2454                 [EditorBrowsable (EditorBrowsableState.Never)]  
2455                 [Browsable (false)]
2456                 public new event PaintEventHandler Paint {
2457                         add { base.Paint += value; }
2458                         remove { base.Paint -= value; }
2459                 }
2460
2461                 [EditorBrowsable (EditorBrowsableState.Never)]  
2462                 [Browsable (false)]
2463                 public new event EventHandler TextChanged {
2464                         add { base.TextChanged += value; }
2465                         remove { base.TextChanged -= value; }
2466                 }
2467                 #endregion      // Events
2468         }
2469 }
2470