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