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:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
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.
23 // Copyright (c) 2006 Jonathan Pobst
26 // Jonathan Pobst (monkey@jpobst.com)
30 using System.Runtime.InteropServices;
31 using System.ComponentModel;
33 using System.Windows.Forms.Layout;
34 using System.Collections.Generic;
35 using System.ComponentModel.Design.Serialization;
37 namespace System.Windows.Forms
40 [ClassInterface (ClassInterfaceType.AutoDispatch)]
41 [DefaultEvent ("ItemClicked")]
42 [DefaultProperty ("Items")]
43 [Designer ("System.Windows.Forms.Design.ToolStripDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
44 [DesignerSerializer ("System.Windows.Forms.Design.ToolStripCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
45 public class ToolStrip : ScrollableControl, IComponent, IDisposable, IToolStripData
47 #region Private Variables
48 private bool allow_item_reorder;
49 private bool allow_merge;
50 private Color back_color;
51 private bool can_overflow;
52 private ToolStrip currently_merged_with;
53 private ToolStripDropDownDirection default_drop_down_direction;
54 internal ToolStripItemCollection displayed_items;
55 private Color fore_color;
56 private Padding grip_margin;
57 private ToolStripGripStyle grip_style;
58 private List<ToolStripItem> hidden_merged_items;
59 private ImageList image_list;
60 private Size image_scaling_size;
61 private bool is_currently_merged;
62 private ToolStripItemCollection items;
63 private bool keyboard_active;
64 private LayoutEngine layout_engine;
65 private LayoutSettings layout_settings;
66 private ToolStripLayoutStyle layout_style;
67 private Orientation orientation;
68 private ToolStripOverflowButton overflow_button;
69 private List<ToolStripItem> pre_merge_items;
70 private ToolStripRenderer renderer;
71 private ToolStripRenderMode render_mode;
72 private ToolStripTextDirection text_direction;
73 private Timer tooltip_timer;
74 private ToolTip tooltip_window;
75 private bool show_item_tool_tips;
78 private ToolStripItem mouse_currently_over;
79 internal bool menu_selected;
80 private ToolStripItem tooltip_currently_showing;
81 private ToolTip.TipState tooltip_state;
83 const int InitialToolTipDelay = 500;
84 const int ToolTipDelay = 5000;
87 #region Public Constructors
88 public ToolStrip () : this (null)
92 public ToolStrip (params ToolStripItem[] items) : base ()
94 SetStyle (ControlStyles.AllPaintingInWmPaint, true);
95 SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
96 SetStyle (ControlStyles.Selectable, false);
97 SetStyle (ControlStyles.SupportsTransparentBackColor, true);
99 this.SuspendLayout ();
101 this.items = new ToolStripItemCollection (this, items, true);
102 this.allow_merge = true;
103 base.AutoSize = true;
104 this.SetAutoSizeMode (AutoSizeMode.GrowAndShrink);
105 this.back_color = Control.DefaultBackColor;
106 this.can_overflow = true;
107 base.CausesValidation = false;
108 this.default_drop_down_direction = ToolStripDropDownDirection.BelowRight;
109 this.displayed_items = new ToolStripItemCollection (this, null, true);
110 this.Dock = this.DefaultDock;
111 base.Font = new Font ("Tahoma", 8.25f);
112 this.fore_color = Control.DefaultForeColor;
113 this.grip_margin = this.DefaultGripMargin;
114 this.grip_style = ToolStripGripStyle.Visible;
115 this.image_scaling_size = new Size (16, 16);
116 this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow;
117 this.orientation = Orientation.Horizontal;
118 if (!(this is ToolStripDropDown))
119 this.overflow_button = new ToolStripOverflowButton (this);
120 this.renderer = null;
121 this.render_mode = ToolStripRenderMode.ManagerRenderMode;
122 this.show_item_tool_tips = this.DefaultShowItemToolTips;
123 base.TabStop = false;
124 this.text_direction = ToolStripTextDirection.Horizontal;
125 this.ResumeLayout ();
127 // Register with the ToolStripManager
128 ToolStripManager.AddToolStrip (this);
132 #region Public Properties
133 [MonoTODO ("Stub, does nothing")]
134 public override bool AllowDrop {
135 get { return base.AllowDrop; }
136 set { base.AllowDrop = value; }
139 [MonoTODO ("Stub, does nothing")]
140 [DefaultValue (false)]
141 public bool AllowItemReorder {
142 get { return this.allow_item_reorder; }
143 set { this.allow_item_reorder = value; }
146 [DefaultValue (true)]
147 public bool AllowMerge {
148 get { return this.allow_merge; }
149 set { this.allow_merge = value; }
152 public override AnchorStyles Anchor {
153 get { return base.Anchor; }
154 set { base.Anchor = value; }
158 [EditorBrowsable (EditorBrowsableState.Never)]
159 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
160 public override bool AutoScroll {
161 get { return base.AutoScroll; }
162 set { base.AutoScroll = value; }
166 [EditorBrowsable (EditorBrowsableState.Never)]
167 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
168 public new Size AutoScrollMargin {
169 get { return base.AutoScrollMargin; }
170 set { base.AutoScrollMargin = value; }
174 [EditorBrowsable (EditorBrowsableState.Never)]
175 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
176 public new Size AutoScrollMinSize {
177 get { return base.AutoScrollMinSize; }
178 set { base.AutoScrollMinSize = value; }
182 [EditorBrowsable (EditorBrowsableState.Never)]
183 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
184 public new Point AutoScrollPosition {
185 get { return base.AutoScrollPosition; }
186 set { base.AutoScrollPosition = value; }
189 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
191 [EditorBrowsable (EditorBrowsableState.Always)]
192 [DefaultValue (true)]
193 public override bool AutoSize {
194 get { return base.AutoSize; }
195 set { base.AutoSize = value; }
198 new public Color BackColor {
199 get { return this.back_color; }
200 set { this.back_color = value; }
203 public override BindingContext BindingContext {
204 get { return base.BindingContext; }
205 set { base.BindingContext = value; }
208 [DefaultValue (true)]
209 public bool CanOverflow {
210 get { return this.can_overflow; }
211 set { this.can_overflow = value; }
215 [DefaultValue (false)]
216 public new bool CausesValidation {
217 get { return base.CausesValidation; }
218 set { base.CausesValidation = value; }
221 [EditorBrowsable (EditorBrowsableState.Never)]
222 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
223 public new ControlCollection Controls {
224 get { return base.Controls; }
228 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
229 public override Cursor Cursor {
230 get { return base.Cursor; }
231 set { base.Cursor = value; }
235 public virtual ToolStripDropDownDirection DefaultDropDownDirection {
236 get { return this.default_drop_down_direction; }
238 if (!Enum.IsDefined (typeof (ToolStripDropDownDirection), value))
239 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripDropDownDirection", value));
241 this.default_drop_down_direction = value;
245 public override Rectangle DisplayRectangle {
247 if (this.orientation == Orientation.Horizontal)
248 if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
249 return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical);
251 return new Rectangle (this.GripRectangle.Right + this.GripMargin.Right, this.Padding.Top, this.Width - this.Padding.Horizontal - this.GripRectangle.Right - this.GripMargin.Right, this.Height - this.Padding.Vertical);
253 if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
254 return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical);
256 return new Rectangle (this.Padding.Left, this.GripRectangle.Bottom + this.GripMargin.Bottom + this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical - this.GripRectangle.Bottom - this.GripMargin.Bottom);
260 [DefaultValue (DockStyle.Top)]
261 public override DockStyle Dock {
262 get { return base.Dock; }
264 if (base.Dock != value) {
269 case DockStyle.Bottom:
271 this.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
274 case DockStyle.Right:
275 this.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
282 public override Font Font {
283 get { return base.Font; }
285 if (base.Font != value) {
288 foreach (ToolStripItem tsi in this.Items)
289 tsi.OnOwnerFontChanged (EventArgs.Empty);
295 public new Color ForeColor {
296 get { return this.fore_color; }
298 if (this.fore_color != value) {
299 this.fore_color = value;
300 this.OnForeColorChanged (EventArgs.Empty);
306 public ToolStripGripDisplayStyle GripDisplayStyle {
307 get { return this.orientation == Orientation.Vertical ? ToolStripGripDisplayStyle.Horizontal : ToolStripGripDisplayStyle.Vertical; }
310 public Padding GripMargin {
311 get { return this.grip_margin; }
313 if (this.grip_margin != value) {
314 this.grip_margin = value;
315 this.PerformLayout ();
321 public Rectangle GripRectangle {
323 if (this.grip_style == ToolStripGripStyle.Hidden)
324 return Rectangle.Empty;
326 if (this.orientation == Orientation.Horizontal)
327 return new Rectangle (this.grip_margin.Left + this.Padding.Left, this.Padding.Top, 3, this.Height);
329 return new Rectangle (this.Padding.Left, this.grip_margin.Top + this.Padding.Top, this.Width, 3);
333 [DefaultValue (ToolStripGripStyle.Visible)]
334 public ToolStripGripStyle GripStyle {
335 get { return this.grip_style; }
337 if (this.grip_style != value) {
338 if (!Enum.IsDefined (typeof (ToolStripGripStyle), value))
339 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripGripStyle", value));
340 this.grip_style = value;
341 this.PerformLayout (this, "GripStyle");
347 [EditorBrowsable (EditorBrowsableState.Never)]
348 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
349 public new bool HasChildren {
350 get { return base.HasChildren; }
354 [EditorBrowsable (EditorBrowsableState.Never)]
355 public new HScrollProperties HorizontalScroll {
356 get { return base.HorizontalScroll; }
360 [DefaultValue (null)]
361 public ImageList ImageList {
362 get { return this.image_list; }
363 set { this.image_list = value; }
366 [DefaultValue ("{Width=16, Height=16}")]
367 public Size ImageScalingSize {
368 get { return this.image_scaling_size; }
369 set { this.image_scaling_size = value; }
372 [MonoTODO ("Always returns false, dragging not implemented yet.")]
374 [EditorBrowsable (EditorBrowsableState.Advanced)]
375 public bool IsCurrentlyDragging {
376 get { return false; }
380 public bool IsDropDown {
382 if (this is ToolStripDropDown)
389 [MergableProperty (false)]
390 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
391 public virtual ToolStripItemCollection Items {
392 get { return this.items; }
395 public override LayoutEngine LayoutEngine {
397 if (layout_engine == null)
398 this.layout_engine = new ToolStripSplitStackLayout ();
400 return this.layout_engine;
405 [DefaultValue (null)]
406 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
407 public LayoutSettings LayoutSettings {
408 get { return this.layout_settings; }
410 if (this.layout_settings != value) {
411 this.layout_settings = value;
412 PerformLayout (this, "LayoutSettings");
417 [AmbientValue (ToolStripLayoutStyle.StackWithOverflow)]
418 public ToolStripLayoutStyle LayoutStyle {
419 get { return layout_style; }
421 if (this.layout_style != value) {
422 if (!Enum.IsDefined (typeof (ToolStripLayoutStyle), value))
423 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripLayoutStyle", value));
425 this.layout_style = value;
427 if (this.layout_style == ToolStripLayoutStyle.Flow)
428 this.layout_engine = new FlowLayout ();
430 this.layout_engine = new ToolStripSplitStackLayout ();
432 if (this.layout_style == ToolStripLayoutStyle.StackWithOverflow) {
433 if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
434 this.layout_style = ToolStripLayoutStyle.VerticalStackWithOverflow;
436 this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow;
439 if (this.layout_style == ToolStripLayoutStyle.HorizontalStackWithOverflow)
440 this.orientation = Orientation.Horizontal;
441 else if (this.layout_style == ToolStripLayoutStyle.VerticalStackWithOverflow)
442 this.orientation = Orientation.Vertical;
444 this.layout_settings = this.CreateLayoutSettings (value);
446 this.PerformLayout (this, "LayoutStyle");
447 this.OnLayoutStyleChanged (EventArgs.Empty);
453 public Orientation Orientation {
454 get { return this.orientation; }
458 [EditorBrowsable (EditorBrowsableState.Advanced)]
459 public ToolStripOverflowButton OverflowButton {
460 get { return this.overflow_button; }
464 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
465 public ToolStripRenderer Renderer {
467 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
468 return ToolStripManager.Renderer;
470 return this.renderer;
473 if (this.renderer != value) {
474 this.renderer = value;
475 this.render_mode = ToolStripRenderMode.Custom;
476 this.PerformLayout (this, "Renderer");
477 this.OnRendererChanged (EventArgs.Empty);
482 public ToolStripRenderMode RenderMode {
483 get { return this.render_mode; }
485 if (!Enum.IsDefined (typeof (ToolStripRenderMode), value))
486 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value));
488 if (value == ToolStripRenderMode.Custom && this.renderer == null)
489 throw new NotSupportedException ("Must set Renderer property before setting RenderMode to Custom");
490 else if (value == ToolStripRenderMode.Professional)
491 this.Renderer = new ToolStripProfessionalRenderer ();
492 else if (value == ToolStripRenderMode.System)
493 this.Renderer = new ToolStripSystemRenderer ();
495 this.render_mode = value;
499 [DefaultValue (true)]
500 public bool ShowItemToolTips {
501 get { return this.show_item_tool_tips; }
502 set { this.show_item_tool_tips = value; }
505 [DefaultValue (false)]
506 public bool Stretch {
507 get { return this.stretch; }
508 set { this.stretch = value; }
511 [DefaultValue (false)]
513 public new bool TabStop {
514 get { return base.TabStop; }
516 base.TabStop = value;
517 SetStyle (ControlStyles.Selectable, value);
521 [DefaultValue (ToolStripTextDirection.Horizontal)]
522 public virtual ToolStripTextDirection TextDirection {
523 get { return this.text_direction; }
525 if (!Enum.IsDefined (typeof (ToolStripTextDirection), value))
526 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripTextDirection", value));
528 if (this.text_direction != value) {
529 this.text_direction = value;
531 this.PerformLayout (this, "TextDirection");
539 [EditorBrowsable (EditorBrowsableState.Never)]
540 public new VScrollProperties VerticalScroll {
541 get { return base.VerticalScroll; }
545 #region Protected Properties
546 protected virtual DockStyle DefaultDock { get { return DockStyle.Top; } }
547 protected virtual Padding DefaultGripMargin { get { return new Padding (2); } }
548 protected override Padding DefaultMargin { get { return Padding.Empty; } }
549 protected override Padding DefaultPadding { get { return new Padding (0, 0, 1, 0); } }
550 protected virtual bool DefaultShowItemToolTips { get { return true; } }
551 protected override Size DefaultSize { get { return new Size (100, 25); } }
552 protected internal virtual ToolStripItemCollection DisplayedItems { get { return this.displayed_items; } }
553 protected internal virtual Size MaxItemSize {
554 get { return new Size (Width - (GripStyle == ToolStripGripStyle.Hidden ? 1 : 8), Height); }
558 #region Public Methods
559 [EditorBrowsable (EditorBrowsableState.Never)]
560 public new Control GetChildAtPoint (Point point)
562 return base.GetChildAtPoint (point);
565 [EditorBrowsable (EditorBrowsableState.Never)]
566 public new Control GetChildAtPoint (Point pt, GetChildAtPointSkip skipValue)
568 return base.GetChildAtPoint (pt, skipValue);
571 public ToolStripItem GetItemAt (Point point)
573 foreach (ToolStripItem tsi in this.displayed_items)
574 if (tsi.Visible && tsi.Bounds.Contains (point))
580 public ToolStripItem GetItemAt (int x, int y)
582 return GetItemAt (new Point (x, y));
585 public virtual ToolStripItem GetNextItem (ToolStripItem start, ArrowDirection direction)
587 if (!Enum.IsDefined (typeof (ArrowDirection), direction))
588 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ArrowDirection", direction));
590 ToolStripItem current_best = null;
591 int current_best_point;
594 case ArrowDirection.Right:
595 current_best_point = int.MaxValue;
598 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
599 if (loop_tsi.Left >= start.Right && loop_tsi.Left < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
600 current_best = loop_tsi;
601 current_best_point = loop_tsi.Left;
604 if (current_best == null)
605 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
606 if (loop_tsi.Left < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
607 current_best = loop_tsi;
608 current_best_point = loop_tsi.Left;
612 case ArrowDirection.Up:
613 current_best_point = int.MinValue;
616 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
617 if (loop_tsi.Bottom <= start.Top && loop_tsi.Top > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
618 current_best = loop_tsi;
619 current_best_point = loop_tsi.Top;
622 if (current_best == null)
623 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
624 if (loop_tsi.Top > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
625 current_best = loop_tsi;
626 current_best_point = loop_tsi.Top;
630 case ArrowDirection.Left:
631 current_best_point = int.MinValue;
634 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
635 if (loop_tsi.Right <= start.Left && loop_tsi.Left > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
636 current_best = loop_tsi;
637 current_best_point = loop_tsi.Left;
640 if (current_best == null)
641 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
642 if (loop_tsi.Left > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
643 current_best = loop_tsi;
644 current_best_point = loop_tsi.Left;
648 case ArrowDirection.Down:
649 current_best_point = int.MaxValue;
652 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
653 if (loop_tsi.Top >= start.Bottom && loop_tsi.Bottom < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
654 current_best = loop_tsi;
655 current_best_point = loop_tsi.Top;
658 if (current_best == null)
659 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
660 if (loop_tsi.Top < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
661 current_best = loop_tsi;
662 current_best_point = loop_tsi.Top;
671 [EditorBrowsable (EditorBrowsableState.Never)]
672 public void ResetMinimumSize ()
674 this.MinimumSize = new Size (-1, -1);
677 [EditorBrowsable (EditorBrowsableState.Never)]
678 public new void SetAutoScrollMargin (int x, int y)
680 base.SetAutoScrollMargin (x, y);
683 public override string ToString ()
685 return String.Format ("{0}, Name: {1}, Items: {2}", base.ToString(), this.Name, this.items.Count.ToString ());
689 #region Protected Methods
690 protected override AccessibleObject CreateAccessibilityInstance ()
692 return new ToolStripAccessibleObject (this);
695 protected override ControlCollection CreateControlsInstance ()
697 return base.CreateControlsInstance ();
700 protected internal virtual ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick)
703 return new ToolStripSeparator ();
705 if (this is ToolStripDropDown)
706 return new ToolStripMenuItem (text, image, onClick);
708 return new ToolStripButton (text, image, onClick);
711 protected virtual LayoutSettings CreateLayoutSettings (ToolStripLayoutStyle layoutStyle)
713 switch (layoutStyle) {
714 case ToolStripLayoutStyle.Flow:
715 return new FlowLayoutSettings (this);
716 case ToolStripLayoutStyle.Table:
717 //return new TableLayoutSettings ();
718 case ToolStripLayoutStyle.StackWithOverflow:
719 case ToolStripLayoutStyle.HorizontalStackWithOverflow:
720 case ToolStripLayoutStyle.VerticalStackWithOverflow:
726 protected override void Dispose (bool disposing)
730 // Event Handler must be stopped before disposing Items.
734 // ToolStripItem.Dispose modifes the collection,
735 // so we iterate it in reverse order
736 for (int i = Items.Count - 1; i >= 0; i--)
737 Items [i].Dispose ();
739 if (this.overflow_button != null && this.overflow_button.drop_down != null)
740 this.overflow_button.drop_down.Dispose ();
742 ToolStripManager.RemoveToolStrip (this);
743 base.Dispose (disposing);
747 [MonoTODO ("Stub, never called")]
748 protected virtual void OnBeginDrag (EventArgs e)
750 EventHandler eh = (EventHandler)(Events[BeginDragEvent]);
755 protected override void OnDockChanged (EventArgs e)
757 base.OnDockChanged (e);
760 [MonoTODO ("Stub, never called")]
761 protected virtual void OnEndDrag (EventArgs e)
763 EventHandler eh = (EventHandler)(Events[EndDragEvent]);
768 protected override bool IsInputChar (char charCode)
770 return base.IsInputChar (charCode);
773 protected override bool IsInputKey (Keys keyData)
775 return base.IsInputKey (keyData);
778 protected override void OnEnabledChanged (EventArgs e)
780 base.OnEnabledChanged (e);
782 foreach (ToolStripItem tsi in this.Items)
783 tsi.OnParentEnabledChanged (EventArgs.Empty);
786 protected override void OnFontChanged (EventArgs e)
788 base.OnFontChanged (e);
791 protected override void OnHandleCreated (EventArgs e)
793 base.OnHandleCreated (e);
796 protected override void OnHandleDestroyed (EventArgs e)
798 base.OnHandleDestroyed (e);
801 protected override void OnInvalidated (InvalidateEventArgs e)
803 base.OnInvalidated (e);
806 protected internal virtual void OnItemAdded (ToolStripItemEventArgs e)
808 if (e.Item.InternalVisible)
809 e.Item.Available = true;
811 e.Item.SetPlacement (ToolStripItemPlacement.Main);
814 this.PerformLayout ();
816 ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemAddedEvent]);
821 protected virtual void OnItemClicked (ToolStripItemClickedEventArgs e)
823 if (this.KeyboardActive)
824 ToolStripManager.SetActiveToolStrip (null, false);
826 ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [ItemClickedEvent]);
831 protected internal virtual void OnItemRemoved (ToolStripItemEventArgs e)
833 ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemRemovedEvent]);
838 protected override void OnLayout (LayoutEventArgs e)
842 this.SetDisplayedItems ();
843 this.OnLayoutCompleted (EventArgs.Empty);
847 protected virtual void OnLayoutCompleted (EventArgs e)
849 EventHandler eh = (EventHandler)(Events [LayoutCompletedEvent]);
854 protected virtual void OnLayoutStyleChanged (EventArgs e)
856 EventHandler eh = (EventHandler)(Events[LayoutStyleChangedEvent]);
861 protected override void OnLeave (EventArgs e)
866 protected override void OnLostFocus (EventArgs e)
868 base.OnLostFocus (e);
871 protected override void OnMouseCaptureChanged (EventArgs e)
873 base.OnMouseCaptureChanged (e);
876 protected override void OnMouseDown (MouseEventArgs mea)
878 if (mouse_currently_over != null)
880 ToolStripItem focused = GetCurrentlyFocusedItem ();
882 if (focused != null && focused != mouse_currently_over)
883 this.FocusInternal (true);
885 if (this is MenuStrip && !menu_selected) {
886 (this as MenuStrip).FireMenuActivate ();
887 menu_selected = true;
890 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseDown);
892 if (this is MenuStrip && mouse_currently_over is ToolStripMenuItem && !(mouse_currently_over as ToolStripMenuItem).HasDropDownItems)
895 this.HideMenus (true, ToolStripDropDownCloseReason.AppClicked);
898 if (this is MenuStrip)
899 this.Capture = false;
901 base.OnMouseDown (mea);
904 protected override void OnMouseLeave (EventArgs e)
906 if (mouse_currently_over != null) {
907 MouseLeftItem (mouse_currently_over);
908 mouse_currently_over.FireEvent (e, ToolStripItemEventType.MouseLeave);
909 mouse_currently_over = null;
912 base.OnMouseLeave (e);
915 protected override void OnMouseMove (MouseEventArgs mea)
918 // Find the item we are now
919 if (this.overflow_button != null && this.overflow_button.Visible && this.overflow_button.Bounds.Contains (mea.Location))
920 tsi = this.overflow_button;
922 tsi = this.GetItemAt (mea.X, mea.Y);
925 // If we were already hovering on this item, just send a mouse move
926 if (tsi == mouse_currently_over)
927 tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
929 // If we were over a different item, fire a mouse leave on it
930 if (mouse_currently_over != null) {
932 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
935 // Set the new item we are currently over
936 mouse_currently_over = tsi;
938 // Fire mouse enter and mouse move
939 tsi.FireEvent (mea, ToolStripItemEventType.MouseEnter);
940 MouseEnteredItem (tsi);
941 tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
943 // If we're over something with a drop down, show it
944 if (menu_selected && mouse_currently_over.Enabled && mouse_currently_over is ToolStripDropDownItem && (mouse_currently_over as ToolStripDropDownItem).HasDropDownItems)
945 (mouse_currently_over as ToolStripDropDownItem).ShowDropDown ();
948 // We're not over anything now, just fire the mouse leave on what we used to be over
949 if (mouse_currently_over != null) {
951 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
952 mouse_currently_over = null;
956 base.OnMouseMove (mea);
959 protected override void OnMouseUp (MouseEventArgs mea)
961 // If we're currently over an item (set in MouseMove)
962 if (mouse_currently_over != null && !(mouse_currently_over is ToolStripControlHost) && mouse_currently_over.Enabled) {
963 // Fire our ItemClicked event
964 OnItemClicked (new ToolStripItemClickedEventArgs (mouse_currently_over));
966 // Fire the item's MouseUp event
967 if (mouse_currently_over != null)
968 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseUp);
970 // The event handler may have blocked until the mouse moved off of the ToolStripItem
971 if (mouse_currently_over == null)
975 base.OnMouseUp (mea);
978 protected override void OnPaint (PaintEventArgs e)
983 this.OnPaintGrip (e);
985 // Make each item draw itself
986 for (int i = 0; i < displayed_items.Count; i++) {
987 ToolStripItem tsi = displayed_items[i];
990 e.Graphics.TranslateTransform (tsi.Bounds.Left, tsi.Bounds.Top);
991 tsi.FireEvent (e, ToolStripItemEventType.Paint);
992 e.Graphics.ResetTransform ();
996 // Paint the Overflow button if it's visible
997 if (this.overflow_button != null && this.overflow_button.Visible) {
998 e.Graphics.TranslateTransform (this.overflow_button.Bounds.Left, this.overflow_button.Bounds.Top);
999 this.overflow_button.FireEvent (e, ToolStripItemEventType.Paint);
1000 e.Graphics.ResetTransform ();
1003 Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size);
1005 ToolStripRenderEventArgs pevent = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, Color.Empty);
1006 pevent.InternalConnectedArea = CalculateConnectedArea ();
1008 this.Renderer.DrawToolStripBorder (pevent);
1011 [EditorBrowsable (EditorBrowsableState.Advanced)]
1012 protected override void OnPaintBackground (PaintEventArgs e)
1014 base.OnPaintBackground (e);
1016 Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size);
1017 ToolStripRenderEventArgs tsrea = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, SystemColors.Control);
1019 this.Renderer.DrawToolStripBackground (tsrea);
1022 protected internal virtual void OnPaintGrip (PaintEventArgs e)
1024 // Never draw a grip with these two layouts
1025 if (this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
1028 PaintEventHandler eh = (PaintEventHandler)(Events [PaintGripEvent]);
1032 if (!(this is MenuStrip)) {
1033 if (this.orientation == Orientation.Horizontal)
1034 e.Graphics.TranslateTransform (2, 0);
1036 e.Graphics.TranslateTransform (0, 2);
1039 this.Renderer.DrawGrip (new ToolStripGripRenderEventArgs (e.Graphics, this, this.GripRectangle, this.GripDisplayStyle, this.grip_style));
1040 e.Graphics.ResetTransform ();
1043 protected virtual void OnRendererChanged (EventArgs e)
1045 EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
1050 [EditorBrowsable (EditorBrowsableState.Advanced)]
1051 protected override void OnRightToLeftChanged (EventArgs e)
1053 base.OnRightToLeftChanged (e);
1055 foreach (ToolStripItem tsi in this.Items)
1056 tsi.OnParentRightToLeftChanged (e);
1059 protected override void OnScroll (ScrollEventArgs se)
1064 protected override void OnTabStopChanged (EventArgs e)
1066 base.OnTabStopChanged (e);
1069 protected override void OnVisibleChanged (EventArgs e)
1072 CloseToolTip (null);
1074 base.OnVisibleChanged (e);
1077 protected override bool ProcessCmdKey (ref Message m, Keys keyData)
1079 return base.ProcessCmdKey (ref m, keyData);
1082 protected override bool ProcessDialogKey (Keys keyData)
1084 if (!this.KeyboardActive)
1087 // Give each item a chance to handle the key
1088 foreach (ToolStripItem tsi in this.Items)
1089 if (tsi.ProcessDialogKey (keyData))
1092 // See if I want to handle it
1093 if (this.ProcessArrowKey (keyData))
1096 ToolStrip ts = null;
1100 this.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1103 case Keys.Control | Keys.Tab:
1104 ts = ToolStripManager.GetNextToolStrip (this, true);
1107 foreach (ToolStripItem tsi in this.Items)
1108 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1110 ToolStripManager.SetActiveToolStrip (ts, true);
1111 ts.SelectNextToolStripItem (null, true);
1115 case Keys.Control | Keys.Shift | Keys.Tab:
1116 ts = ToolStripManager.GetNextToolStrip (this, false);
1119 foreach (ToolStripItem tsi in this.Items)
1120 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1122 ToolStripManager.SetActiveToolStrip (ts, true);
1123 ts.SelectNextToolStripItem (null, true);
1131 if (GetCurrentlySelectedItem () is ToolStripControlHost)
1136 return base.ProcessDialogKey (keyData);
1139 protected override bool ProcessMnemonic (char charCode)
1141 // If any item has an explicit mnemonic, it gets the message
1142 foreach (ToolStripItem tsi in this.Items)
1143 if (tsi.Enabled && tsi.Visible && !string.IsNullOrEmpty (tsi.Text) && Control.IsMnemonic (charCode, tsi.Text))
1144 return tsi.ProcessMnemonic (charCode);
1146 string code = Char.ToUpper (charCode).ToString ();
1148 // If any item's text starts with our letter, it gets the message
1149 if ((Control.ModifierKeys & Keys.Alt) != 0 || this is ToolStripDropDownMenu)
1150 foreach (ToolStripItem tsi in this.Items)
1151 if (tsi.Enabled && tsi.Visible && !string.IsNullOrEmpty (tsi.Text) && tsi.Text.ToUpper ().StartsWith (code) && !(tsi is ToolStripControlHost))
1152 return tsi.ProcessMnemonic (charCode);
1154 return base.ProcessMnemonic (charCode);
1157 [MonoTODO ("Stub, does nothing")]
1158 [EditorBrowsable (EditorBrowsableState.Advanced)]
1159 protected virtual void RestoreFocus ()
1163 protected override void Select (bool directed, bool forward)
1165 foreach (ToolStripItem tsi in this.DisplayedItems)
1166 if (tsi.CanSelect) {
1172 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
1174 base.SetBoundsCore (x, y, width, height, specified);
1177 protected virtual void SetDisplayedItems ()
1179 this.displayed_items.ClearInternal ();
1181 foreach (ToolStripItem tsi in this.items)
1182 if (tsi.Placement == ToolStripItemPlacement.Main && tsi.Available) {
1183 this.displayed_items.AddNoOwnerOrLayout (tsi);
1186 else if (tsi.Placement == ToolStripItemPlacement.Overflow)
1187 tsi.Parent = this.OverflowButton.DropDown;
1189 if (this.OverflowButton != null)
1190 this.OverflowButton.DropDown.SetDisplayedItems ();
1193 protected internal void SetItemLocation (ToolStripItem item, Point location)
1196 throw new ArgumentNullException ("item");
1198 if (item.Owner != this)
1199 throw new NotSupportedException ("The item is not owned by this ToolStrip");
1201 item.SetBounds (new Rectangle (location, item.Size));
1204 protected internal static void SetItemParent (ToolStripItem item, ToolStrip parent)
1206 if (item.Owner != null) {
1207 item.Owner.Items.RemoveNoOwnerOrLayout (item);
1209 if (item.Owner is ToolStripOverflow)
1210 (item.Owner as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1213 parent.Items.AddNoOwnerOrLayout (item);
1214 item.Parent = parent;
1217 protected override void SetVisibleCore (bool visible)
1219 base.SetVisibleCore (visible);
1222 protected override void WndProc (ref Message m)
1224 base.WndProc (ref m);
1228 #region Public Events
1229 static object BeginDragEvent = new object ();
1230 static object EndDragEvent = new object ();
1231 static object ItemAddedEvent = new object ();
1232 static object ItemClickedEvent = new object ();
1233 static object ItemRemovedEvent = new object ();
1234 static object LayoutCompletedEvent = new object ();
1235 static object LayoutStyleChangedEvent = new object ();
1236 static object PaintGripEvent = new object ();
1237 static object RendererChangedEvent = new object ();
1240 [EditorBrowsable (EditorBrowsableState.Always)]
1241 public new event EventHandler AutoSizeChanged {
1242 add { base.AutoSizeChanged += value; }
1243 remove { base.AutoSizeChanged -= value; }
1246 [MonoTODO ("Event never raised")]
1247 public event EventHandler BeginDrag {
1248 add { Events.AddHandler (BeginDragEvent, value); }
1249 remove { Events.RemoveHandler (BeginDragEvent, value); }
1253 public new event EventHandler CausesValidationChanged {
1254 add { base.CausesValidationChanged += value; }
1255 remove { base.CausesValidationChanged -= value; }
1259 [EditorBrowsable (EditorBrowsableState.Never)]
1260 public new event ControlEventHandler ControlAdded {
1261 add { base.ControlAdded += value; }
1262 remove { base.ControlAdded -= value; }
1266 [EditorBrowsable (EditorBrowsableState.Never)]
1267 public new event ControlEventHandler ControlRemoved {
1268 add { base.ControlRemoved += value; }
1269 remove { base.ControlRemoved -= value; }
1273 public new event EventHandler CursorChanged {
1274 add { base.CursorChanged += value; }
1275 remove { base.CursorChanged -= value; }
1278 [MonoTODO ("Event never raised")]
1279 public event EventHandler EndDrag {
1280 add { Events.AddHandler (EndDragEvent, value); }
1281 remove { Events.RemoveHandler (EndDragEvent, value); }
1285 public new event EventHandler ForeColorChanged {
1286 add { base.ForeColorChanged += value; }
1287 remove { base.ForeColorChanged -= value; }
1290 public event ToolStripItemEventHandler ItemAdded {
1291 add { Events.AddHandler (ItemAddedEvent, value); }
1292 remove { Events.RemoveHandler (ItemAddedEvent, value); }
1295 public event ToolStripItemClickedEventHandler ItemClicked {
1296 add { Events.AddHandler (ItemClickedEvent, value); }
1297 remove { Events.RemoveHandler (ItemClickedEvent, value); }
1300 public event ToolStripItemEventHandler ItemRemoved {
1301 add { Events.AddHandler (ItemRemovedEvent, value); }
1302 remove { Events.RemoveHandler (ItemRemovedEvent, value); }
1305 public event EventHandler LayoutCompleted {
1306 add { Events.AddHandler (LayoutCompletedEvent, value); }
1307 remove { Events.RemoveHandler (LayoutCompletedEvent, value); }
1310 public event EventHandler LayoutStyleChanged {
1311 add { Events.AddHandler (LayoutStyleChangedEvent, value); }
1312 remove { Events.RemoveHandler (LayoutStyleChangedEvent, value); }
1315 public event PaintEventHandler PaintGrip {
1316 add { Events.AddHandler (PaintGripEvent, value); }
1317 remove { Events.RemoveHandler (PaintGripEvent, value); }
1320 public event EventHandler RendererChanged {
1321 add { Events.AddHandler (RendererChangedEvent, value); }
1322 remove { Events.RemoveHandler (RendererChangedEvent, value); }
1326 #region Internal Properties
1327 internal virtual bool KeyboardActive
1329 get { return this.keyboard_active; }
1331 if (this.keyboard_active != value) {
1332 this.keyboard_active = value;
1335 Application.KeyboardCapture = this;
1336 else if (Application.KeyboardCapture == this) {
1337 Application.KeyboardCapture = null;
1338 ToolStripManager.ActivatedByKeyboard = false;
1341 // Redraw for mnemonic underlines
1348 #region Private Methods
1349 internal virtual Rectangle CalculateConnectedArea ()
1351 return Rectangle.Empty;
1354 internal void ChangeSelection (ToolStripItem nextItem)
1356 if (Application.KeyboardCapture != this)
1357 ToolStripManager.SetActiveToolStrip (this, ToolStripManager.ActivatedByKeyboard);
1359 foreach (ToolStripItem tsi in this.Items)
1360 if (tsi != nextItem)
1361 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1363 ToolStripItem current = GetCurrentlySelectedItem ();
1365 if (current != null && !(current is ToolStripControlHost))
1366 this.FocusInternal (true);
1368 if (nextItem is ToolStripControlHost)
1369 (nextItem as ToolStripControlHost).Focus ();
1373 if (nextItem.Parent is MenuStrip && (nextItem.Parent as MenuStrip).MenuDroppedDown)
1374 (nextItem as ToolStripMenuItem).HandleAutoExpansion ();
1377 internal virtual void Dismiss ()
1379 this.Dismiss (ToolStripDropDownCloseReason.AppClicked);
1382 internal virtual void Dismiss (ToolStripDropDownCloseReason reason)
1384 // Release our stranglehold on the keyboard
1385 this.KeyboardActive = false;
1387 // Set our drop down flag to false;
1388 this.menu_selected = false;
1390 // Make sure all of our items are deselected and repainted
1391 foreach (ToolStripItem tsi in this.Items)
1392 tsi.Dismiss (reason);
1394 // We probably need to redraw for mnemonic underlines
1398 internal ToolStripItem GetCurrentlySelectedItem ()
1400 foreach (ToolStripItem tsi in this.DisplayedItems)
1407 internal ToolStripItem GetCurrentlyFocusedItem ()
1409 foreach (ToolStripItem tsi in this.DisplayedItems)
1410 if ((tsi is ToolStripControlHost) && (tsi as ToolStripControlHost).Control.Focused)
1416 internal override Size GetPreferredSizeCore (Size proposedSize)
1418 return GetToolStripPreferredSize (proposedSize);
1421 internal virtual Size GetToolStripPreferredSize (Size proposedSize)
1423 Size new_size = Size.Empty;
1425 // TODO: This is total duct tape. We really have to call into the correct
1426 // layout engine, do a dry run of the layout, and find out our true
1427 // preferred dimensions.
1428 if (this.LayoutStyle == ToolStripLayoutStyle.Flow) {
1429 Point currentLocation = Point.Empty;
1432 foreach (ToolStripItem tsi in items)
1433 if (tsi.Available) {
1434 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1436 if ((DisplayRectangle.Width - currentLocation.X) < (tsi_preferred.Width + tsi.Margin.Horizontal)) {
1438 currentLocation.Y += tallest;
1441 currentLocation.X = DisplayRectangle.Left;
1444 // Offset the left margin and set the control to our point
1445 currentLocation.Offset (tsi.Margin.Left, 0);
1446 tallest = Math.Max (tallest, tsi_preferred.Height + tsi.Margin.Vertical);
1448 // Update our location pointer
1449 currentLocation.X += tsi_preferred.Width + tsi.Margin.Right;
1452 currentLocation.Y += tallest;
1453 return new Size (currentLocation.X + this.Padding.Horizontal, currentLocation.Y + this.Padding.Vertical);
1456 if (this.orientation == Orientation.Vertical) {
1457 foreach (ToolStripItem tsi in this.items)
1458 if (tsi.Available) {
1459 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1460 new_size.Height += tsi_preferred.Height + tsi.Margin.Top + tsi.Margin.Bottom;
1462 if (new_size.Width < (this.Padding.Horizontal + tsi_preferred.Width + tsi.Margin.Horizontal))
1463 new_size.Width = (this.Padding.Horizontal + tsi_preferred.Width + tsi.Margin.Horizontal);
1466 new_size.Height += (this.GripRectangle.Height + this.GripMargin.Vertical + this.Padding.Vertical + 4);
1468 if (new_size.Width == 0)
1469 new_size.Width = ExplicitBounds.Width;
1473 foreach (ToolStripItem tsi in this.items)
1474 if (tsi.Available) {
1475 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1476 new_size.Width += tsi_preferred.Width + tsi.Margin.Left + tsi.Margin.Right;
1478 if (new_size.Height < (this.Padding.Vertical + tsi_preferred.Height + tsi.Margin.Vertical))
1479 new_size.Height = (this.Padding.Vertical + tsi_preferred.Height + tsi.Margin.Vertical);
1482 new_size.Width += (this.GripRectangle.Width + this.GripMargin.Horizontal + this.Padding.Horizontal + 4);
1484 if (new_size.Height == 0)
1485 new_size.Height = ExplicitBounds.Height;
1487 if (this is StatusStrip)
1488 new_size.Height = Math.Max (new_size.Height, 22);
1494 internal virtual ToolStrip GetTopLevelToolStrip ()
1499 internal virtual void HandleItemClick (ToolStripItem dismissingItem)
1501 this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.ItemClicked);
1504 internal void HideMenus (bool release, ToolStripDropDownCloseReason reason)
1506 if (this is MenuStrip && release && menu_selected)
1507 (this as MenuStrip).FireMenuDeactivate ();
1510 menu_selected = false;
1512 NotifySelectedChanged (null);
1515 internal void NotifySelectedChanged (ToolStripItem tsi)
1517 foreach (ToolStripItem tsi2 in this.DisplayedItems)
1519 if (tsi2 is ToolStripDropDownItem)
1520 (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1522 if (this.OverflowButton != null) {
1523 ToolStripItemCollection tsic = this.OverflowButton.DropDown.DisplayedItems;
1525 foreach (ToolStripItem tsi2 in tsic)
1527 if (tsi2 is ToolStripDropDownItem)
1528 (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1530 this.OverflowButton.HideDropDown ();
1533 foreach (ToolStripItem tsi2 in this.Items)
1535 tsi2.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1538 internal virtual bool OnMenuKey ()
1543 internal virtual bool ProcessArrowKey (Keys keyData)
1549 tsi = this.GetCurrentlySelectedItem ();
1551 if (tsi is ToolStripControlHost)
1554 tsi = this.SelectNextToolStripItem (tsi, true);
1556 if (tsi is ToolStripControlHost)
1557 (tsi as ToolStripControlHost).Focus ();
1561 tsi = this.GetCurrentlySelectedItem ();
1563 tsi = this.SelectNextToolStripItem (tsi, true);
1565 if (tsi is ToolStripControlHost)
1566 (tsi as ToolStripControlHost).Focus ();
1570 tsi = this.GetCurrentlySelectedItem ();
1572 if (tsi is ToolStripControlHost)
1575 tsi = this.SelectNextToolStripItem (tsi, false);
1577 if (tsi is ToolStripControlHost)
1578 (tsi as ToolStripControlHost).Focus ();
1581 case Keys.Shift | Keys.Tab:
1582 tsi = this.GetCurrentlySelectedItem ();
1584 tsi = this.SelectNextToolStripItem (tsi, false);
1586 if (tsi is ToolStripControlHost)
1587 (tsi as ToolStripControlHost).Focus ();
1595 internal virtual ToolStripItem SelectNextToolStripItem (ToolStripItem start, bool forward)
1597 ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Right : ArrowDirection.Left);
1599 if (next_item == null)
1602 this.ChangeSelection (next_item);
1604 if (next_item is ToolStripControlHost)
1605 (next_item as ToolStripControlHost).Focus ();
1610 #region Stuff for ToolTips
1611 private void MouseEnteredItem (ToolStripItem item)
1613 if (this.show_item_tool_tips && !(item is ToolStripTextBox)) {
1614 ToolTipTimer.Interval = InitialToolTipDelay;
1615 tooltip_state = ToolTip.TipState.Initial;
1616 tooltip_currently_showing = item;
1617 ToolTipTimer.Start ();
1621 private void CloseToolTip (ToolStripItem item)
1623 ToolTipTimer.Stop ();
1624 ToolTipWindow.Hide (this);
1625 tooltip_currently_showing = null;
1626 tooltip_state = ToolTip.TipState.Down;
1629 private void MouseLeftItem (ToolStripItem item)
1631 CloseToolTip (item);
1634 private Timer ToolTipTimer {
1636 if (tooltip_timer == null) {
1637 tooltip_timer = new Timer ();
1638 tooltip_timer.Enabled = false;
1639 tooltip_timer.Interval = InitialToolTipDelay;
1640 tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
1643 return tooltip_timer;
1647 private ToolTip ToolTipWindow {
1649 if (tooltip_window == null)
1650 tooltip_window = new ToolTip ();
1652 return tooltip_window;
1656 private void ShowToolTip ()
1658 string tooltip = tooltip_currently_showing.GetToolTip ();
1660 if (!string.IsNullOrEmpty (tooltip)) {
1661 ToolTipWindow.Present (this, tooltip);
1662 ToolTipTimer.Interval = ToolTipDelay;
1663 ToolTipTimer.Start ();
1664 tooltip_state = ToolTip.TipState.Show;
1667 tooltip_currently_showing.FireEvent (EventArgs.Empty, ToolStripItemEventType.MouseHover);
1670 private void ToolTipTimer_Tick (object o, EventArgs args)
1672 ToolTipTimer.Stop ();
1674 switch (tooltip_state) {
1675 case ToolTip.TipState.Initial:
1678 case ToolTip.TipState.Show:
1679 CloseToolTip (null);
1685 #region Stuff for Merging
1686 internal ToolStrip CurrentlyMergedWith {
1687 get { return this.currently_merged_with; }
1688 set { this.currently_merged_with = value; }
1691 internal List<ToolStripItem> HiddenMergedItems {
1693 if (this.hidden_merged_items == null)
1694 this.hidden_merged_items = new List<ToolStripItem> ();
1696 return this.hidden_merged_items;
1700 internal bool IsCurrentlyMerged {
1701 get { return this.is_currently_merged; }
1703 this.is_currently_merged = value;
1705 if (!value && this is MenuStrip)
1706 foreach (ToolStripMenuItem tsmi in this.Items)
1707 tsmi.DropDown.IsCurrentlyMerged = value;
1711 internal void BeginMerge ()
1713 if (!IsCurrentlyMerged) {
1714 IsCurrentlyMerged = true;
1716 if (this.pre_merge_items == null) {
1717 this.pre_merge_items = new List<ToolStripItem> ();
1719 foreach (ToolStripItem tsi in this.Items)
1720 this.pre_merge_items.Add (tsi);
1725 internal void RevertMergeItem (ToolStripItem item)
1729 // Remove it from it's current Parent
1730 if (item.Parent != null && item.Parent != this) {
1731 if (item.Parent is ToolStripOverflow)
1732 (item.Parent as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1734 item.Parent.Items.RemoveNoOwnerOrLayout (item);
1736 item.Parent = item.Owner;
1739 // Find where the item was before the merge
1740 index = item.Owner.pre_merge_items.IndexOf (item);
1742 // Find the first pre-merge item that was after this item, that
1743 // is currently in the Items collection. Insert our item before
1745 for (int i = index; i < this.pre_merge_items.Count; i++) {
1746 if (this.Items.Contains (this.pre_merge_items[i])) {
1747 item.Owner.Items.InsertNoOwnerOrLayout (this.Items.IndexOf (this.pre_merge_items[i]), item);
1752 // There aren't any items that are supposed to be after this item,
1753 // so just append it to the end.
1754 item.Owner.Items.AddNoOwnerOrLayout (item);
1759 #region ToolStripAccessibleObject
1761 public class ToolStripAccessibleObject : ControlAccessibleObject
1763 #region Public Constructor
1764 public ToolStripAccessibleObject (ToolStrip owner) : base (owner)
1769 #region Public Properties
1770 public override AccessibleRole Role {
1771 get { return AccessibleRole.ToolBar; }
1775 #region Public Methods
1776 public override AccessibleObject GetChild (int index)
1778 return base.GetChild (index);
1781 public override int GetChildCount ()
1783 return (owner as ToolStrip).Items.Count;
1786 public override AccessibleObject HitTest (int x, int y)
1788 return base.HitTest (x, y);