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