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