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