2007-04-17 Everaldo Canuto <everaldo@simios.org>
[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
37 namespace System.Windows.Forms
38 {
39         [ComVisible (true)]
40         [ClassInterface (ClassInterfaceType.AutoDispatch)]
41         [DefaultEvent ("ItemClicked")]
42         [DefaultProperty ("Items")]
43         public class ToolStrip : ScrollableControl, IComponent, IDisposable
44         {
45                 #region Private Variables
46                 private bool allow_merge;
47                 private Color back_color;
48                 private bool can_overflow;
49                 private ToolStrip currently_merged_with;
50                 private ToolStripDropDownDirection default_drop_down_direction;
51                 internal ToolStripItemCollection displayed_items;
52                 private Color fore_color;
53                 private Padding grip_margin;
54                 private ToolStripGripStyle grip_style;
55                 private List<ToolStripItem> hidden_merged_items;
56                 private ImageList image_list;
57                 private Size image_scaling_size;
58                 private bool is_currently_merged;
59                 private ToolStripItemCollection items;
60                 private LayoutEngine layout_engine;
61                 private LayoutSettings layout_settings;
62                 private ToolStripLayoutStyle layout_style;
63                 private Orientation orientation;
64                 private ToolStripOverflowButton overflow_button;
65                 private List<ToolStripItem> pre_merge_items;
66                 private ToolStripRenderer renderer;
67                 private ToolStripRenderMode render_mode;
68                 private Timer tooltip_timer;
69                 private ToolTip.ToolTipWindow tooltip_window;
70                 private bool show_item_tool_tips;
71                 private bool stretch;
72
73                 private ToolStripItem mouse_currently_over;
74                 private bool menu_selected;
75                 private ToolStripItem tooltip_currently_showing;
76                 #endregion
77
78                 #region Public Constructors
79                 public ToolStrip () : this (null)
80                 {
81                 }
82
83                 public ToolStrip (params ToolStripItem[] items) : base ()
84                 {
85                         SetStyle (ControlStyles.AllPaintingInWmPaint, true);
86                         SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
87                         SetStyle (ControlStyles.Selectable, false);
88                         SetStyle (ControlStyles.SupportsTransparentBackColor, true);
89
90                         this.SuspendLayout ();
91                         this.items = new ToolStripItemCollection (this, items);
92                         this.allow_merge = true;
93                         base.AutoSize = true;
94                         this.back_color = Control.DefaultBackColor;
95                         this.can_overflow = true;
96                         base.CausesValidation = false;
97                         this.default_drop_down_direction = ToolStripDropDownDirection.BelowRight;
98                         this.displayed_items = new ToolStripItemCollection (this, null);
99                         this.Dock = this.DefaultDock;
100                         base.Font = new Font ("Tahoma", 8.25f);
101                         this.fore_color = Control.DefaultForeColor;
102                         this.grip_margin = this.DefaultGripMargin;
103                         this.grip_style = ToolStripGripStyle.Visible;
104                         this.image_scaling_size = new Size (16, 16);
105                         this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow;
106                         this.orientation = Orientation.Horizontal;
107                         if (!(this is ToolStripDropDown))
108                                 this.overflow_button = new ToolStripOverflowButton (this);
109                         this.Padding = this.DefaultPadding;
110                         this.renderer = null;
111                         this.render_mode = ToolStripRenderMode.ManagerRenderMode;
112                         this.show_item_tool_tips = this.DefaultShowItemToolTips;
113                         base.TabStop = false;
114                         this.ResumeLayout ();
115                         DoAutoSize ();
116                         
117                         // Register with the ToolStripManager
118                         ToolStripManager.AddToolStrip (this);
119                 }
120                 #endregion
121
122                 #region Public Properties
123                 public bool AllowMerge {
124                         get { return this.allow_merge; }
125                         set { this.allow_merge = false; }
126                 }
127                 
128                 public override AnchorStyles Anchor {
129                         get { return base.Anchor; }
130                         set { base.Anchor = value; }
131                 }
132
133                 [Browsable (false)]
134                 [EditorBrowsable (EditorBrowsableState.Never)]
135                 public override bool AutoScroll {
136                         get { return base.AutoScroll; }
137                         set { base.AutoScroll = value; }
138                 }
139
140                 [Browsable (false)]
141                 [EditorBrowsable (EditorBrowsableState.Never)]
142                 public new Size AutoScrollMargin {
143                         get { return base.AutoScrollMargin; }
144                         set { base.AutoScrollMargin = value; }
145                 }
146
147                 [Browsable (false)]
148                 [EditorBrowsable (EditorBrowsableState.Never)]
149                 public new Size AutoScrollMinSize {
150                         get { return base.AutoScrollMinSize; }
151                         set { base.AutoScrollMinSize = value; }
152                 }
153
154                 [Browsable (false)]
155                 [EditorBrowsable (EditorBrowsableState.Never)]
156                 public new Point AutoScrollPosition {
157                         get { return base.AutoScrollPosition; }
158                         set { base.AutoScrollPosition = value; }
159                 }
160
161                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
162                 [Browsable (true)]
163                 [EditorBrowsable (EditorBrowsableState.Always)]
164                 [DefaultValue (true)]
165                 public override bool AutoSize {
166                         get { return base.AutoSize; }
167                         set { base.AutoSize = value; }
168                 }
169                 
170                 new public Color BackColor {
171                         get { return this.back_color; }
172                         set { this.back_color = value; }
173                 }
174
175                 [DefaultValue (true)]
176                 public bool CanOverflow {
177                         get { return this.can_overflow; }
178                         set { this.can_overflow = value; }
179                 }
180                 
181                 [Browsable (false)]
182                 [DefaultValue (false)]
183                 public new bool CausesValidation {
184                         get { return base.CausesValidation; }
185                         set { base.CausesValidation = value; }
186                 }
187                 
188                 [EditorBrowsable (EditorBrowsableState.Never)]
189                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
190                 public new ControlCollection Controls {
191                         get { return base.Controls; }
192                 }
193
194                 [Browsable (false)]
195                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
196                 public override Cursor Cursor {
197                         get { return base.Cursor; }
198                         set { base.Cursor = value; }
199                 }
200                 
201                 [Browsable (false)]
202                 public virtual ToolStripDropDownDirection DefaultDropDownDirection {
203                         get { return this.default_drop_down_direction; }
204                         set { 
205                                 if (!Enum.IsDefined (typeof (ToolStripDropDownDirection), value))
206                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripDropDownDirection", value));
207                                         
208                                 this.default_drop_down_direction = value;
209                         }
210                 }
211
212                 public override Rectangle DisplayRectangle {
213                         get {
214                                 if (this.orientation == Orientation.Horizontal)
215                                         if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
216                                                 return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical);
217                                         else
218                                                 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);
219                                 else
220                                         if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
221                                                 return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical);
222                                         else
223                                                 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);
224                         }
225                 }
226
227                 [DefaultValue (DockStyle.Top)]
228                 public override DockStyle Dock {
229                         get { return base.Dock; }
230                         set {
231                                 if (base.Dock != value) {
232                                         base.Dock = value;
233                                         
234                                         switch (value) {
235                                                 case DockStyle.Top:
236                                                 case DockStyle.Bottom:
237                                                 case DockStyle.None:
238                                                         this.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
239                                                         break;
240                                                 case DockStyle.Left:
241                                                 case DockStyle.Right:
242                                                         this.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
243                                                         break;
244                                         }
245                                 }
246                         }
247                 }
248
249                 public override Font Font {
250                         get { return base.Font; }
251                         set { 
252                                 if (base.Font != value) {
253                                         base.Font = value;
254                                         
255                                         foreach (ToolStripItem tsi in this.Items)
256                                                 tsi.OnOwnerFontChanged (EventArgs.Empty);
257                                 }
258                          }
259                 }
260                 
261                 [Browsable (false)]
262                 public new Color ForeColor {
263                         get { return this.fore_color; }
264                         set { 
265                                 if (this.fore_color != value) {
266                                         this.fore_color = value; 
267                                         this.OnForeColorChanged (EventArgs.Empty); 
268                                 }
269                         }
270                 }
271
272                 [Browsable (false)]
273                 public ToolStripGripDisplayStyle GripDisplayStyle {
274                         get { return this.orientation == Orientation.Vertical ? ToolStripGripDisplayStyle.Horizontal : ToolStripGripDisplayStyle.Vertical; }
275                 }
276
277                 public Padding GripMargin {
278                         get { return this.grip_margin; }
279                         set { 
280                                 if (this.grip_margin != value) {
281                                         this.grip_margin = value; 
282                                         this.PerformLayout (); 
283                                 }
284                         }
285                 }
286
287                 [Browsable (false)]
288                 public Rectangle GripRectangle {
289                         get {
290                                 if (this.grip_style == ToolStripGripStyle.Hidden)
291                                         return Rectangle.Empty;
292
293                                 if (this.orientation == Orientation.Horizontal)
294                                         return new Rectangle (this.grip_margin.Left + this.Padding.Left, this.Padding.Top, 3, this.Height);
295                                 else
296                                         return new Rectangle (this.Padding.Left, this.grip_margin.Top + this.Padding.Top, this.Width, 3);
297                         }
298                 }
299
300                 [DefaultValue (ToolStripGripStyle.Visible)]
301                 public ToolStripGripStyle GripStyle {
302                         get { return this.grip_style; }
303                         set {
304                                 if (this.grip_style != value) {
305                                         if (!Enum.IsDefined (typeof (ToolStripGripStyle), value))
306                                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripGripStyle", value));
307                                         this.grip_style = value;
308                                         this.PerformLayout ();
309                                 }
310                         }
311                 }
312
313                 [Browsable (false)]
314                 [EditorBrowsable (EditorBrowsableState.Never)]
315                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
316                 public new bool HasChildren {
317                         get { return base.HasChildren; }
318                 }
319
320                 [Browsable (false)]
321                 [EditorBrowsable (EditorBrowsableState.Never)]
322                 public new HScrollProperties HorizontalScroll {
323                         get { return base.HorizontalScroll; }
324                 }
325                 
326                 [Browsable (false)]
327                 [DefaultValue (null)]
328                 public ImageList ImageList {
329                         get { return this.image_list; }
330                         set { this.image_list = value; }
331                 }
332
333                 [DefaultValue ("{Width=16, Height=16}")]
334                 public Size ImageScalingSize {
335                         get { return this.image_scaling_size; }
336                         set { this.image_scaling_size = value; }
337                 }
338
339                 [MonoTODO ("Always returns false, dragging not implemented yet.")]
340                 [Browsable (false)]
341                 [EditorBrowsable (EditorBrowsableState.Advanced)]
342                 public bool IsCurrentlyDragging {
343                         get { return false; }
344                 }
345                 
346                 [Browsable (false)]
347                 public bool IsDropDown {
348                         get {
349                                 if (this is ToolStripDropDown)
350                                         return true;
351
352                                 return false;
353                         }
354                 }
355
356                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
357                 public virtual ToolStripItemCollection Items {
358                         get { return this.items; }
359                 }
360
361                 public override LayoutEngine LayoutEngine {
362                         get { 
363                                  if (layout_engine == null)
364                                         this.layout_engine = new ToolStripSplitStackLayout ();
365                                         
366                                  return this.layout_engine;
367                         }
368                 }
369
370                 [Browsable (false)]
371                 [DefaultValue (null)]
372                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
373                 public LayoutSettings LayoutSettings {
374                         get { return this.layout_settings; }
375                         set { this.layout_settings = value; }
376                 }
377                 
378                 [AmbientValue (ToolStripLayoutStyle.StackWithOverflow)]
379                 public ToolStripLayoutStyle LayoutStyle {
380                         get { return layout_style; }
381                         set {
382                                 if (this.layout_style != value) {
383                                         if (!Enum.IsDefined (typeof (ToolStripLayoutStyle), value))
384                                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripLayoutStyle", value));
385
386                                         this.layout_style = value;
387
388                                         if (this.layout_style == ToolStripLayoutStyle.Flow)
389                                                 this.layout_engine = new FlowLayout ();
390                                         else
391                                                 this.layout_engine = new ToolStripSplitStackLayout ();
392
393                                         if (this.layout_style == ToolStripLayoutStyle.StackWithOverflow) {
394                                                 if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
395                                                         this.layout_style = ToolStripLayoutStyle.VerticalStackWithOverflow;
396                                                 else
397                                                         this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow;
398                                         }
399
400                                         if (this.layout_style == ToolStripLayoutStyle.HorizontalStackWithOverflow)
401                                                 this.orientation = Orientation.Horizontal;
402                                         else if (this.layout_style == ToolStripLayoutStyle.VerticalStackWithOverflow)
403                                                 this.orientation = Orientation.Vertical;
404                                                 
405                                         this.layout_settings = this.CreateLayoutSettings (value);
406                                         
407                                         this.PerformLayout ();
408                                         this.OnLayoutStyleChanged (EventArgs.Empty);
409                                 }
410                         }
411                 }
412
413                 [Browsable (false)]
414                 public Orientation Orientation {
415                         get { return this.orientation; }
416                 }
417
418                 [Browsable (false)]
419                 [EditorBrowsable (EditorBrowsableState.Advanced)]
420                 public ToolStripOverflowButton OverflowButton {
421                         get { return this.overflow_button; }
422                 }
423                 
424                 [Browsable (false)]
425                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
426                 public ToolStripRenderer Renderer {
427                         get { 
428                                 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
429                                         return ToolStripManager.Renderer;
430                                         
431                                 return this.renderer; 
432                         }
433                         set { 
434                                 if (this.renderer != value) {
435                                         this.renderer = value; 
436                                         this.render_mode = ToolStripRenderMode.Custom;
437                                         this.PerformLayout ();
438                                         this.OnRendererChanged (EventArgs.Empty);
439                                 }
440                         }
441                 }
442
443                 public ToolStripRenderMode RenderMode {
444                         get { return this.render_mode; }
445                         set {
446                                 if (!Enum.IsDefined (typeof (ToolStripRenderMode), value))
447                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value));
448
449                                 if (value == ToolStripRenderMode.Custom && this.renderer == null)
450                                         throw new NotSupportedException ("Must set Renderer property before setting RenderMode to Custom");
451                                 if (value == ToolStripRenderMode.Professional || value == ToolStripRenderMode.System)
452                                         this.Renderer = new ToolStripProfessionalRenderer ();
453
454                                 this.render_mode = value;
455                         }
456                 }
457
458                 [DefaultValue (true)]
459                 public bool ShowItemToolTips {
460                         get { return this.show_item_tool_tips; }
461                         set { this.show_item_tool_tips = value; }
462                 }
463                 
464                 [DefaultValue (false)]
465                 public bool Stretch {
466                         get { return this.stretch; }
467                         set { this.stretch = value; }
468                 }
469                 
470                 [DefaultValue (false)]
471                 [DispId(-516)]
472                 public new bool TabStop {
473                         get { return base.TabStop; }
474                         set { base.TabStop = value; }
475                 }
476
477                 [Browsable (false)]
478                 [EditorBrowsable (EditorBrowsableState.Never)]
479                 public new VScrollProperties VerticalScroll {
480                         get { return base.VerticalScroll; }
481                 }
482                 #endregion
483
484                 #region Protected Properties
485                 protected virtual DockStyle DefaultDock { get { return DockStyle.Top; } }
486                 protected virtual Padding DefaultGripMargin { get { return new Padding (2); } }
487                 protected override Padding DefaultMargin { get { return Padding.Empty; } }
488                 protected override Padding DefaultPadding { get { return new Padding (0, 0, 1, 0); } }
489                 protected virtual bool DefaultShowItemToolTips { get { return true; } }
490                 protected override Size DefaultSize { get { return new Size (100, 25); } }
491                 protected internal virtual ToolStripItemCollection DisplayedItems { get { return this.displayed_items; } }
492                 #endregion
493
494                 #region Public Methods
495                 public new Control GetChildAtPoint (Point point)
496                 {
497                         return base.GetChildAtPoint (point);
498                 }
499                 
500                 public ToolStripItem GetItemAt (Point point)
501                 {
502                         foreach (ToolStripItem tsi in this.displayed_items)
503                                 if (tsi.Visible && tsi.Bounds.Contains (point))
504                                         return tsi;
505
506                         return null;
507                 }
508
509                 public ToolStripItem GetItemAt (int x, int y)
510                 {
511                         return GetItemAt (new Point (x, y));
512                 }
513
514                 public virtual ToolStripItem GetNextItem (ToolStripItem start, ArrowDirection direction)
515                 {
516                         if (!Enum.IsDefined (typeof (ArrowDirection), direction))
517                                 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ArrowDirection", direction));
518
519                         int index = this.items.IndexOf (start);
520
521                         switch (direction) {
522                                 case ArrowDirection.Left:
523                                 case ArrowDirection.Up:
524                                         if (index > 0)
525                                                 return this.items[index - 1];
526         
527                                         return this.items[this.items.Count - 1];
528                                 case ArrowDirection.Right:
529                                 case ArrowDirection.Down:
530                                         if (index + 1 >= this.items.Count)
531                                                 return this.items[0];
532
533                                         return this.items[index + 1];
534                         }
535
536                         return null;
537                 }
538
539                 public void ResetMinimumSize ()
540                 {
541                         this.MinimumSize = new Size (-1, -1);
542                 }
543
544                 [Browsable (false)]
545                 [EditorBrowsable (EditorBrowsableState.Never)]
546                 public new void SetAutoScrollMargin (int x, int y)
547                 {
548                         base.SetAutoScrollMargin (x, y);
549                 }
550                 
551                 public override string ToString ()
552                 {
553                         return String.Format ("{0}, Name: {1}, Items: {2}", base.ToString(), this.Name, this.items.Count.ToString ());
554                 }
555                 #endregion
556
557                 #region Protected Methods
558                 protected override AccessibleObject CreateAccessibilityInstance ()
559                 {
560                         AccessibleObject ao = new AccessibleObject (this);
561                         
562                         ao.role = AccessibleRole.ToolBar;
563                         
564                         return ao;
565                 }
566                 
567                 protected override ControlCollection CreateControlsInstance ()
568                 {
569                         return base.CreateControlsInstance ();
570                 }
571
572                 protected internal virtual ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick)
573                 {
574                         if (text == "-")
575                                 return new ToolStripSeparator ();
576
577                         if (this is ToolStripDropDown)
578                                 return new ToolStripMenuItem (text, image, onClick);
579                                 
580                         return new ToolStripButton (text, image, onClick);
581                 }
582
583                 protected virtual LayoutSettings CreateLayoutSettings (ToolStripLayoutStyle layoutStyle)
584                 {
585                         switch (layoutStyle) {
586                                 case ToolStripLayoutStyle.Flow:
587                                         return new FlowLayoutSettings ();
588                                 case ToolStripLayoutStyle.Table:
589                                         //return new TableLayoutSettings ();
590                                 case ToolStripLayoutStyle.StackWithOverflow:
591                                 case ToolStripLayoutStyle.HorizontalStackWithOverflow:
592                                 case ToolStripLayoutStyle.VerticalStackWithOverflow:
593                                 default:
594                                         return null;
595                         }
596                 }
597                 
598                 protected override void Dispose (bool disposing)
599                 {
600                         if (!IsDisposed) {
601                                 ToolStripManager.RemoveToolStrip (this);
602                                 base.Dispose (disposing);
603                         }
604                 }
605                 
606                 protected override void OnDockChanged (EventArgs e)
607                 {
608                         base.OnDockChanged (e);
609                 }
610
611                 protected override void OnEnabledChanged (EventArgs e)
612                 {
613                         base.OnEnabledChanged (e);
614                         
615                         foreach (ToolStripItem tsi in this.Items)
616                                 tsi.OnParentEnabledChanged (EventArgs.Empty);
617                 }
618
619                 protected override void OnFontChanged (EventArgs e)
620                 {
621                         base.OnFontChanged (e);
622                 }
623
624                 protected override void OnHandleCreated (EventArgs e)
625                 {
626                         base.OnHandleCreated (e);
627                 }
628
629                 protected override void OnHandleDestroyed (EventArgs e)
630                 {
631                         base.OnHandleDestroyed (e);
632                 }
633
634                 protected override void OnInvalidated (InvalidateEventArgs e)
635                 {
636                         base.OnInvalidated (e);
637                 }
638
639                 protected internal virtual void OnItemAdded (ToolStripItemEventArgs e)
640                 {
641                         e.Item.Available = true;
642                         e.Item.SetPlacement (ToolStripItemPlacement.Main);
643                         this.DoAutoSize ();
644                         this.PerformLayout ();
645                         
646                         ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemAddedEvent]);
647                         if (eh != null)
648                                 eh (this, e);
649                 }
650
651                 protected virtual void OnItemClicked (ToolStripItemClickedEventArgs e)
652                 {
653                         ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [ItemClickedEvent]);
654                         if (eh != null)
655                                 eh (this, e);
656                 }
657
658                 protected internal virtual void OnItemRemoved (ToolStripItemEventArgs e)
659                 {
660                         ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemRemovedEvent]);
661                         if (eh != null)
662                                 eh (this, e);
663                 }
664
665                 protected override void OnLayout (LayoutEventArgs e)
666                 {
667                         DoAutoSize ();
668                         base.OnLayout (e);
669
670                         this.SetDisplayedItems ();
671                         this.OnLayoutCompleted (EventArgs.Empty);
672                         this.Invalidate ();
673                 }
674
675                 protected virtual void OnLayoutCompleted (EventArgs e)
676                 {
677                         EventHandler eh = (EventHandler)(Events [LayoutCompletedEvent]);
678                         if (eh != null)
679                                 eh (this, e);
680                 }
681
682                 protected virtual void OnLayoutStyleChanged (EventArgs e)
683                 {
684                         EventHandler eh = (EventHandler)(Events[LayoutStyleChangedEvent]);
685                         if (eh != null)
686                                 eh (this, e);
687                 }
688
689                 protected override void OnLeave (EventArgs e)
690                 {
691                         base.OnLeave (e);
692                 }
693
694                 protected override void OnLostFocus (EventArgs e)
695                 {
696                         base.OnLostFocus (e);
697                 }
698
699                 protected override void OnMouseCaptureChanged (EventArgs e)
700                 {
701                         base.OnMouseCaptureChanged (e);
702                 }
703                 
704                 protected override void OnMouseDown (MouseEventArgs mea)
705                 {
706                         if (mouse_currently_over != null)
707                         {
708                                 if (this is MenuStrip && !(mouse_currently_over as ToolStripMenuItem).HasDropDownItems) {
709                                         if (!menu_selected)
710                                                 (this as MenuStrip).FireMenuActivate ();
711                                         
712                                         return;
713                                 }
714                                         
715                                 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseDown);
716                                 
717                                 if (this is MenuStrip && !menu_selected) {
718                                         (this as MenuStrip).FireMenuActivate ();
719                                         menu_selected = true;                           
720                                 }
721                         } else {
722                                 if (this is MenuStrip)
723                                         this.HideMenus (true, ToolStripDropDownCloseReason.AppClicked);
724                         }
725                         
726                         if (this is MenuStrip)
727                                 this.Capture = false;
728
729                         base.OnMouseDown (mea);
730                 }
731
732                 protected override void OnMouseLeave (EventArgs e)
733                 {
734                         if (mouse_currently_over != null) {
735                                 MouseLeftItem (mouse_currently_over);
736                                 mouse_currently_over.FireEvent (e, ToolStripItemEventType.MouseLeave);
737                                 mouse_currently_over = null;
738                         }
739
740                         base.OnMouseLeave (e);
741                 }
742
743                 protected override void OnMouseMove (MouseEventArgs mea)
744                 {
745                         ToolStripItem tsi;
746                         // Find the item we are now 
747                         if (this.overflow_button != null && this.overflow_button.Visible && this.overflow_button.Bounds.Contains (mea.Location))
748                                 tsi = this.overflow_button;
749                         else
750                                 tsi = this.GetItemAt (mea.X, mea.Y);
751
752                         if (tsi != null) {
753                                 // If we were already hovering on this item, just send a mouse move
754                                 if (tsi == mouse_currently_over) 
755                                         tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
756                                 else {
757                                         // If we were over a different item, fire a mouse leave on it
758                                         if (mouse_currently_over != null) {
759                                                 MouseLeftItem (tsi);
760                                                 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
761                                         }
762                                         
763                                         // Set the new item we are currently over
764                                         mouse_currently_over = tsi;
765                                         
766                                         // Fire mouse enter and mouse move
767                                         tsi.FireEvent (mea, ToolStripItemEventType.MouseEnter);
768                                         MouseEnteredItem (tsi);
769                                         tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
770
771                                         // If we're over something with a drop down, show it
772                                         if (menu_selected && mouse_currently_over.Enabled && mouse_currently_over is ToolStripDropDownItem && (mouse_currently_over as ToolStripDropDownItem).HasDropDownItems)
773                                                 (mouse_currently_over as ToolStripDropDownItem).ShowDropDown ();
774                                 }
775                         } else {
776                                 // We're not over anything now, just fire the mouse leave on what we used to be over
777                                 if (mouse_currently_over != null) {
778                                         MouseLeftItem (tsi);
779                                         mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
780                                         mouse_currently_over = null;
781                                 }
782                         }
783                         
784                         base.OnMouseMove (mea);
785                 }
786
787                 protected override void OnMouseUp (MouseEventArgs mea)
788                 {
789                         // If we're currently over an item (set in MouseMove)
790                         if (mouse_currently_over != null) {
791                                 // Fire the item's MouseUp event
792                                 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseUp);
793
794                                 // The event handler may have blocked until the mouse moved off of the ToolStripItem
795                                 if (mouse_currently_over == null)
796                                         return;
797                                         
798                                 // Fire our ItemClicked event
799                                 OnItemClicked (new ToolStripItemClickedEventArgs (mouse_currently_over));
800                         }
801
802                         base.OnMouseUp (mea);
803                 }
804
805                 protected override void OnPaint (PaintEventArgs e)
806                 {
807                         base.OnPaint (e);
808
809                         // Draw the grip
810                         this.OnPaintGrip (e);
811
812                         // Make each item draw itself
813                         foreach (ToolStripItem tsi in this.displayed_items) {
814                                 e.Graphics.TranslateTransform (tsi.Bounds.Left, tsi.Bounds.Top);
815                                 tsi.FireEvent (e, ToolStripItemEventType.Paint);
816                                 e.Graphics.ResetTransform ();
817                         }
818
819                         // Paint the Overflow button if it's visible
820                         if (this.overflow_button != null && this.overflow_button.Visible) {
821                                 e.Graphics.TranslateTransform (this.overflow_button.Bounds.Left, this.overflow_button.Bounds.Top);
822                                 this.overflow_button.FireEvent (e, ToolStripItemEventType.Paint);
823                                 e.Graphics.ResetTransform ();
824                         }
825
826                         Rectangle affected_bounds = new Rectangle (new Point (0, 0), this.Size);
827                         Rectangle connected_area = Rectangle.Empty;
828
829                         if (this is ToolStripDropDown && (this as ToolStripDropDown).OwnerItem != null && !(this as ToolStripDropDown).OwnerItem.IsOnDropDown)
830                                 connected_area = new Rectangle (1, 0, (this as ToolStripDropDown).OwnerItem.Width - 2, 2);
831
832                         ToolStripRenderEventArgs pevent = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, Color.Empty);
833                         pevent.InternalConnectedArea = connected_area;
834
835                         this.Renderer.DrawToolStripBorder (pevent);
836                 }
837
838                 [EditorBrowsable (EditorBrowsableState.Advanced)]
839                 protected override void OnPaintBackground (PaintEventArgs pevent)
840                 {
841                         base.OnPaintBackground (pevent);
842
843                         Rectangle affected_bounds = new Rectangle (new Point (0, 0), this.Size);
844                         Rectangle connected_area = Rectangle.Empty;
845
846                         if (this is ToolStripDropDown && (this as ToolStripDropDown).OwnerItem != null && !(this as ToolStripDropDown).OwnerItem.IsOnDropDown)
847                                 connected_area = new Rectangle (1, 0, (this as ToolStripDropDown).OwnerItem.Width - 2, 2);
848                         
849                         ToolStripRenderEventArgs e = new ToolStripRenderEventArgs (pevent.Graphics, this, affected_bounds, Color.Empty);
850                         e.InternalConnectedArea = connected_area;
851                         
852                         this.Renderer.DrawToolStripBackground (e);
853                 }
854
855                 protected internal virtual void OnPaintGrip (PaintEventArgs e)
856                 {
857                         // Never draw a grip with these two layouts
858                         if (this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
859                                 return;
860                         
861                         PaintEventHandler eh = (PaintEventHandler)(Events [PaintGripEvent]);
862                         if (eh != null)
863                                 eh (this, e);
864
865                         if (!(this is MenuStrip)) {
866                                 if (this.orientation == Orientation.Horizontal)
867                                         e.Graphics.TranslateTransform (2, 0);
868                                 else
869                                         e.Graphics.TranslateTransform (0, 2);
870                         }
871
872                         this.Renderer.DrawGrip (new ToolStripGripRenderEventArgs (e.Graphics, this, this.GripRectangle, this.GripDisplayStyle, this.grip_style));
873                         e.Graphics.ResetTransform ();
874                 }
875
876                 protected virtual void OnRendererChanged (EventArgs e)
877                 {
878                         EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
879                         if (eh != null)
880                                 eh (this, e);
881                 }
882
883                 [EditorBrowsable (EditorBrowsableState.Advanced)]
884                 protected override void OnRightToLeftChanged (EventArgs e)
885                 {
886                         base.OnRightToLeftChanged (e);
887                 }
888
889                 protected override void OnScroll (ScrollEventArgs se)
890                 {
891                         base.OnScroll (se);
892                 }
893                 
894                 protected override void OnTabStopChanged (EventArgs e)
895                 {
896                         base.OnTabStopChanged (e);
897                 }
898
899                 protected override void OnVisibleChanged (EventArgs e)
900                 {
901                         base.OnVisibleChanged (e);
902                 }
903
904                 protected override bool ProcessCmdKey (ref Message msg, Keys keyData)
905                 {
906                         return base.ProcessCmdKey (ref msg, keyData);
907                 }
908                 
909                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
910                 {
911                         base.SetBoundsCore (x, y, width, height, specified);
912                 }
913
914                 protected virtual void SetDisplayedItems ()
915                 {
916                         this.displayed_items.Clear ();
917                         
918                         foreach (ToolStripItem tsi in this.items)
919                                 if (tsi.Placement == ToolStripItemPlacement.Main && tsi.Available) {
920                                         this.displayed_items.AddNoOwnerOrLayout (tsi);
921                                         tsi.Parent = this; 
922                                 }
923                                 else if (tsi.Placement == ToolStripItemPlacement.Overflow)
924                                         tsi.Parent = this.OverflowButton.DropDown; 
925                         
926                         if (this.OverflowButton != null)
927                                 this.OverflowButton.DropDown.SetDisplayedItems ();
928                 }
929
930                 protected internal void SetItemLocation (ToolStripItem item, Point location)
931                 {
932                         if (item == null)
933                                 throw new ArgumentNullException ("item");
934                                 
935                         if (item.Owner != this)
936                                 throw new NotSupportedException ("The item is not owned by this ToolStrip");
937                                 
938                         item.SetBounds (new Rectangle (location, item.Size));
939                 }
940                 
941                 protected internal static void SetItemParent (ToolStripItem item, ToolStrip parent)
942                 {
943                         if (item.Parent != null) {
944                                 item.Parent.Items.RemoveNoOwnerOrLayout (item);
945                                 
946                                 if (item.Parent is ToolStripOverflow)
947                                         (item.Parent as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
948                         }
949                         
950                         parent.Items.AddNoOwnerOrLayout (item);
951                         item.Parent = parent;
952                 }
953
954                 protected override void SetVisibleCore (bool value)
955                 {
956                         base.SetVisibleCore (value);
957                 }
958
959                 protected override void WndProc (ref Message m)
960                 {
961                         base.WndProc (ref m);
962                 }
963                 #endregion
964
965                 #region Public Events
966                 static object ItemAddedEvent = new object ();
967                 static object ItemClickedEvent = new object ();
968                 static object ItemRemovedEvent = new object ();
969                 static object LayoutCompletedEvent = new object ();
970                 static object LayoutStyleChangedEvent = new object ();
971                 static object PaintGripEvent = new object ();
972                 static object RendererChangedEvent = new object ();
973
974                 [Browsable (true)]
975                 [EditorBrowsable (EditorBrowsableState.Always)]
976                 public new event EventHandler AutoSizeChanged {
977                         add { base.AutoSizeChanged += value; }
978                         remove { base.AutoSizeChanged -= value; }
979                 }
980
981                 [Browsable (false)]
982                 public new event EventHandler CausesValidationChanged {
983                         add { base.CausesValidationChanged += value; }
984                         remove { base.CausesValidationChanged -= value; }
985                 }
986
987                 [Browsable (false)]
988                 public new event ControlEventHandler ControlAdded {
989                         add { base.ControlAdded += value; }
990                         remove { base.ControlAdded -= value; }
991                 }
992
993                 [Browsable (false)]
994                 public new event ControlEventHandler ControlRemoved {
995                         add { base.ControlRemoved += value; }
996                         remove { base.ControlRemoved -= value; }
997                 }
998                 
999                 [Browsable (false)]
1000                 public new event EventHandler CursorChanged {
1001                         add { base.CursorChanged += value; }
1002                         remove { base.CursorChanged -= value; }
1003                 }
1004
1005                 [Browsable (false)]
1006                 public new event EventHandler ForeColorChanged {
1007                         add { base.ForeColorChanged += value; }
1008                         remove { base.ForeColorChanged -= value; }
1009                 }
1010
1011                 public event ToolStripItemEventHandler ItemAdded {
1012                         add { Events.AddHandler (ItemAddedEvent, value); }
1013                         remove { Events.RemoveHandler (ItemAddedEvent, value); }
1014                 }
1015
1016                 public event ToolStripItemClickedEventHandler ItemClicked {
1017                         add { Events.AddHandler (ItemClickedEvent, value); }
1018                         remove { Events.RemoveHandler (ItemClickedEvent, value); }
1019                 }
1020
1021                 public event ToolStripItemEventHandler ItemRemoved {
1022                         add { Events.AddHandler (ItemRemovedEvent, value); }
1023                         remove { Events.RemoveHandler (ItemRemovedEvent, value); }
1024                 }
1025
1026                 public event EventHandler LayoutCompleted {
1027                         add { Events.AddHandler (LayoutCompletedEvent, value); }
1028                         remove { Events.RemoveHandler (LayoutCompletedEvent, value); }
1029                 }
1030
1031                 public event EventHandler LayoutStyleChanged {
1032                         add { Events.AddHandler (LayoutStyleChangedEvent, value); }
1033                         remove { Events.RemoveHandler (LayoutStyleChangedEvent, value); }
1034                 }
1035
1036                 public event PaintEventHandler PaintGrip {
1037                         add { Events.AddHandler (PaintGripEvent, value); }
1038                         remove { Events.RemoveHandler (PaintGripEvent, value); }
1039                 }
1040
1041                 public event EventHandler RendererChanged {
1042                         add { Events.AddHandler (RendererChangedEvent, value); }
1043                         remove { Events.RemoveHandler (RendererChangedEvent, value); }
1044                 }
1045                 #endregion
1046
1047                 #region Private Methods
1048                 private void DoAutoSize ()
1049                 {
1050                         if (this.AutoSize == true && this.Dock == DockStyle.None)
1051                                 this.Size = GetPreferredSize (Size.Empty);
1052                                 
1053                         if (this.AutoSize == true && this.Orientation == Orientation.Horizontal && (this.Dock == DockStyle.Top || this.Dock == DockStyle.Bottom))
1054                                 this.Height = GetPreferredSize (Size.Empty).Height;
1055                 }
1056
1057                 public override Size GetPreferredSize (Size proposedSize)
1058                 {
1059                         Size new_size = new Size (0, this.Height);
1060
1061                         if (this.orientation == Orientation.Vertical) {
1062                                 foreach (ToolStripItem tsi in this.items)
1063                                         if (tsi.GetPreferredSize (Size.Empty).Height + tsi.Margin.Top + tsi.Margin.Bottom > new_size.Height)
1064                                                 new_size.Height = tsi.GetPreferredSize (Size.Empty).Height + tsi.Margin.Top + tsi.Margin.Bottom;
1065
1066                                 new_size.Height += this.Padding.Top + this.Padding.Bottom;
1067                                 new_size.Width = this.Width;
1068                         } else {
1069                                 foreach (ToolStripItem tsi in this.items) 
1070                                         if (tsi.Available) {
1071                                                 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1072                                                 new_size.Width += tsi_preferred.Width + tsi.Margin.Left + tsi.Margin.Right;
1073                                                 
1074                                                 if (new_size.Height < (this.Padding.Vertical + tsi_preferred.Height))
1075                                                         new_size.Height = (this.Padding.Vertical + tsi_preferred.Height);
1076                                         }
1077                         }
1078
1079                         new_size.Width += (this.GripRectangle.Width + this.GripMargin.Horizontal + this.Padding.Horizontal + 4);
1080                         return new_size;
1081                 }
1082                 
1083                 internal void HideMenus (bool release, ToolStripDropDownCloseReason reason)
1084                 {
1085                         if (this is MenuStrip && release && menu_selected)
1086                                 (this as MenuStrip).FireMenuDeactivate ();
1087                                 
1088                         if (release)
1089                                 menu_selected = false;
1090                                 
1091                         NotifySelectedChanged (null);
1092                 }
1093
1094                 internal void NotifySelectedChanged (ToolStripItem tsi)
1095                 {
1096                         foreach (ToolStripItem tsi2 in this.DisplayedItems)
1097                                 if (tsi != tsi2)
1098                                         if (tsi2 is ToolStripDropDownItem)
1099                                                 (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1100
1101                         if (this.OverflowButton != null) {
1102                                 ToolStripItemCollection tsic = this.OverflowButton.DropDown.DisplayedItems;
1103                                 
1104                                 foreach (ToolStripItem tsi2 in tsic)
1105                                         if (tsi != tsi2)
1106                                                 if (tsi2 is ToolStripDropDownItem)
1107                                                         (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1108                         
1109                                 this.OverflowButton.HideDropDown ();
1110                         }
1111                 }
1112                 
1113                 private void MouseEnteredItem (ToolStripItem item)
1114                 {
1115                         if (this.show_item_tool_tips) {
1116                                 tooltip_currently_showing = item;
1117                                 ToolTipTimer.Start ();
1118                         }
1119                 }
1120                 
1121                 private void MouseLeftItem (ToolStripItem item)
1122                 {
1123                         ToolTipTimer.Stop ();
1124                         ToolTipWindow.Hide ();
1125                         tooltip_currently_showing = null;
1126                 }
1127                 
1128                 private Timer ToolTipTimer {
1129                         get {
1130                                 if (tooltip_timer == null) {
1131                                         tooltip_timer = new Timer ();
1132                                         tooltip_timer.Enabled = false;
1133                                         tooltip_timer.Interval = 500;
1134                                         tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
1135                                 }
1136                                 
1137                                 return tooltip_timer;
1138                         }
1139                 }
1140                 
1141                 private ToolTip.ToolTipWindow ToolTipWindow {
1142                         get {
1143                                 if (tooltip_window == null)
1144                                         tooltip_window = new ToolTip.ToolTipWindow ();
1145                                         
1146                                 return tooltip_window;
1147                         }
1148                 }
1149                 
1150                 private void ToolTipTimer_Tick (object o, EventArgs args)
1151                 {
1152                         string tooltip = tooltip_currently_showing.GetToolTip ();
1153                         
1154                         if (!string.IsNullOrEmpty (tooltip))
1155                                 ToolTipWindow.Present (this, tooltip);
1156
1157                         tooltip_currently_showing.FireEvent (EventArgs.Empty, ToolStripItemEventType.MouseHover);
1158
1159                         ToolTipTimer.Stop ();
1160                 }
1161                 
1162                 internal ToolStrip CurrentlyMergedWith {
1163                         get { return this.currently_merged_with; }
1164                         set { this.currently_merged_with = value; }
1165                 }
1166                 
1167                 internal List<ToolStripItem> HiddenMergedItems {
1168                         get {
1169                                 if (this.hidden_merged_items == null)
1170                                         this.hidden_merged_items = new List<ToolStripItem> ();
1171                                         
1172                                 return this.hidden_merged_items;
1173                         }
1174                 }
1175                 
1176                 internal bool IsCurrentlyMerged {
1177                         get { return this.is_currently_merged; }
1178                         set { 
1179                                 this.is_currently_merged = value; 
1180                                 
1181                                 if (!value && this is MenuStrip) 
1182                                         foreach (ToolStripMenuItem tsmi in this.Items)
1183                                                 tsmi.DropDown.IsCurrentlyMerged = value;
1184                          }
1185                 }
1186                 
1187                 internal void BeginMerge ()
1188                 {
1189                         if (!IsCurrentlyMerged) {
1190                                 IsCurrentlyMerged = true;
1191                                 
1192                                 if (this.pre_merge_items == null) {
1193                                         this.pre_merge_items = new List<ToolStripItem> ();
1194                         
1195                                 foreach (ToolStripItem tsi in this.Items)
1196                                         this.pre_merge_items.Add (tsi);
1197                                 }
1198                                 
1199                                 if (this is MenuStrip)
1200                                         foreach (ToolStripMenuItem tsmi in this.Items)
1201                                                 tsmi.DropDown.BeginMerge ();
1202                         }
1203                 }
1204                 
1205                 internal void RevertMergeItem (ToolStripItem item)
1206                 {
1207                         int index = 0;
1208
1209                         // Remove it from it's current Parent
1210                         if (item.Parent != null && item.Parent != this) {
1211                                 if (item.Parent is ToolStripOverflow)
1212                                         (item.Parent as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1213                                 else
1214                                         item.Parent.Items.RemoveNoOwnerOrLayout (item);
1215
1216                                 item.Parent = item.Owner;       
1217                         }
1218                         
1219                         // Find where the item was before the merge
1220                         index = item.Owner.pre_merge_items.IndexOf (item);
1221
1222                         // Find the first pre-merge item that was after this item, that
1223                         // is currently in the Items collection.  Insert our item before
1224                         // that one.
1225                         for (int i = index; i < this.pre_merge_items.Count; i++) {
1226                                 if (this.Items.Contains (this.pre_merge_items[i])) {
1227                                         item.Owner.Items.InsertNoOwnerOrLayout (this.Items.IndexOf (this.pre_merge_items[i]), item);
1228                                         return;
1229                                 }
1230                         }
1231                         
1232                         // There aren't any items that are supposed to be after this item,
1233                         // so just append it to the end.
1234                         item.Owner.Items.AddNoOwnerOrLayout (item);
1235                 }
1236                 #endregion
1237         }
1238 }
1239 #endif