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