2007-05-02 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStrip.cs
1 //
2 // ToolStrip.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 //
25 // Authors:
26 //      Jonathan Pobst (monkey@jpobst.com)
27 //
28
29 #if NET_2_0
30 using System;
31 using System.Runtime.InteropServices;
32 using System.ComponentModel;
33 using System.Drawing;
34 using System.Windows.Forms.Layout;
35 using System.Collections.Generic;
36 using System.ComponentModel.Design.Serialization;
37
38 namespace System.Windows.Forms
39 {
40         [ComVisible (true)]
41         [ClassInterface (ClassInterfaceType.AutoDispatch)]
42         [DefaultEvent ("ItemClicked")]
43         [DefaultProperty ("Items")]
44         [Designer ("System.Windows.Forms.Design.ToolStripDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45         [DesignerSerializer ("System.Windows.Forms.Design.ToolStripCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
46         public class ToolStrip : ScrollableControl, IComponent, IDisposable
47         {
48                 #region Private Variables
49                 private bool allow_merge;
50                 private Color back_color;
51                 private bool can_overflow;
52                 private ToolStrip currently_merged_with;
53                 private ToolStripDropDownDirection default_drop_down_direction;
54                 internal ToolStripItemCollection displayed_items;
55                 private Color fore_color;
56                 private Padding grip_margin;
57                 private ToolStripGripStyle grip_style;
58                 private List<ToolStripItem> hidden_merged_items;
59                 private ImageList image_list;
60                 private Size image_scaling_size;
61                 private bool is_currently_merged;
62                 private ToolStripItemCollection items;
63                 private bool keyboard_active;
64                 private LayoutEngine layout_engine;
65                 private LayoutSettings layout_settings;
66                 private ToolStripLayoutStyle layout_style;
67                 private Orientation orientation;
68                 private ToolStripOverflowButton overflow_button;
69                 private List<ToolStripItem> pre_merge_items;
70                 private ToolStripRenderer renderer;
71                 private ToolStripRenderMode render_mode;
72                 private Timer tooltip_timer;
73                 private ToolTip.ToolTipWindow tooltip_window;
74                 private bool show_item_tool_tips;
75                 private bool stretch;
76
77                 private ToolStripItem mouse_currently_over;
78                 internal bool menu_selected;
79                 private ToolStripItem tooltip_currently_showing;
80                 #endregion
81
82                 #region Public Constructors
83                 public ToolStrip () : this (null)
84                 {
85                 }
86
87                 public ToolStrip (params ToolStripItem[] items) : base ()
88                 {
89                         SetStyle (ControlStyles.AllPaintingInWmPaint, true);
90                         SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
91                         SetStyle (ControlStyles.Selectable, false);
92                         SetStyle (ControlStyles.SupportsTransparentBackColor, true);
93
94                         this.SuspendLayout ();
95                         this.items = new ToolStripItemCollection (this, items);
96                         this.allow_merge = true;
97                         base.AutoSize = true;
98                         this.back_color = Control.DefaultBackColor;
99                         this.can_overflow = true;
100                         base.CausesValidation = false;
101                         this.default_drop_down_direction = ToolStripDropDownDirection.BelowRight;
102                         this.displayed_items = new ToolStripItemCollection (this, null);
103                         this.Dock = this.DefaultDock;
104                         base.Font = new Font ("Tahoma", 8.25f);
105                         this.fore_color = Control.DefaultForeColor;
106                         this.grip_margin = this.DefaultGripMargin;
107                         this.grip_style = ToolStripGripStyle.Visible;
108                         this.image_scaling_size = new Size (16, 16);
109                         this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow;
110                         this.orientation = Orientation.Horizontal;
111                         if (!(this is ToolStripDropDown))
112                                 this.overflow_button = new ToolStripOverflowButton (this);
113                         this.renderer = null;
114                         this.render_mode = ToolStripRenderMode.ManagerRenderMode;
115                         this.show_item_tool_tips = this.DefaultShowItemToolTips;
116                         base.TabStop = false;
117                         this.ResumeLayout ();
118                         DoAutoSize ();
119                         
120                         // Register with the ToolStripManager
121                         ToolStripManager.AddToolStrip (this);
122                 }
123                 #endregion
124
125                 #region Public Properties
126                 [DefaultValue (true)]
127                 public bool AllowMerge {
128                         get { return this.allow_merge; }
129                         set { this.allow_merge = false; }
130                 }
131                 
132                 public override AnchorStyles Anchor {
133                         get { return base.Anchor; }
134                         set { base.Anchor = value; }
135                 }
136
137                 [Browsable (false)]
138                 [EditorBrowsable (EditorBrowsableState.Never)]
139                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
140                 public override bool AutoScroll {
141                         get { return base.AutoScroll; }
142                         set { base.AutoScroll = value; }
143                 }
144
145                 [Browsable (false)]
146                 [EditorBrowsable (EditorBrowsableState.Never)]
147                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
148                 public new Size AutoScrollMargin {
149                         get { return base.AutoScrollMargin; }
150                         set { base.AutoScrollMargin = value; }
151                 }
152
153                 [Browsable (false)]
154                 [EditorBrowsable (EditorBrowsableState.Never)]
155                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
156                 public new Size AutoScrollMinSize {
157                         get { return base.AutoScrollMinSize; }
158                         set { base.AutoScrollMinSize = value; }
159                 }
160
161                 [Browsable (false)]
162                 [EditorBrowsable (EditorBrowsableState.Never)]
163                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
164                 public new Point AutoScrollPosition {
165                         get { return base.AutoScrollPosition; }
166                         set { base.AutoScrollPosition = value; }
167                 }
168
169                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
170                 [Browsable (true)]
171                 [EditorBrowsable (EditorBrowsableState.Always)]
172                 [DefaultValue (true)]
173                 public override bool AutoSize {
174                         get { return base.AutoSize; }
175                         set { base.AutoSize = value; }
176                 }
177                 
178                 new public Color BackColor {
179                         get { return this.back_color; }
180                         set { this.back_color = value; }
181                 }
182
183                 [DefaultValue (true)]
184                 public bool CanOverflow {
185                         get { return this.can_overflow; }
186                         set { this.can_overflow = value; }
187                 }
188                 
189                 [Browsable (false)]
190                 [DefaultValue (false)]
191                 public new bool CausesValidation {
192                         get { return base.CausesValidation; }
193                         set { base.CausesValidation = value; }
194                 }
195                 
196                 [EditorBrowsable (EditorBrowsableState.Never)]
197                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
198                 public new ControlCollection Controls {
199                         get { return base.Controls; }
200                 }
201
202                 [Browsable (false)]
203                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
204                 public override Cursor Cursor {
205                         get { return base.Cursor; }
206                         set { base.Cursor = value; }
207                 }
208                 
209                 [Browsable (false)]
210                 public virtual ToolStripDropDownDirection DefaultDropDownDirection {
211                         get { return this.default_drop_down_direction; }
212                         set { 
213                                 if (!Enum.IsDefined (typeof (ToolStripDropDownDirection), value))
214                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripDropDownDirection", value));
215                                         
216                                 this.default_drop_down_direction = value;
217                         }
218                 }
219
220                 public override Rectangle DisplayRectangle {
221                         get {
222                                 if (this.orientation == Orientation.Horizontal)
223                                         if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
224                                                 return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical);
225                                         else
226                                                 return new Rectangle (this.GripRectangle.Right + this.GripMargin.Right, this.Padding.Top, this.Width - this.Padding.Horizontal - this.GripRectangle.Right - this.GripMargin.Right, this.Height - this.Padding.Vertical);
227                                 else
228                                         if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
229                                                 return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical);
230                                         else
231                                                 return new Rectangle (this.Padding.Left, this.GripRectangle.Bottom + this.GripMargin.Bottom + this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical - this.GripRectangle.Bottom - this.GripMargin.Bottom);
232                         }
233                 }
234
235                 [DefaultValue (DockStyle.Top)]
236                 public override DockStyle Dock {
237                         get { return base.Dock; }
238                         set {
239                                 if (base.Dock != value) {
240                                         base.Dock = value;
241                                         
242                                         switch (value) {
243                                                 case DockStyle.Top:
244                                                 case DockStyle.Bottom:
245                                                 case DockStyle.None:
246                                                         this.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
247                                                         break;
248                                                 case DockStyle.Left:
249                                                 case DockStyle.Right:
250                                                         this.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
251                                                         break;
252                                         }
253                                 }
254                         }
255                 }
256
257                 public override Font Font {
258                         get { return base.Font; }
259                         set { 
260                                 if (base.Font != value) {
261                                         base.Font = value;
262                                         
263                                         foreach (ToolStripItem tsi in this.Items)
264                                                 tsi.OnOwnerFontChanged (EventArgs.Empty);
265                                 }
266                          }
267                 }
268                 
269                 [Browsable (false)]
270                 public new Color ForeColor {
271                         get { return this.fore_color; }
272                         set { 
273                                 if (this.fore_color != value) {
274                                         this.fore_color = value; 
275                                         this.OnForeColorChanged (EventArgs.Empty); 
276                                 }
277                         }
278                 }
279
280                 [Browsable (false)]
281                 public ToolStripGripDisplayStyle GripDisplayStyle {
282                         get { return this.orientation == Orientation.Vertical ? ToolStripGripDisplayStyle.Horizontal : ToolStripGripDisplayStyle.Vertical; }
283                 }
284
285                 public Padding GripMargin {
286                         get { return this.grip_margin; }
287                         set { 
288                                 if (this.grip_margin != value) {
289                                         this.grip_margin = value; 
290                                         this.PerformLayout (); 
291                                 }
292                         }
293                 }
294
295                 [Browsable (false)]
296                 public Rectangle GripRectangle {
297                         get {
298                                 if (this.grip_style == ToolStripGripStyle.Hidden)
299                                         return Rectangle.Empty;
300
301                                 if (this.orientation == Orientation.Horizontal)
302                                         return new Rectangle (this.grip_margin.Left + this.Padding.Left, this.Padding.Top, 3, this.Height);
303                                 else
304                                         return new Rectangle (this.Padding.Left, this.grip_margin.Top + this.Padding.Top, this.Width, 3);
305                         }
306                 }
307
308                 [DefaultValue (ToolStripGripStyle.Visible)]
309                 public ToolStripGripStyle GripStyle {
310                         get { return this.grip_style; }
311                         set {
312                                 if (this.grip_style != value) {
313                                         if (!Enum.IsDefined (typeof (ToolStripGripStyle), value))
314                                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripGripStyle", value));
315                                         this.grip_style = value;
316                                         this.PerformLayout ();
317                                 }
318                         }
319                 }
320
321                 [Browsable (false)]
322                 [EditorBrowsable (EditorBrowsableState.Never)]
323                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
324                 public new bool HasChildren {
325                         get { return base.HasChildren; }
326                 }
327
328                 [Browsable (false)]
329                 [EditorBrowsable (EditorBrowsableState.Never)]
330                 public new HScrollProperties HorizontalScroll {
331                         get { return base.HorizontalScroll; }
332                 }
333                 
334                 [Browsable (false)]
335                 [DefaultValue (null)]
336                 public ImageList ImageList {
337                         get { return this.image_list; }
338                         set { this.image_list = value; }
339                 }
340
341                 [DefaultValue ("{Width=16, Height=16}")]
342                 public Size ImageScalingSize {
343                         get { return this.image_scaling_size; }
344                         set { this.image_scaling_size = value; }
345                 }
346
347                 [MonoTODO ("Always returns false, dragging not implemented yet.")]
348                 [Browsable (false)]
349                 [EditorBrowsable (EditorBrowsableState.Advanced)]
350                 public bool IsCurrentlyDragging {
351                         get { return false; }
352                 }
353                 
354                 [Browsable (false)]
355                 public bool IsDropDown {
356                         get {
357                                 if (this is ToolStripDropDown)
358                                         return true;
359
360                                 return false;
361                         }
362                 }
363
364                 [MergableProperty (false)]
365                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
366                 public virtual ToolStripItemCollection Items {
367                         get { return this.items; }
368                 }
369
370                 public override LayoutEngine LayoutEngine {
371                         get { 
372                                  if (layout_engine == null)
373                                         this.layout_engine = new ToolStripSplitStackLayout ();
374                                         
375                                  return this.layout_engine;
376                         }
377                 }
378
379                 [Browsable (false)]
380                 [DefaultValue (null)]
381                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
382                 public LayoutSettings LayoutSettings {
383                         get { return this.layout_settings; }
384                         set { this.layout_settings = value; }
385                 }
386                 
387                 [AmbientValue (ToolStripLayoutStyle.StackWithOverflow)]
388                 public ToolStripLayoutStyle LayoutStyle {
389                         get { return layout_style; }
390                         set {
391                                 if (this.layout_style != value) {
392                                         if (!Enum.IsDefined (typeof (ToolStripLayoutStyle), value))
393                                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripLayoutStyle", value));
394
395                                         this.layout_style = value;
396
397                                         if (this.layout_style == ToolStripLayoutStyle.Flow)
398                                                 this.layout_engine = new FlowLayout ();
399                                         else
400                                                 this.layout_engine = new ToolStripSplitStackLayout ();
401
402                                         if (this.layout_style == ToolStripLayoutStyle.StackWithOverflow) {
403                                                 if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
404                                                         this.layout_style = ToolStripLayoutStyle.VerticalStackWithOverflow;
405                                                 else
406                                                         this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow;
407                                         }
408
409                                         if (this.layout_style == ToolStripLayoutStyle.HorizontalStackWithOverflow)
410                                                 this.orientation = Orientation.Horizontal;
411                                         else if (this.layout_style == ToolStripLayoutStyle.VerticalStackWithOverflow)
412                                                 this.orientation = Orientation.Vertical;
413                                                 
414                                         this.layout_settings = this.CreateLayoutSettings (value);
415                                         
416                                         this.PerformLayout ();
417                                         this.OnLayoutStyleChanged (EventArgs.Empty);
418                                 }
419                         }
420                 }
421
422                 [Browsable (false)]
423                 public Orientation Orientation {
424                         get { return this.orientation; }
425                 }
426
427                 [Browsable (false)]
428                 [EditorBrowsable (EditorBrowsableState.Advanced)]
429                 public ToolStripOverflowButton OverflowButton {
430                         get { return this.overflow_button; }
431                 }
432                 
433                 [Browsable (false)]
434                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
435                 public ToolStripRenderer Renderer {
436                         get { 
437                                 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
438                                         return ToolStripManager.Renderer;
439                                         
440                                 return this.renderer; 
441                         }
442                         set { 
443                                 if (this.renderer != value) {
444                                         this.renderer = value; 
445                                         this.render_mode = ToolStripRenderMode.Custom;
446                                         this.PerformLayout ();
447                                         this.OnRendererChanged (EventArgs.Empty);
448                                 }
449                         }
450                 }
451
452                 public ToolStripRenderMode RenderMode {
453                         get { return this.render_mode; }
454                         set {
455                                 if (!Enum.IsDefined (typeof (ToolStripRenderMode), value))
456                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value));
457
458                                 if (value == ToolStripRenderMode.Custom && this.renderer == null)
459                                         throw new NotSupportedException ("Must set Renderer property before setting RenderMode to Custom");
460                                 if (value == ToolStripRenderMode.Professional || value == ToolStripRenderMode.System)
461                                         this.Renderer = new ToolStripProfessionalRenderer ();
462
463                                 this.render_mode = value;
464                         }
465                 }
466
467                 [DefaultValue (true)]
468                 public bool ShowItemToolTips {
469                         get { return this.show_item_tool_tips; }
470                         set { this.show_item_tool_tips = value; }
471                 }
472                 
473                 [DefaultValue (false)]
474                 public bool Stretch {
475                         get { return this.stretch; }
476                         set { this.stretch = value; }
477                 }
478                 
479                 [DefaultValue (false)]
480                 [DispId(-516)]
481                 public new bool TabStop {
482                         get { return base.TabStop; }
483                         set { base.TabStop = value; }
484                 }
485
486                 [Browsable (false)]
487                 [EditorBrowsable (EditorBrowsableState.Never)]
488                 public new VScrollProperties VerticalScroll {
489                         get { return base.VerticalScroll; }
490                 }
491                 #endregion
492
493                 #region Protected Properties
494                 protected virtual DockStyle DefaultDock { get { return DockStyle.Top; } }
495                 protected virtual Padding DefaultGripMargin { get { return new Padding (2); } }
496                 protected override Padding DefaultMargin { get { return Padding.Empty; } }
497                 protected override Padding DefaultPadding { get { return new Padding (0, 0, 1, 0); } }
498                 protected virtual bool DefaultShowItemToolTips { get { return true; } }
499                 protected override Size DefaultSize { get { return new Size (100, 25); } }
500                 protected internal virtual ToolStripItemCollection DisplayedItems { get { return this.displayed_items; } }
501                 #endregion
502
503                 #region Public Methods
504                 [EditorBrowsable (EditorBrowsableState.Never)]
505                 public new Control GetChildAtPoint (Point point)
506                 {
507                         return base.GetChildAtPoint (point);
508                 }
509
510                 //[EditorBrowsable (EditorBrowsableState.Never)]
511                 //public new Control GetChildAtPoint (Point pt, GetChildAtPointSkip skipValue)
512                 //{
513                 //        return base.GetChildAtPoint (pt, skipValue);
514                 //}
515                 
516                 public ToolStripItem GetItemAt (Point point)
517                 {
518                         foreach (ToolStripItem tsi in this.displayed_items)
519                                 if (tsi.Visible && tsi.Bounds.Contains (point))
520                                         return tsi;
521
522                         return null;
523                 }
524
525                 public ToolStripItem GetItemAt (int x, int y)
526                 {
527                         return GetItemAt (new Point (x, y));
528                 }
529
530                 public virtual ToolStripItem GetNextItem (ToolStripItem start, ArrowDirection direction)
531                 {
532                         if (!Enum.IsDefined (typeof (ArrowDirection), direction))
533                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ArrowDirection", direction));
534
535                         ToolStripItem current_best = null;
536                         int current_best_point;
537                         
538                         switch (direction) {
539                                 case ArrowDirection.Right:
540                                         current_best_point = int.MaxValue;
541
542                                         if (start != null)
543                                                 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
544                                                         if (loop_tsi.Left >= start.Right && loop_tsi.Left < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
545                                                                 current_best = loop_tsi;
546                                                                 current_best_point = loop_tsi.Left;
547                                                         }
548                                                         
549                                         if (current_best == null)
550                                                 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
551                                                         if (loop_tsi.Left < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
552                                                                 current_best = loop_tsi;
553                                                                 current_best_point = loop_tsi.Left;
554                                                         }
555                                                         
556                                         break;
557                                 case ArrowDirection.Up:
558                                         current_best_point = int.MinValue;
559
560                                         if (start != null)
561                                                 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
562                                                         if (loop_tsi.Bottom <= start.Top && loop_tsi.Top > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
563                                                                 current_best = loop_tsi;
564                                                                 current_best_point = loop_tsi.Top;
565                                                         }
566
567                                         if (current_best == null)
568                                                 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
569                                                         if (loop_tsi.Top > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
570                                                                 current_best = loop_tsi;
571                                                                 current_best_point = loop_tsi.Top;
572                                                         }
573
574                                         break;
575                                 case ArrowDirection.Left:
576                                         current_best_point = int.MinValue;
577
578                                         if (start != null)
579                                                 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
580                                                         if (loop_tsi.Right <= start.Left && loop_tsi.Left > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
581                                                                 current_best = loop_tsi;
582                                                                 current_best_point = loop_tsi.Left;
583                                                         }
584
585                                         if (current_best == null)
586                                                 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
587                                                         if (loop_tsi.Left > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
588                                                                 current_best = loop_tsi;
589                                                                 current_best_point = loop_tsi.Left;
590                                                         }
591
592                                         break;
593                                 case ArrowDirection.Down:
594                                         current_best_point = int.MaxValue;
595
596                                         if (start != null) 
597                                                 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
598                                                         if (loop_tsi.Top >= start.Bottom && loop_tsi.Bottom < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
599                                                                 current_best = loop_tsi;
600                                                                 current_best_point = loop_tsi.Top;
601                                                         }
602
603                                         if (current_best == null)
604                                                 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
605                                                         if (loop_tsi.Top < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
606                                                                 current_best = loop_tsi;
607                                                                 current_best_point = loop_tsi.Top;
608                                                         }
609
610                                         break;
611                         }
612
613                         return current_best;
614                 }
615
616                 [EditorBrowsable (EditorBrowsableState.Never)]
617                 public void ResetMinimumSize ()
618                 {
619                         this.MinimumSize = new Size (-1, -1);
620                 }
621
622                 [EditorBrowsable (EditorBrowsableState.Never)]
623                 public new void SetAutoScrollMargin (int x, int y)
624                 {
625                         base.SetAutoScrollMargin (x, y);
626                 }
627                 
628                 public override string ToString ()
629                 {
630                         return String.Format ("{0}, Name: {1}, Items: {2}", base.ToString(), this.Name, this.items.Count.ToString ());
631                 }
632                 #endregion
633
634                 #region Protected Methods
635                 protected override AccessibleObject CreateAccessibilityInstance ()
636                 {
637                         AccessibleObject ao = new AccessibleObject (this);
638                         
639                         ao.role = AccessibleRole.ToolBar;
640                         
641                         return ao;
642                 }
643                 
644                 protected override ControlCollection CreateControlsInstance ()
645                 {
646                         return base.CreateControlsInstance ();
647                 }
648
649                 protected internal virtual ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick)
650                 {
651                         if (text == "-")
652                                 return new ToolStripSeparator ();
653
654                         if (this is ToolStripDropDown)
655                                 return new ToolStripMenuItem (text, image, onClick);
656                                 
657                         return new ToolStripButton (text, image, onClick);
658                 }
659
660                 protected virtual LayoutSettings CreateLayoutSettings (ToolStripLayoutStyle layoutStyle)
661                 {
662                         switch (layoutStyle) {
663                                 case ToolStripLayoutStyle.Flow:
664                                         return new FlowLayoutSettings ();
665                                 case ToolStripLayoutStyle.Table:
666                                         //return new TableLayoutSettings ();
667                                 case ToolStripLayoutStyle.StackWithOverflow:
668                                 case ToolStripLayoutStyle.HorizontalStackWithOverflow:
669                                 case ToolStripLayoutStyle.VerticalStackWithOverflow:
670                                 default:
671                                         return null;
672                         }
673                 }
674                 
675                 protected override void Dispose (bool disposing)
676                 {
677                         if (!IsDisposed) {
678                                 ToolStripManager.RemoveToolStrip (this);
679                                 base.Dispose (disposing);
680                         }
681                 }
682                 
683                 protected override void OnDockChanged (EventArgs e)
684                 {
685                         base.OnDockChanged (e);
686                 }
687
688                 protected override bool IsInputChar (char charCode)
689                 {
690                         return base.IsInputChar (charCode);
691                 }
692
693                 protected override bool IsInputKey (Keys keyData)
694                 {
695                         return base.IsInputKey (keyData);
696                 }
697                 
698                 protected override void OnEnabledChanged (EventArgs e)
699                 {
700                         base.OnEnabledChanged (e);
701                         
702                         foreach (ToolStripItem tsi in this.Items)
703                                 tsi.OnParentEnabledChanged (EventArgs.Empty);
704                 }
705
706                 protected override void OnFontChanged (EventArgs e)
707                 {
708                         base.OnFontChanged (e);
709                 }
710
711                 protected override void OnHandleCreated (EventArgs e)
712                 {
713                         base.OnHandleCreated (e);
714                 }
715
716                 protected override void OnHandleDestroyed (EventArgs e)
717                 {
718                         base.OnHandleDestroyed (e);
719                 }
720
721                 protected override void OnInvalidated (InvalidateEventArgs e)
722                 {
723                         base.OnInvalidated (e);
724                 }
725
726                 protected internal virtual void OnItemAdded (ToolStripItemEventArgs e)
727                 {
728                         e.Item.Available = true;
729                         e.Item.SetPlacement (ToolStripItemPlacement.Main);
730                         this.DoAutoSize ();
731                         this.PerformLayout ();
732                         
733                         ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemAddedEvent]);
734                         if (eh != null)
735                                 eh (this, e);
736                 }
737
738                 protected virtual void OnItemClicked (ToolStripItemClickedEventArgs e)
739                 {
740                         ToolStripManager.SetActiveToolStrip (null);
741                         
742                         ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [ItemClickedEvent]);
743                         if (eh != null)
744                                 eh (this, e);
745                 }
746
747                 protected internal virtual void OnItemRemoved (ToolStripItemEventArgs e)
748                 {
749                         ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemRemovedEvent]);
750                         if (eh != null)
751                                 eh (this, e);
752                 }
753
754                 protected override void OnLayout (LayoutEventArgs e)
755                 {
756                         DoAutoSize ();
757                         base.OnLayout (e);
758
759                         this.SetDisplayedItems ();
760                         this.OnLayoutCompleted (EventArgs.Empty);
761                         this.Invalidate ();
762                 }
763
764                 protected virtual void OnLayoutCompleted (EventArgs e)
765                 {
766                         EventHandler eh = (EventHandler)(Events [LayoutCompletedEvent]);
767                         if (eh != null)
768                                 eh (this, e);
769                 }
770
771                 protected virtual void OnLayoutStyleChanged (EventArgs e)
772                 {
773                         EventHandler eh = (EventHandler)(Events[LayoutStyleChangedEvent]);
774                         if (eh != null)
775                                 eh (this, e);
776                 }
777
778                 protected override void OnLeave (EventArgs e)
779                 {
780                         base.OnLeave (e);
781                 }
782
783                 protected override void OnLostFocus (EventArgs e)
784                 {
785                         base.OnLostFocus (e);
786                 }
787
788                 protected override void OnMouseCaptureChanged (EventArgs e)
789                 {
790                         base.OnMouseCaptureChanged (e);
791                 }
792                 
793                 protected override void OnMouseDown (MouseEventArgs mea)
794                 {
795                         if (mouse_currently_over != null)
796                         {
797                                 if (this is MenuStrip && !(mouse_currently_over as ToolStripMenuItem).HasDropDownItems) {
798                                         if (!menu_selected)
799                                                 (this as MenuStrip).FireMenuActivate ();
800                                         
801                                         return;
802                                 }
803                                         
804                                 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseDown);
805                                 
806                                 if (this is MenuStrip && !menu_selected) {
807                                         (this as MenuStrip).FireMenuActivate ();
808                                         menu_selected = true;                           
809                                 }
810                         } else {
811                                 if (this is MenuStrip)
812                                         this.HideMenus (true, ToolStripDropDownCloseReason.AppClicked);
813                         }
814                         
815                         if (this is MenuStrip)
816                                 this.Capture = false;
817
818                         base.OnMouseDown (mea);
819                 }
820
821                 protected override void OnMouseLeave (EventArgs e)
822                 {
823                         if (mouse_currently_over != null) {
824                                 MouseLeftItem (mouse_currently_over);
825                                 mouse_currently_over.FireEvent (e, ToolStripItemEventType.MouseLeave);
826                                 mouse_currently_over = null;
827                         }
828
829                         base.OnMouseLeave (e);
830                 }
831
832                 protected override void OnMouseMove (MouseEventArgs mea)
833                 {
834                         ToolStripItem tsi;
835                         // Find the item we are now 
836                         if (this.overflow_button != null && this.overflow_button.Visible && this.overflow_button.Bounds.Contains (mea.Location))
837                                 tsi = this.overflow_button;
838                         else
839                                 tsi = this.GetItemAt (mea.X, mea.Y);
840
841                         if (tsi != null) {
842                                 // If we were already hovering on this item, just send a mouse move
843                                 if (tsi == mouse_currently_over) 
844                                         tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
845                                 else {
846                                         // If we were over a different item, fire a mouse leave on it
847                                         if (mouse_currently_over != null) {
848                                                 MouseLeftItem (tsi);
849                                                 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
850                                         }
851                                         
852                                         // Set the new item we are currently over
853                                         mouse_currently_over = tsi;
854                                         
855                                         // Fire mouse enter and mouse move
856                                         tsi.FireEvent (mea, ToolStripItemEventType.MouseEnter);
857                                         MouseEnteredItem (tsi);
858                                         tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
859
860                                         // If we're over something with a drop down, show it
861                                         if (menu_selected && mouse_currently_over.Enabled && mouse_currently_over is ToolStripDropDownItem && (mouse_currently_over as ToolStripDropDownItem).HasDropDownItems)
862                                                 (mouse_currently_over as ToolStripDropDownItem).ShowDropDown ();
863                                 }
864                         } else {
865                                 // We're not over anything now, just fire the mouse leave on what we used to be over
866                                 if (mouse_currently_over != null) {
867                                         MouseLeftItem (tsi);
868                                         mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
869                                         mouse_currently_over = null;
870                                 }
871                         }
872                         
873                         base.OnMouseMove (mea);
874                 }
875
876                 protected override void OnMouseUp (MouseEventArgs mea)
877                 {
878                         // If we're currently over an item (set in MouseMove)
879                         if (mouse_currently_over != null) {
880                                 // Fire the item's MouseUp event
881                                 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseUp);
882
883                                 // The event handler may have blocked until the mouse moved off of the ToolStripItem
884                                 if (mouse_currently_over == null)
885                                         return;
886                                         
887                                 // Fire our ItemClicked event
888                                 OnItemClicked (new ToolStripItemClickedEventArgs (mouse_currently_over));
889                         }
890
891                         base.OnMouseUp (mea);
892                 }
893
894                 protected override void OnPaint (PaintEventArgs e)
895                 {
896                         base.OnPaint (e);
897
898                         // Draw the grip
899                         this.OnPaintGrip (e);
900
901                         // Make each item draw itself
902                         foreach (ToolStripItem tsi in this.displayed_items) {
903                                 e.Graphics.TranslateTransform (tsi.Bounds.Left, tsi.Bounds.Top);
904                                 tsi.FireEvent (e, ToolStripItemEventType.Paint);
905                                 e.Graphics.ResetTransform ();
906                         }
907
908                         // Paint the Overflow button if it's visible
909                         if (this.overflow_button != null && this.overflow_button.Visible) {
910                                 e.Graphics.TranslateTransform (this.overflow_button.Bounds.Left, this.overflow_button.Bounds.Top);
911                                 this.overflow_button.FireEvent (e, ToolStripItemEventType.Paint);
912                                 e.Graphics.ResetTransform ();
913                         }
914
915                         Rectangle affected_bounds = new Rectangle (new Point (0, 0), this.Size);
916                         Rectangle connected_area = Rectangle.Empty;
917
918                         if (this is ToolStripDropDown && (this as ToolStripDropDown).OwnerItem != null && !(this as ToolStripDropDown).OwnerItem.IsOnDropDown)
919                                 connected_area = new Rectangle (1, 0, (this as ToolStripDropDown).OwnerItem.Width - 2, 2);
920
921                         ToolStripRenderEventArgs pevent = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, Color.Empty);
922                         pevent.InternalConnectedArea = connected_area;
923
924                         this.Renderer.DrawToolStripBorder (pevent);
925                 }
926
927                 [EditorBrowsable (EditorBrowsableState.Advanced)]
928                 protected override void OnPaintBackground (PaintEventArgs pevent)
929                 {
930                         base.OnPaintBackground (pevent);
931
932                         Rectangle affected_bounds = new Rectangle (new Point (0, 0), this.Size);
933                         Rectangle connected_area = Rectangle.Empty;
934
935                         if (this is ToolStripDropDown && (this as ToolStripDropDown).OwnerItem != null && !(this as ToolStripDropDown).OwnerItem.IsOnDropDown)
936                                 connected_area = new Rectangle (1, 0, (this as ToolStripDropDown).OwnerItem.Width - 2, 2);
937                         
938                         ToolStripRenderEventArgs e = new ToolStripRenderEventArgs (pevent.Graphics, this, affected_bounds, Color.Empty);
939                         e.InternalConnectedArea = connected_area;
940                         
941                         this.Renderer.DrawToolStripBackground (e);
942                 }
943
944                 protected internal virtual void OnPaintGrip (PaintEventArgs e)
945                 {
946                         // Never draw a grip with these two layouts
947                         if (this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
948                                 return;
949                         
950                         PaintEventHandler eh = (PaintEventHandler)(Events [PaintGripEvent]);
951                         if (eh != null)
952                                 eh (this, e);
953
954                         if (!(this is MenuStrip)) {
955                                 if (this.orientation == Orientation.Horizontal)
956                                         e.Graphics.TranslateTransform (2, 0);
957                                 else
958                                         e.Graphics.TranslateTransform (0, 2);
959                         }
960
961                         this.Renderer.DrawGrip (new ToolStripGripRenderEventArgs (e.Graphics, this, this.GripRectangle, this.GripDisplayStyle, this.grip_style));
962                         e.Graphics.ResetTransform ();
963                 }
964
965                 protected virtual void OnRendererChanged (EventArgs e)
966                 {
967                         EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
968                         if (eh != null)
969                                 eh (this, e);
970                 }
971
972                 [EditorBrowsable (EditorBrowsableState.Advanced)]
973                 protected override void OnRightToLeftChanged (EventArgs e)
974                 {
975                         base.OnRightToLeftChanged (e);
976
977                         foreach (ToolStripItem tsi in this.Items)
978                                 tsi.OnParentRightToLeftChanged (e);
979                 }
980
981                 protected override void OnScroll (ScrollEventArgs se)
982                 {
983                         base.OnScroll (se);
984                 }
985                 
986                 protected override void OnTabStopChanged (EventArgs e)
987                 {
988                         base.OnTabStopChanged (e);
989                 }
990
991                 protected override void OnVisibleChanged (EventArgs e)
992                 {
993                         base.OnVisibleChanged (e);
994                 }
995
996                 protected override bool ProcessCmdKey (ref Message msg, Keys keyData)
997                 {
998                         return base.ProcessCmdKey (ref msg, keyData);
999                 }
1000
1001                 protected override bool ProcessDialogKey (Keys keyData)
1002                 {
1003                         if (!this.KeyboardActive)
1004                                 return false;
1005                                 
1006                         // Give each item a chance to handle the key
1007                         foreach (ToolStripItem tsi in this.Items)
1008                                 if (tsi.ProcessDialogKey (keyData))
1009                                         return true;
1010                         
1011                         // See if I want to handle it
1012                         if (this.ProcessArrowKey (keyData))
1013                                 return true;
1014                         
1015                         ToolStrip ts = null;
1016                         
1017                         switch (keyData) {
1018                                 case Keys.Escape:
1019                                         this.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1020                                         return true;
1021                         
1022                                 case Keys.Control | Keys.Tab:
1023                                         ts = ToolStripManager.GetNextToolStrip (this, true);
1024                                         
1025                                         if (ts != null) {
1026                                                 foreach (ToolStripItem tsi in this.Items)
1027                                                         tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1028
1029                                                 ToolStripManager.SetActiveToolStrip (ts);
1030                                                 ts.SelectNextToolStripItem (null, true);
1031                                         }
1032                                         
1033                                         return true;
1034                                 case Keys.Control | Keys.Shift | Keys.Tab:
1035                                         ts = ToolStripManager.GetNextToolStrip (this, false);
1036
1037                                         if (ts != null) {
1038                                                 foreach (ToolStripItem tsi in this.Items)
1039                                                         tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1040
1041                                                 ToolStripManager.SetActiveToolStrip (ts);
1042                                                 ts.SelectNextToolStripItem (null, true);
1043                                         }
1044                                         
1045                                         return true;
1046                                 case Keys.Down:
1047                                 case Keys.Up:
1048                                 case Keys.Left:
1049                                 case Keys.Right:
1050                                         if (GetCurrentlySelectedItem () is ToolStripControlHost)
1051                                                 return false;
1052                                         break;
1053                         }
1054
1055                         return base.ProcessDialogKey (keyData);
1056                 }
1057
1058                 protected override bool ProcessMnemonic (char charCode)
1059                 {
1060                         // If any item has an explicit mnemonic, it gets the message
1061                         foreach (ToolStripItem tsi in this.Items)
1062                                 if (tsi.Enabled && tsi.Visible && Control.IsMnemonic (charCode, tsi.Text))
1063                                         return tsi.ProcessMnemonic (charCode);
1064
1065                         string code = Char.ToUpper (charCode).ToString ();
1066                         
1067                         // If any item's text starts with our letter, it gets the message
1068                         foreach (ToolStripItem tsi in this.Items)
1069                                 if (tsi.Enabled && tsi.Visible && tsi.Text.Length > 0 && tsi.Text.ToUpper ().StartsWith (code))
1070                                         return tsi.ProcessMnemonic (charCode);
1071
1072                         return base.ProcessMnemonic (charCode);
1073                 }
1074                 
1075                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
1076                 {
1077                         base.SetBoundsCore (x, y, width, height, specified);
1078                 }
1079
1080                 protected virtual void SetDisplayedItems ()
1081                 {
1082                         this.displayed_items.Clear ();
1083                         
1084                         foreach (ToolStripItem tsi in this.items)
1085                                 if (tsi.Placement == ToolStripItemPlacement.Main && tsi.Available) {
1086                                         this.displayed_items.AddNoOwnerOrLayout (tsi);
1087                                         tsi.Parent = this; 
1088                                 }
1089                                 else if (tsi.Placement == ToolStripItemPlacement.Overflow)
1090                                         tsi.Parent = this.OverflowButton.DropDown; 
1091                         
1092                         if (this.OverflowButton != null)
1093                                 this.OverflowButton.DropDown.SetDisplayedItems ();
1094                 }
1095
1096                 protected internal void SetItemLocation (ToolStripItem item, Point location)
1097                 {
1098                         if (item == null)
1099                                 throw new ArgumentNullException ("item");
1100                                 
1101                         if (item.Owner != this)
1102                                 throw new NotSupportedException ("The item is not owned by this ToolStrip");
1103                                 
1104                         item.SetBounds (new Rectangle (location, item.Size));
1105                 }
1106                 
1107                 protected internal static void SetItemParent (ToolStripItem item, ToolStrip parent)
1108                 {
1109                         if (item.Parent != null) {
1110                                 item.Parent.Items.RemoveNoOwnerOrLayout (item);
1111                                 
1112                                 if (item.Parent is ToolStripOverflow)
1113                                         (item.Parent as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1114                         }
1115                         
1116                         parent.Items.AddNoOwnerOrLayout (item);
1117                         item.Parent = parent;
1118                 }
1119
1120                 protected override void SetVisibleCore (bool value)
1121                 {
1122                         base.SetVisibleCore (value);
1123                 }
1124
1125                 protected override void WndProc (ref Message m)
1126                 {
1127                         base.WndProc (ref m);
1128                 }
1129                 #endregion
1130
1131                 #region Public Events
1132                 static object ItemAddedEvent = new object ();
1133                 static object ItemClickedEvent = new object ();
1134                 static object ItemRemovedEvent = new object ();
1135                 static object LayoutCompletedEvent = new object ();
1136                 static object LayoutStyleChangedEvent = new object ();
1137                 static object PaintGripEvent = new object ();
1138                 static object RendererChangedEvent = new object ();
1139
1140                 [Browsable (true)]
1141                 [EditorBrowsable (EditorBrowsableState.Always)]
1142                 public new event EventHandler AutoSizeChanged {
1143                         add { base.AutoSizeChanged += value; }
1144                         remove { base.AutoSizeChanged -= value; }
1145                 }
1146
1147                 [Browsable (false)]
1148                 public new event EventHandler CausesValidationChanged {
1149                         add { base.CausesValidationChanged += value; }
1150                         remove { base.CausesValidationChanged -= value; }
1151                 }
1152
1153                 [Browsable (false)]
1154                 [EditorBrowsable (EditorBrowsableState.Never)]
1155                 public new event ControlEventHandler ControlAdded {
1156                         add { base.ControlAdded += value; }
1157                         remove { base.ControlAdded -= value; }
1158                 }
1159
1160                 [Browsable (false)]
1161                 [EditorBrowsable (EditorBrowsableState.Never)]
1162                 public new event ControlEventHandler ControlRemoved {
1163                         add { base.ControlRemoved += value; }
1164                         remove { base.ControlRemoved -= value; }
1165                 }
1166                 
1167                 [Browsable (false)]
1168                 public new event EventHandler CursorChanged {
1169                         add { base.CursorChanged += value; }
1170                         remove { base.CursorChanged -= value; }
1171                 }
1172
1173                 [Browsable (false)]
1174                 public new event EventHandler ForeColorChanged {
1175                         add { base.ForeColorChanged += value; }
1176                         remove { base.ForeColorChanged -= value; }
1177                 }
1178
1179                 public event ToolStripItemEventHandler ItemAdded {
1180                         add { Events.AddHandler (ItemAddedEvent, value); }
1181                         remove { Events.RemoveHandler (ItemAddedEvent, value); }
1182                 }
1183
1184                 public event ToolStripItemClickedEventHandler ItemClicked {
1185                         add { Events.AddHandler (ItemClickedEvent, value); }
1186                         remove { Events.RemoveHandler (ItemClickedEvent, value); }
1187                 }
1188
1189                 public event ToolStripItemEventHandler ItemRemoved {
1190                         add { Events.AddHandler (ItemRemovedEvent, value); }
1191                         remove { Events.RemoveHandler (ItemRemovedEvent, value); }
1192                 }
1193
1194                 public event EventHandler LayoutCompleted {
1195                         add { Events.AddHandler (LayoutCompletedEvent, value); }
1196                         remove { Events.RemoveHandler (LayoutCompletedEvent, value); }
1197                 }
1198
1199                 public event EventHandler LayoutStyleChanged {
1200                         add { Events.AddHandler (LayoutStyleChangedEvent, value); }
1201                         remove { Events.RemoveHandler (LayoutStyleChangedEvent, value); }
1202                 }
1203
1204                 public event PaintEventHandler PaintGrip {
1205                         add { Events.AddHandler (PaintGripEvent, value); }
1206                         remove { Events.RemoveHandler (PaintGripEvent, value); }
1207                 }
1208
1209                 public event EventHandler RendererChanged {
1210                         add { Events.AddHandler (RendererChangedEvent, value); }
1211                         remove { Events.RemoveHandler (RendererChangedEvent, value); }
1212                 }
1213                 #endregion
1214
1215                 #region Internal Properties
1216                 internal virtual bool KeyboardActive
1217                 {
1218                         get { return this.keyboard_active; }
1219                         set {
1220                                 if (this.keyboard_active != value) {
1221                                         this.keyboard_active = value;
1222                                         
1223                                         if (value)
1224                                                 Application.KeyboardCapture = this;
1225                                         else if (Application.KeyboardCapture == this)
1226                                                 Application.KeyboardCapture = null;
1227                                         
1228                                         // Redraw for mnemonic underlines
1229                                         this.Refresh ();
1230                                 }
1231                         }
1232                 }
1233                 #endregion
1234                 
1235                 #region Private Methods
1236                 internal void ChangeSelection (ToolStripItem nextItem)
1237                 {
1238                         if (Application.KeyboardCapture != this)
1239                                 ToolStripManager.SetActiveToolStrip (this);
1240                                 
1241                         foreach (ToolStripItem tsi in this.Items)
1242                                 if (tsi != nextItem)
1243                                         tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1244                                         
1245                         nextItem.Select ();
1246                         
1247                         if (nextItem.Parent is MenuStrip && (nextItem.Parent as MenuStrip).MenuDroppedDown)
1248                                 (nextItem as ToolStripMenuItem).HandleAutoExpansion ();
1249                 }
1250                 
1251                 internal virtual void Dismiss ()
1252                 {
1253                         this.Dismiss (ToolStripDropDownCloseReason.AppClicked);
1254                 }
1255                 
1256                 internal virtual void Dismiss (ToolStripDropDownCloseReason reason)
1257                 {
1258                         // Release our stranglehold on the keyboard
1259                         this.KeyboardActive = false;
1260                         
1261                         // Set our drop down flag to false;
1262                         this.menu_selected = false;
1263                         
1264                         // Make sure all of our items are deselected and repainted
1265                         foreach (ToolStripItem tsi in this.Items)
1266                                 tsi.Dismiss (reason);
1267                 }
1268                 
1269                 private void DoAutoSize ()
1270                 {
1271                         if (this.AutoSize == true && this.Dock == DockStyle.None)
1272                                 this.Size = GetPreferredSize (Size.Empty);
1273                                 
1274                         if (this.AutoSize == true && this.Orientation == Orientation.Horizontal && (this.Dock == DockStyle.Top || this.Dock == DockStyle.Bottom))
1275                                 this.Height = GetPreferredSize (Size.Empty).Height;
1276                 }
1277
1278                 internal ToolStripItem GetCurrentlySelectedItem ()
1279                 {
1280                         foreach (ToolStripItem tsi in this.DisplayedItems)
1281                                 if (tsi.Selected)
1282                                         return tsi;
1283                                         
1284                         return null;
1285                 }
1286                 
1287                 public override Size GetPreferredSize (Size proposedSize)
1288                 {
1289                         Size new_size = new Size (0, this.Height);
1290
1291                         if (this.orientation == Orientation.Vertical) {
1292                                 foreach (ToolStripItem tsi in this.items)
1293                                         if (tsi.GetPreferredSize (Size.Empty).Height + tsi.Margin.Top + tsi.Margin.Bottom > new_size.Height)
1294                                                 new_size.Height = tsi.GetPreferredSize (Size.Empty).Height + tsi.Margin.Top + tsi.Margin.Bottom;
1295
1296                                 new_size.Height += this.Padding.Top + this.Padding.Bottom;
1297                                 new_size.Width = this.Width;
1298                         } else {
1299                                 foreach (ToolStripItem tsi in this.items) 
1300                                         if (tsi.Available) {
1301                                                 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1302                                                 new_size.Width += tsi_preferred.Width + tsi.Margin.Left + tsi.Margin.Right;
1303                                                 
1304                                                 if (new_size.Height < (this.Padding.Vertical + tsi_preferred.Height))
1305                                                         new_size.Height = (this.Padding.Vertical + tsi_preferred.Height);
1306                                         }
1307                         }
1308
1309                         new_size.Width += (this.GripRectangle.Width + this.GripMargin.Horizontal + this.Padding.Horizontal + 4);
1310                         return new_size;
1311                 }
1312                 
1313                 internal virtual ToolStrip GetTopLevelToolStrip ()
1314                 {
1315                         return this;
1316                 }
1317                 
1318                 internal void HandleItemClick (ToolStripItem dismissingItem)
1319                 {
1320                         this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.ItemClicked);
1321                         this.OnItemClicked (new ToolStripItemClickedEventArgs (dismissingItem));
1322                 }
1323                 
1324                 internal void HideMenus (bool release, ToolStripDropDownCloseReason reason)
1325                 {
1326                         if (this is MenuStrip && release && menu_selected)
1327                                 (this as MenuStrip).FireMenuDeactivate ();
1328                                 
1329                         if (release)
1330                                 menu_selected = false;
1331                                 
1332                         NotifySelectedChanged (null);
1333                 }
1334
1335                 internal void NotifySelectedChanged (ToolStripItem tsi)
1336                 {
1337                         foreach (ToolStripItem tsi2 in this.DisplayedItems)
1338                                 if (tsi != tsi2)
1339                                         if (tsi2 is ToolStripDropDownItem)
1340                                                 (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1341
1342                         if (this.OverflowButton != null) {
1343                                 ToolStripItemCollection tsic = this.OverflowButton.DropDown.DisplayedItems;
1344                                 
1345                                 foreach (ToolStripItem tsi2 in tsic)
1346                                         if (tsi != tsi2)
1347                                                 if (tsi2 is ToolStripDropDownItem)
1348                                                         (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1349                         
1350                                 this.OverflowButton.HideDropDown ();
1351                         }
1352                         
1353                         foreach (ToolStripItem tsi2 in this.Items)
1354                                 if (tsi != tsi2)
1355                                         tsi2.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1356                 }
1357                 
1358                 internal virtual bool OnMenuKey ()
1359                 {
1360                         return false;
1361                 }
1362
1363                 internal virtual bool ProcessArrowKey (Keys keyData)
1364                 {
1365                         ToolStripItem tsi;
1366                         
1367                         switch (keyData) {
1368                                 case Keys.Right:
1369                                         tsi = this.GetCurrentlySelectedItem ();
1370                                         
1371                                         if (tsi is ToolStripControlHost)
1372                                                 return false;
1373                                         
1374                                         tsi = this.SelectNextToolStripItem (tsi, true);
1375                                         
1376                                         if (tsi is ToolStripControlHost)
1377                                                 (tsi as ToolStripControlHost).Focus ();
1378                                                 
1379                                         return true;
1380                                 case Keys.Tab:
1381                                         tsi = this.GetCurrentlySelectedItem ();
1382
1383                                         tsi = this.SelectNextToolStripItem (tsi, true);
1384
1385                                         if (tsi is ToolStripControlHost)
1386                                                 (tsi as ToolStripControlHost).Focus ();
1387                                                 
1388                                         return true;
1389                                 case Keys.Left:
1390                                         tsi = this.GetCurrentlySelectedItem ();
1391
1392                                         if (tsi is ToolStripControlHost)
1393                                                 return false;
1394
1395                                         tsi = this.SelectNextToolStripItem (tsi, false);
1396
1397                                         if (tsi is ToolStripControlHost)
1398                                                 (tsi as ToolStripControlHost).Focus ();
1399
1400                                         return true;
1401                                 case Keys.Shift | Keys.Tab:
1402                                         tsi = this.GetCurrentlySelectedItem ();
1403                                         
1404                                         tsi = this.SelectNextToolStripItem (tsi, false);
1405
1406                                         if (tsi is ToolStripControlHost)
1407                                                 (tsi as ToolStripControlHost).Focus ();
1408
1409                                         return true;
1410                         }
1411
1412                         return false;
1413                 }
1414
1415                 internal virtual ToolStripItem SelectNextToolStripItem (ToolStripItem start, bool forward)
1416                 {
1417                         ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Right : ArrowDirection.Left);
1418                         
1419                         this.ChangeSelection (next_item);
1420
1421                         if (next_item is ToolStripControlHost)
1422                                 (next_item as ToolStripControlHost).Focus ();
1423                 
1424                         return next_item;
1425                 }
1426
1427                 #region Stuff for ToolTips
1428                 private void MouseEnteredItem (ToolStripItem item)
1429                 {
1430                         if (this.show_item_tool_tips) {
1431                                 tooltip_currently_showing = item;
1432                                 ToolTipTimer.Start ();
1433                         }
1434                 }
1435                 
1436                 private void MouseLeftItem (ToolStripItem item)
1437                 {
1438                         ToolTipTimer.Stop ();
1439                         ToolTipWindow.Hide ();
1440                         tooltip_currently_showing = null;
1441                 }
1442                 
1443                 private Timer ToolTipTimer {
1444                         get {
1445                                 if (tooltip_timer == null) {
1446                                         tooltip_timer = new Timer ();
1447                                         tooltip_timer.Enabled = false;
1448                                         tooltip_timer.Interval = 500;
1449                                         tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
1450                                 }
1451                                 
1452                                 return tooltip_timer;
1453                         }
1454                 }
1455                 
1456                 private ToolTip.ToolTipWindow ToolTipWindow {
1457                         get {
1458                                 if (tooltip_window == null)
1459                                         tooltip_window = new ToolTip.ToolTipWindow ();
1460                                         
1461                                 return tooltip_window;
1462                         }
1463                 }
1464                 
1465                 private void ToolTipTimer_Tick (object o, EventArgs args)
1466                 {
1467                         string tooltip = tooltip_currently_showing.GetToolTip ();
1468                         
1469                         if (!string.IsNullOrEmpty (tooltip))
1470                                 ToolTipWindow.Present (this, tooltip);
1471
1472                         tooltip_currently_showing.FireEvent (EventArgs.Empty, ToolStripItemEventType.MouseHover);
1473
1474                         ToolTipTimer.Stop ();
1475                 }
1476                 #endregion
1477
1478                 #region Stuff for Merging
1479                 internal ToolStrip CurrentlyMergedWith {
1480                         get { return this.currently_merged_with; }
1481                         set { this.currently_merged_with = value; }
1482                 }
1483                 
1484                 internal List<ToolStripItem> HiddenMergedItems {
1485                         get {
1486                                 if (this.hidden_merged_items == null)
1487                                         this.hidden_merged_items = new List<ToolStripItem> ();
1488                                         
1489                                 return this.hidden_merged_items;
1490                         }
1491                 }
1492                 
1493                 internal bool IsCurrentlyMerged {
1494                         get { return this.is_currently_merged; }
1495                         set { 
1496                                 this.is_currently_merged = value; 
1497                                 
1498                                 if (!value && this is MenuStrip) 
1499                                         foreach (ToolStripMenuItem tsmi in this.Items)
1500                                                 tsmi.DropDown.IsCurrentlyMerged = value;
1501                          }
1502                 }
1503                 
1504                 internal void BeginMerge ()
1505                 {
1506                         if (!IsCurrentlyMerged) {
1507                                 IsCurrentlyMerged = true;
1508                                 
1509                                 if (this.pre_merge_items == null) {
1510                                         this.pre_merge_items = new List<ToolStripItem> ();
1511                         
1512                                 foreach (ToolStripItem tsi in this.Items)
1513                                         this.pre_merge_items.Add (tsi);
1514                                 }
1515                                 
1516                                 if (this is MenuStrip)
1517                                         foreach (ToolStripMenuItem tsmi in this.Items)
1518                                                 tsmi.DropDown.BeginMerge ();
1519                         }
1520                 }
1521                 
1522                 internal void RevertMergeItem (ToolStripItem item)
1523                 {
1524                         int index = 0;
1525
1526                         // Remove it from it's current Parent
1527                         if (item.Parent != null && item.Parent != this) {
1528                                 if (item.Parent is ToolStripOverflow)
1529                                         (item.Parent as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1530                                 else
1531                                         item.Parent.Items.RemoveNoOwnerOrLayout (item);
1532
1533                                 item.Parent = item.Owner;       
1534                         }
1535                         
1536                         // Find where the item was before the merge
1537                         index = item.Owner.pre_merge_items.IndexOf (item);
1538
1539                         // Find the first pre-merge item that was after this item, that
1540                         // is currently in the Items collection.  Insert our item before
1541                         // that one.
1542                         for (int i = index; i < this.pre_merge_items.Count; i++) {
1543                                 if (this.Items.Contains (this.pre_merge_items[i])) {
1544                                         item.Owner.Items.InsertNoOwnerOrLayout (this.Items.IndexOf (this.pre_merge_items[i]), item);
1545                                         return;
1546                                 }
1547                         }
1548                         
1549                         // There aren't any items that are supposed to be after this item,
1550                         // so just append it to the end.
1551                         item.Owner.Items.AddNoOwnerOrLayout (item);
1552                 }
1553                 #endregion
1554                 #endregion
1555         }
1556 }
1557 #endif