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)
31 using System.Runtime.InteropServices;
32 using System.ComponentModel;
34 using System.Windows.Forms.Layout;
35 using System.Collections.Generic;
36 using System.ComponentModel.Design.Serialization;
38 namespace System.Windows.Forms
41 [ClassInterface (ClassInterfaceType.AutoDispatch)]
42 [DefaultEvent ("ItemClicked")]
43 [DefaultProperty ("Items")]
44 [Designer ("System.Windows.Forms.Design.ToolStripDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45 [DesignerSerializer ("System.Windows.Forms.Design.ToolStripCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
46 public class ToolStrip : ScrollableControl, IComponent, IDisposable, IToolStripData
48 #region Private Variables
49 private bool allow_item_reorder;
50 private bool allow_merge;
51 private Color back_color;
52 private bool can_overflow;
53 private ToolStrip currently_merged_with;
54 private ToolStripDropDownDirection default_drop_down_direction;
55 internal ToolStripItemCollection displayed_items;
56 private Color fore_color;
57 private Padding grip_margin;
58 private ToolStripGripStyle grip_style;
59 private List<ToolStripItem> hidden_merged_items;
60 private ImageList image_list;
61 private Size image_scaling_size;
62 private bool is_currently_merged;
63 private ToolStripItemCollection items;
64 private bool keyboard_active;
65 private LayoutEngine layout_engine;
66 private LayoutSettings layout_settings;
67 private ToolStripLayoutStyle layout_style;
68 private Orientation orientation;
69 private ToolStripOverflowButton overflow_button;
70 private List<ToolStripItem> pre_merge_items;
71 private ToolStripRenderer renderer;
72 private ToolStripRenderMode render_mode;
73 private ToolStripTextDirection text_direction;
74 private Timer tooltip_timer;
75 private ToolTip tooltip_window;
76 private bool show_item_tool_tips;
79 private ToolStripItem mouse_currently_over;
80 internal bool menu_selected;
81 private ToolStripItem tooltip_currently_showing;
84 #region Public Constructors
85 public ToolStrip () : this (null)
89 public ToolStrip (params ToolStripItem[] items) : base ()
91 SetStyle (ControlStyles.AllPaintingInWmPaint, true);
92 SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
93 SetStyle (ControlStyles.Selectable, false);
94 SetStyle (ControlStyles.SupportsTransparentBackColor, true);
96 this.SuspendLayout ();
98 this.items = new ToolStripItemCollection (this, items, true);
99 this.allow_merge = true;
100 base.AutoSize = true;
101 this.SetAutoSizeMode (AutoSizeMode.GrowAndShrink);
102 this.back_color = Control.DefaultBackColor;
103 this.can_overflow = true;
104 base.CausesValidation = false;
105 this.default_drop_down_direction = ToolStripDropDownDirection.BelowRight;
106 this.displayed_items = new ToolStripItemCollection (this, null, true);
107 this.Dock = this.DefaultDock;
108 base.Font = new Font ("Tahoma", 8.25f);
109 this.fore_color = Control.DefaultForeColor;
110 this.grip_margin = this.DefaultGripMargin;
111 this.grip_style = ToolStripGripStyle.Visible;
112 this.image_scaling_size = new Size (16, 16);
113 this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow;
114 this.orientation = Orientation.Horizontal;
115 if (!(this is ToolStripDropDown))
116 this.overflow_button = new ToolStripOverflowButton (this);
117 this.renderer = null;
118 this.render_mode = ToolStripRenderMode.ManagerRenderMode;
119 this.show_item_tool_tips = this.DefaultShowItemToolTips;
120 base.TabStop = false;
121 this.text_direction = ToolStripTextDirection.Horizontal;
122 this.ResumeLayout ();
124 // Register with the ToolStripManager
125 ToolStripManager.AddToolStrip (this);
129 #region Public Properties
131 public override bool AllowDrop {
132 get { return base.AllowDrop; }
133 set { base.AllowDrop = value; }
137 [DefaultValue (false)]
138 public bool AllowItemReorder {
139 get { return this.allow_item_reorder; }
140 set { this.allow_item_reorder = value; }
143 [DefaultValue (true)]
144 public bool AllowMerge {
145 get { return this.allow_merge; }
146 set { this.allow_merge = value; }
149 public override AnchorStyles Anchor {
150 get { return base.Anchor; }
151 set { base.Anchor = value; }
155 [EditorBrowsable (EditorBrowsableState.Never)]
156 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
157 public override bool AutoScroll {
158 get { return base.AutoScroll; }
159 set { base.AutoScroll = value; }
163 [EditorBrowsable (EditorBrowsableState.Never)]
164 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
165 public new Size AutoScrollMargin {
166 get { return base.AutoScrollMargin; }
167 set { base.AutoScrollMargin = value; }
171 [EditorBrowsable (EditorBrowsableState.Never)]
172 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
173 public new Size AutoScrollMinSize {
174 get { return base.AutoScrollMinSize; }
175 set { base.AutoScrollMinSize = value; }
179 [EditorBrowsable (EditorBrowsableState.Never)]
180 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
181 public new Point AutoScrollPosition {
182 get { return base.AutoScrollPosition; }
183 set { base.AutoScrollPosition = value; }
186 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
188 [EditorBrowsable (EditorBrowsableState.Always)]
189 [DefaultValue (true)]
190 public override bool AutoSize {
191 get { return base.AutoSize; }
192 set { base.AutoSize = value; }
195 new public Color BackColor {
196 get { return this.back_color; }
197 set { this.back_color = value; }
200 public override BindingContext BindingContext {
201 get { return base.BindingContext; }
202 set { base.BindingContext = value; }
205 [DefaultValue (true)]
206 public bool CanOverflow {
207 get { return this.can_overflow; }
208 set { this.can_overflow = value; }
212 [DefaultValue (false)]
213 public new bool CausesValidation {
214 get { return base.CausesValidation; }
215 set { base.CausesValidation = value; }
218 [EditorBrowsable (EditorBrowsableState.Never)]
219 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
220 public new ControlCollection Controls {
221 get { return base.Controls; }
225 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
226 public override Cursor Cursor {
227 get { return base.Cursor; }
228 set { base.Cursor = value; }
232 public virtual ToolStripDropDownDirection DefaultDropDownDirection {
233 get { return this.default_drop_down_direction; }
235 if (!Enum.IsDefined (typeof (ToolStripDropDownDirection), value))
236 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripDropDownDirection", value));
238 this.default_drop_down_direction = value;
242 public override Rectangle DisplayRectangle {
244 if (this.orientation == Orientation.Horizontal)
245 if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
246 return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical);
248 return new Rectangle (this.GripRectangle.Right + this.GripMargin.Right, this.Padding.Top, this.Width - this.Padding.Horizontal - this.GripRectangle.Right - this.GripMargin.Right, this.Height - this.Padding.Vertical);
250 if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
251 return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical);
253 return new Rectangle (this.Padding.Left, this.GripRectangle.Bottom + this.GripMargin.Bottom + this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical - this.GripRectangle.Bottom - this.GripMargin.Bottom);
257 [DefaultValue (DockStyle.Top)]
258 public override DockStyle Dock {
259 get { return base.Dock; }
261 if (base.Dock != value) {
266 case DockStyle.Bottom:
268 this.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
271 case DockStyle.Right:
272 this.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
279 public override Font Font {
280 get { return base.Font; }
282 if (base.Font != value) {
285 foreach (ToolStripItem tsi in this.Items)
286 tsi.OnOwnerFontChanged (EventArgs.Empty);
292 public new Color ForeColor {
293 get { return this.fore_color; }
295 if (this.fore_color != value) {
296 this.fore_color = value;
297 this.OnForeColorChanged (EventArgs.Empty);
303 public ToolStripGripDisplayStyle GripDisplayStyle {
304 get { return this.orientation == Orientation.Vertical ? ToolStripGripDisplayStyle.Horizontal : ToolStripGripDisplayStyle.Vertical; }
307 public Padding GripMargin {
308 get { return this.grip_margin; }
310 if (this.grip_margin != value) {
311 this.grip_margin = value;
312 this.PerformLayout ();
318 public Rectangle GripRectangle {
320 if (this.grip_style == ToolStripGripStyle.Hidden)
321 return Rectangle.Empty;
323 if (this.orientation == Orientation.Horizontal)
324 return new Rectangle (this.grip_margin.Left + this.Padding.Left, this.Padding.Top, 3, this.Height);
326 return new Rectangle (this.Padding.Left, this.grip_margin.Top + this.Padding.Top, this.Width, 3);
330 [DefaultValue (ToolStripGripStyle.Visible)]
331 public ToolStripGripStyle GripStyle {
332 get { return this.grip_style; }
334 if (this.grip_style != value) {
335 if (!Enum.IsDefined (typeof (ToolStripGripStyle), value))
336 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripGripStyle", value));
337 this.grip_style = value;
338 this.PerformLayout (this, "GripStyle");
344 [EditorBrowsable (EditorBrowsableState.Never)]
345 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
346 public new bool HasChildren {
347 get { return base.HasChildren; }
351 [EditorBrowsable (EditorBrowsableState.Never)]
352 public new HScrollProperties HorizontalScroll {
353 get { return base.HorizontalScroll; }
357 [DefaultValue (null)]
358 public ImageList ImageList {
359 get { return this.image_list; }
360 set { this.image_list = value; }
363 [DefaultValue ("{Width=16, Height=16}")]
364 public Size ImageScalingSize {
365 get { return this.image_scaling_size; }
366 set { this.image_scaling_size = value; }
369 [MonoTODO ("Always returns false, dragging not implemented yet.")]
371 [EditorBrowsable (EditorBrowsableState.Advanced)]
372 public bool IsCurrentlyDragging {
373 get { return false; }
377 public bool IsDropDown {
379 if (this is ToolStripDropDown)
386 [MergableProperty (false)]
387 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
388 public virtual ToolStripItemCollection Items {
389 get { return this.items; }
392 public override LayoutEngine LayoutEngine {
394 if (layout_engine == null)
395 this.layout_engine = new ToolStripSplitStackLayout ();
397 return this.layout_engine;
402 [DefaultValue (null)]
403 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
404 public LayoutSettings LayoutSettings {
405 get { return this.layout_settings; }
407 if (this.layout_settings != value) {
408 this.layout_settings = value;
409 PerformLayout (this, "LayoutSettings");
414 [AmbientValue (ToolStripLayoutStyle.StackWithOverflow)]
415 public ToolStripLayoutStyle LayoutStyle {
416 get { return layout_style; }
418 if (this.layout_style != value) {
419 if (!Enum.IsDefined (typeof (ToolStripLayoutStyle), value))
420 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripLayoutStyle", value));
422 this.layout_style = value;
424 if (this.layout_style == ToolStripLayoutStyle.Flow)
425 this.layout_engine = new FlowLayout ();
427 this.layout_engine = new ToolStripSplitStackLayout ();
429 if (this.layout_style == ToolStripLayoutStyle.StackWithOverflow) {
430 if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
431 this.layout_style = ToolStripLayoutStyle.VerticalStackWithOverflow;
433 this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow;
436 if (this.layout_style == ToolStripLayoutStyle.HorizontalStackWithOverflow)
437 this.orientation = Orientation.Horizontal;
438 else if (this.layout_style == ToolStripLayoutStyle.VerticalStackWithOverflow)
439 this.orientation = Orientation.Vertical;
441 this.layout_settings = this.CreateLayoutSettings (value);
443 this.PerformLayout (this, "LayoutStyle");
444 this.OnLayoutStyleChanged (EventArgs.Empty);
450 public Orientation Orientation {
451 get { return this.orientation; }
455 [EditorBrowsable (EditorBrowsableState.Advanced)]
456 public ToolStripOverflowButton OverflowButton {
457 get { return this.overflow_button; }
461 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
462 public ToolStripRenderer Renderer {
464 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
465 return ToolStripManager.Renderer;
467 return this.renderer;
470 if (this.renderer != value) {
471 this.renderer = value;
472 this.render_mode = ToolStripRenderMode.Custom;
473 this.PerformLayout (this, "Renderer");
474 this.OnRendererChanged (EventArgs.Empty);
479 public ToolStripRenderMode RenderMode {
480 get { return this.render_mode; }
482 if (!Enum.IsDefined (typeof (ToolStripRenderMode), value))
483 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value));
485 if (value == ToolStripRenderMode.Custom && this.renderer == null)
486 throw new NotSupportedException ("Must set Renderer property before setting RenderMode to Custom");
487 else if (value == ToolStripRenderMode.Professional)
488 this.Renderer = new ToolStripProfessionalRenderer ();
489 else if (value == ToolStripRenderMode.System)
490 this.Renderer = new ToolStripSystemRenderer ();
492 this.render_mode = value;
496 [DefaultValue (true)]
497 public bool ShowItemToolTips {
498 get { return this.show_item_tool_tips; }
499 set { this.show_item_tool_tips = value; }
502 [DefaultValue (false)]
503 public bool Stretch {
504 get { return this.stretch; }
505 set { this.stretch = value; }
508 [DefaultValue (false)]
510 public new bool TabStop {
511 get { return base.TabStop; }
513 base.TabStop = value;
514 SetStyle (ControlStyles.Selectable, value);
518 [DefaultValue (ToolStripTextDirection.Horizontal)]
519 public virtual ToolStripTextDirection TextDirection {
520 get { return this.text_direction; }
522 if (!Enum.IsDefined (typeof (ToolStripTextDirection), value))
523 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripTextDirection", value));
525 if (this.text_direction != value) {
526 this.text_direction = value;
528 this.PerformLayout (this, "TextDirection");
536 [EditorBrowsable (EditorBrowsableState.Never)]
537 public new VScrollProperties VerticalScroll {
538 get { return base.VerticalScroll; }
542 #region Protected Properties
543 protected virtual DockStyle DefaultDock { get { return DockStyle.Top; } }
544 protected virtual Padding DefaultGripMargin { get { return new Padding (2); } }
545 protected override Padding DefaultMargin { get { return Padding.Empty; } }
546 protected override Padding DefaultPadding { get { return new Padding (0, 0, 1, 0); } }
547 protected virtual bool DefaultShowItemToolTips { get { return true; } }
548 protected override Size DefaultSize { get { return new Size (100, 25); } }
549 protected internal virtual ToolStripItemCollection DisplayedItems { get { return this.displayed_items; } }
550 protected internal virtual Size MaxItemSize {
551 get { return new Size (Width - (GripStyle == ToolStripGripStyle.Hidden ? 1 : 8), Height); }
555 #region Public Methods
556 [EditorBrowsable (EditorBrowsableState.Never)]
557 public new Control GetChildAtPoint (Point point)
559 return base.GetChildAtPoint (point);
562 [EditorBrowsable (EditorBrowsableState.Never)]
563 public new Control GetChildAtPoint (Point pt, GetChildAtPointSkip skipValue)
565 return base.GetChildAtPoint (pt, skipValue);
568 public ToolStripItem GetItemAt (Point point)
570 foreach (ToolStripItem tsi in this.displayed_items)
571 if (tsi.Visible && tsi.Bounds.Contains (point))
577 public ToolStripItem GetItemAt (int x, int y)
579 return GetItemAt (new Point (x, y));
582 public virtual ToolStripItem GetNextItem (ToolStripItem start, ArrowDirection direction)
584 if (!Enum.IsDefined (typeof (ArrowDirection), direction))
585 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ArrowDirection", direction));
587 ToolStripItem current_best = null;
588 int current_best_point;
591 case ArrowDirection.Right:
592 current_best_point = int.MaxValue;
595 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
596 if (loop_tsi.Left >= start.Right && loop_tsi.Left < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
597 current_best = loop_tsi;
598 current_best_point = loop_tsi.Left;
601 if (current_best == null)
602 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
603 if (loop_tsi.Left < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
604 current_best = loop_tsi;
605 current_best_point = loop_tsi.Left;
609 case ArrowDirection.Up:
610 current_best_point = int.MinValue;
613 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
614 if (loop_tsi.Bottom <= start.Top && loop_tsi.Top > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
615 current_best = loop_tsi;
616 current_best_point = loop_tsi.Top;
619 if (current_best == null)
620 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
621 if (loop_tsi.Top > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
622 current_best = loop_tsi;
623 current_best_point = loop_tsi.Top;
627 case ArrowDirection.Left:
628 current_best_point = int.MinValue;
631 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
632 if (loop_tsi.Right <= start.Left && loop_tsi.Left > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
633 current_best = loop_tsi;
634 current_best_point = loop_tsi.Left;
637 if (current_best == null)
638 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
639 if (loop_tsi.Left > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
640 current_best = loop_tsi;
641 current_best_point = loop_tsi.Left;
645 case ArrowDirection.Down:
646 current_best_point = int.MaxValue;
649 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
650 if (loop_tsi.Top >= start.Bottom && loop_tsi.Bottom < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
651 current_best = loop_tsi;
652 current_best_point = loop_tsi.Top;
655 if (current_best == null)
656 foreach (ToolStripItem loop_tsi in this.DisplayedItems)
657 if (loop_tsi.Top < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) {
658 current_best = loop_tsi;
659 current_best_point = loop_tsi.Top;
668 [EditorBrowsable (EditorBrowsableState.Never)]
669 public void ResetMinimumSize ()
671 this.MinimumSize = new Size (-1, -1);
674 [EditorBrowsable (EditorBrowsableState.Never)]
675 public new void SetAutoScrollMargin (int x, int y)
677 base.SetAutoScrollMargin (x, y);
680 public override string ToString ()
682 return String.Format ("{0}, Name: {1}, Items: {2}", base.ToString(), this.Name, this.items.Count.ToString ());
686 #region Protected Methods
687 protected override AccessibleObject CreateAccessibilityInstance ()
689 return new ToolStripAccessibleObject (this);
692 protected override ControlCollection CreateControlsInstance ()
694 return base.CreateControlsInstance ();
697 protected internal virtual ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick)
700 return new ToolStripSeparator ();
702 if (this is ToolStripDropDown)
703 return new ToolStripMenuItem (text, image, onClick);
705 return new ToolStripButton (text, image, onClick);
708 protected virtual LayoutSettings CreateLayoutSettings (ToolStripLayoutStyle layoutStyle)
710 switch (layoutStyle) {
711 case ToolStripLayoutStyle.Flow:
712 return new FlowLayoutSettings (this);
713 case ToolStripLayoutStyle.Table:
714 //return new TableLayoutSettings ();
715 case ToolStripLayoutStyle.StackWithOverflow:
716 case ToolStripLayoutStyle.HorizontalStackWithOverflow:
717 case ToolStripLayoutStyle.VerticalStackWithOverflow:
723 protected override void Dispose (bool disposing)
726 // ToolStripItem.Dispose modifes the collection,
727 // so we iterate it in reverse order
728 for (int i = Items.Count - 1; i >= 0; i--)
729 Items [i].Dispose ();
731 if (this.overflow_button != null && this.overflow_button.drop_down != null)
732 this.overflow_button.drop_down.Dispose ();
734 ToolStripManager.RemoveToolStrip (this);
735 base.Dispose (disposing);
739 [MonoTODO ("Not called")]
740 protected virtual void OnBeginDrag (EventArgs e)
742 EventHandler eh = (EventHandler)(Events[BeginDragEvent]);
747 protected override void OnDockChanged (EventArgs e)
749 base.OnDockChanged (e);
752 [MonoTODO ("Not called")]
753 protected virtual void OnEndDrag (EventArgs e)
755 EventHandler eh = (EventHandler)(Events[EndDragEvent]);
760 protected override bool IsInputChar (char charCode)
762 return base.IsInputChar (charCode);
765 protected override bool IsInputKey (Keys keyData)
767 return base.IsInputKey (keyData);
770 protected override void OnEnabledChanged (EventArgs e)
772 base.OnEnabledChanged (e);
774 foreach (ToolStripItem tsi in this.Items)
775 tsi.OnParentEnabledChanged (EventArgs.Empty);
778 protected override void OnFontChanged (EventArgs e)
780 base.OnFontChanged (e);
783 protected override void OnHandleCreated (EventArgs e)
785 base.OnHandleCreated (e);
788 protected override void OnHandleDestroyed (EventArgs e)
790 base.OnHandleDestroyed (e);
793 protected override void OnInvalidated (InvalidateEventArgs e)
795 base.OnInvalidated (e);
798 protected internal virtual void OnItemAdded (ToolStripItemEventArgs e)
800 if (e.Item.InternalVisible)
801 e.Item.Available = true;
803 e.Item.SetPlacement (ToolStripItemPlacement.Main);
806 this.PerformLayout ();
808 ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemAddedEvent]);
813 protected virtual void OnItemClicked (ToolStripItemClickedEventArgs e)
815 if (this.KeyboardActive)
816 ToolStripManager.SetActiveToolStrip (null, false);
818 ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [ItemClickedEvent]);
823 protected internal virtual void OnItemRemoved (ToolStripItemEventArgs e)
825 ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemRemovedEvent]);
830 protected override void OnLayout (LayoutEventArgs e)
834 this.SetDisplayedItems ();
835 this.OnLayoutCompleted (EventArgs.Empty);
839 protected virtual void OnLayoutCompleted (EventArgs e)
841 EventHandler eh = (EventHandler)(Events [LayoutCompletedEvent]);
846 protected virtual void OnLayoutStyleChanged (EventArgs e)
848 EventHandler eh = (EventHandler)(Events[LayoutStyleChangedEvent]);
853 protected override void OnLeave (EventArgs e)
858 protected override void OnLostFocus (EventArgs e)
860 base.OnLostFocus (e);
863 protected override void OnMouseCaptureChanged (EventArgs e)
865 base.OnMouseCaptureChanged (e);
868 protected override void OnMouseDown (MouseEventArgs mea)
870 if (mouse_currently_over != null)
872 ToolStripItem focused = GetCurrentlyFocusedItem ();
874 if (focused != null && focused != mouse_currently_over)
875 this.FocusInternal (true);
877 if (this is MenuStrip && !menu_selected) {
878 (this as MenuStrip).FireMenuActivate ();
879 menu_selected = true;
882 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseDown);
884 if (this is MenuStrip && mouse_currently_over is ToolStripMenuItem && !(mouse_currently_over as ToolStripMenuItem).HasDropDownItems)
887 if (this is MenuStrip)
888 this.HideMenus (true, ToolStripDropDownCloseReason.AppClicked);
891 if (this is MenuStrip)
892 this.Capture = false;
894 base.OnMouseDown (mea);
897 protected override void OnMouseLeave (EventArgs e)
899 if (mouse_currently_over != null) {
900 MouseLeftItem (mouse_currently_over);
901 mouse_currently_over.FireEvent (e, ToolStripItemEventType.MouseLeave);
902 mouse_currently_over = null;
905 base.OnMouseLeave (e);
908 protected override void OnMouseMove (MouseEventArgs mea)
911 // Find the item we are now
912 if (this.overflow_button != null && this.overflow_button.Visible && this.overflow_button.Bounds.Contains (mea.Location))
913 tsi = this.overflow_button;
915 tsi = this.GetItemAt (mea.X, mea.Y);
918 // If we were already hovering on this item, just send a mouse move
919 if (tsi == mouse_currently_over)
920 tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
922 // If we were over a different item, fire a mouse leave on it
923 if (mouse_currently_over != null) {
925 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
928 // Set the new item we are currently over
929 mouse_currently_over = tsi;
931 // Fire mouse enter and mouse move
932 tsi.FireEvent (mea, ToolStripItemEventType.MouseEnter);
933 MouseEnteredItem (tsi);
934 tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
936 // If we're over something with a drop down, show it
937 if (menu_selected && mouse_currently_over.Enabled && mouse_currently_over is ToolStripDropDownItem && (mouse_currently_over as ToolStripDropDownItem).HasDropDownItems)
938 (mouse_currently_over as ToolStripDropDownItem).ShowDropDown ();
941 // We're not over anything now, just fire the mouse leave on what we used to be over
942 if (mouse_currently_over != null) {
944 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
945 mouse_currently_over = null;
949 base.OnMouseMove (mea);
952 protected override void OnMouseUp (MouseEventArgs mea)
954 // If we're currently over an item (set in MouseMove)
955 if (mouse_currently_over != null && !(mouse_currently_over is ToolStripControlHost) && mouse_currently_over.Enabled) {
956 // Fire our ItemClicked event
957 OnItemClicked (new ToolStripItemClickedEventArgs (mouse_currently_over));
959 // Fire the item's MouseUp event
960 if (mouse_currently_over != null)
961 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseUp);
963 // The event handler may have blocked until the mouse moved off of the ToolStripItem
964 if (mouse_currently_over == null)
968 base.OnMouseUp (mea);
971 protected override void OnPaint (PaintEventArgs e)
976 this.OnPaintGrip (e);
978 // Make each item draw itself
979 for (int i = 0; i < displayed_items.Count; i++) {
980 ToolStripItem tsi = displayed_items[i];
983 e.Graphics.TranslateTransform (tsi.Bounds.Left, tsi.Bounds.Top);
984 tsi.FireEvent (e, ToolStripItemEventType.Paint);
985 e.Graphics.ResetTransform ();
989 // Paint the Overflow button if it's visible
990 if (this.overflow_button != null && this.overflow_button.Visible) {
991 e.Graphics.TranslateTransform (this.overflow_button.Bounds.Left, this.overflow_button.Bounds.Top);
992 this.overflow_button.FireEvent (e, ToolStripItemEventType.Paint);
993 e.Graphics.ResetTransform ();
996 Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size);
998 ToolStripRenderEventArgs pevent = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, Color.Empty);
999 pevent.InternalConnectedArea = CalculateConnectedArea ();
1001 this.Renderer.DrawToolStripBorder (pevent);
1004 [EditorBrowsable (EditorBrowsableState.Advanced)]
1005 protected override void OnPaintBackground (PaintEventArgs e)
1007 base.OnPaintBackground (e);
1009 Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size);
1010 ToolStripRenderEventArgs tsrea = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, SystemColors.Control);
1012 this.Renderer.DrawToolStripBackground (tsrea);
1015 protected internal virtual void OnPaintGrip (PaintEventArgs e)
1017 // Never draw a grip with these two layouts
1018 if (this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
1021 PaintEventHandler eh = (PaintEventHandler)(Events [PaintGripEvent]);
1025 if (!(this is MenuStrip)) {
1026 if (this.orientation == Orientation.Horizontal)
1027 e.Graphics.TranslateTransform (2, 0);
1029 e.Graphics.TranslateTransform (0, 2);
1032 this.Renderer.DrawGrip (new ToolStripGripRenderEventArgs (e.Graphics, this, this.GripRectangle, this.GripDisplayStyle, this.grip_style));
1033 e.Graphics.ResetTransform ();
1036 protected virtual void OnRendererChanged (EventArgs e)
1038 EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
1043 [EditorBrowsable (EditorBrowsableState.Advanced)]
1044 protected override void OnRightToLeftChanged (EventArgs e)
1046 base.OnRightToLeftChanged (e);
1048 foreach (ToolStripItem tsi in this.Items)
1049 tsi.OnParentRightToLeftChanged (e);
1052 protected override void OnScroll (ScrollEventArgs se)
1057 protected override void OnTabStopChanged (EventArgs e)
1059 base.OnTabStopChanged (e);
1062 protected override void OnVisibleChanged (EventArgs e)
1064 base.OnVisibleChanged (e);
1067 protected override bool ProcessCmdKey (ref Message m, Keys keyData)
1069 return base.ProcessCmdKey (ref m, keyData);
1072 protected override bool ProcessDialogKey (Keys keyData)
1074 if (!this.KeyboardActive)
1077 // Give each item a chance to handle the key
1078 foreach (ToolStripItem tsi in this.Items)
1079 if (tsi.ProcessDialogKey (keyData))
1082 // See if I want to handle it
1083 if (this.ProcessArrowKey (keyData))
1086 ToolStrip ts = null;
1090 this.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1093 case Keys.Control | Keys.Tab:
1094 ts = ToolStripManager.GetNextToolStrip (this, true);
1097 foreach (ToolStripItem tsi in this.Items)
1098 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1100 ToolStripManager.SetActiveToolStrip (ts, true);
1101 ts.SelectNextToolStripItem (null, true);
1105 case Keys.Control | Keys.Shift | Keys.Tab:
1106 ts = ToolStripManager.GetNextToolStrip (this, false);
1109 foreach (ToolStripItem tsi in this.Items)
1110 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1112 ToolStripManager.SetActiveToolStrip (ts, true);
1113 ts.SelectNextToolStripItem (null, true);
1121 if (GetCurrentlySelectedItem () is ToolStripControlHost)
1126 return base.ProcessDialogKey (keyData);
1129 protected override bool ProcessMnemonic (char charCode)
1131 // If any item has an explicit mnemonic, it gets the message
1132 foreach (ToolStripItem tsi in this.Items)
1133 if (tsi.Enabled && tsi.Visible && !string.IsNullOrEmpty (tsi.Text) && Control.IsMnemonic (charCode, tsi.Text))
1134 return tsi.ProcessMnemonic (charCode);
1136 string code = Char.ToUpper (charCode).ToString ();
1138 // If any item's text starts with our letter, it gets the message
1139 if (this is ToolStripDropDownMenu)
1140 foreach (ToolStripItem tsi in this.Items)
1141 if (tsi.Enabled && tsi.Visible && !string.IsNullOrEmpty (tsi.Text) && tsi.Text.ToUpper ().StartsWith (code) && !(tsi is ToolStripControlHost))
1142 return tsi.ProcessMnemonic (charCode);
1144 return base.ProcessMnemonic (charCode);
1148 [EditorBrowsable (EditorBrowsableState.Advanced)]
1149 protected virtual void RestoreFocus ()
1154 protected override void Select (bool directed, bool forward)
1156 foreach (ToolStripItem tsi in this.DisplayedItems)
1157 if (tsi.CanSelect) {
1163 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
1165 base.SetBoundsCore (x, y, width, height, specified);
1168 protected virtual void SetDisplayedItems ()
1170 this.displayed_items.Clear ();
1172 foreach (ToolStripItem tsi in this.items)
1173 if (tsi.Placement == ToolStripItemPlacement.Main && tsi.Available) {
1174 this.displayed_items.AddNoOwnerOrLayout (tsi);
1177 else if (tsi.Placement == ToolStripItemPlacement.Overflow)
1178 tsi.Parent = this.OverflowButton.DropDown;
1180 if (this.OverflowButton != null)
1181 this.OverflowButton.DropDown.SetDisplayedItems ();
1184 protected internal void SetItemLocation (ToolStripItem item, Point location)
1187 throw new ArgumentNullException ("item");
1189 if (item.Owner != this)
1190 throw new NotSupportedException ("The item is not owned by this ToolStrip");
1192 item.SetBounds (new Rectangle (location, item.Size));
1195 protected internal static void SetItemParent (ToolStripItem item, ToolStrip parent)
1197 if (item.Owner != null) {
1198 item.Owner.Items.RemoveNoOwnerOrLayout (item);
1200 if (item.Owner is ToolStripOverflow)
1201 (item.Owner as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1204 parent.Items.AddNoOwnerOrLayout (item);
1205 item.Parent = parent;
1208 protected override void SetVisibleCore (bool visible)
1210 base.SetVisibleCore (visible);
1213 protected override void WndProc (ref Message m)
1215 base.WndProc (ref m);
1219 #region Public Events
1220 static object BeginDragEvent = new object ();
1221 static object EndDragEvent = new object ();
1222 static object ItemAddedEvent = new object ();
1223 static object ItemClickedEvent = new object ();
1224 static object ItemRemovedEvent = new object ();
1225 static object LayoutCompletedEvent = new object ();
1226 static object LayoutStyleChangedEvent = new object ();
1227 static object PaintGripEvent = new object ();
1228 static object RendererChangedEvent = new object ();
1231 [EditorBrowsable (EditorBrowsableState.Always)]
1232 public new event EventHandler AutoSizeChanged {
1233 add { base.AutoSizeChanged += value; }
1234 remove { base.AutoSizeChanged -= value; }
1238 public event EventHandler BeginDrag {
1239 add { Events.AddHandler (BeginDragEvent, value); }
1240 remove { Events.RemoveHandler (BeginDragEvent, value); }
1244 public new event EventHandler CausesValidationChanged {
1245 add { base.CausesValidationChanged += value; }
1246 remove { base.CausesValidationChanged -= value; }
1250 [EditorBrowsable (EditorBrowsableState.Never)]
1251 public new event ControlEventHandler ControlAdded {
1252 add { base.ControlAdded += value; }
1253 remove { base.ControlAdded -= value; }
1257 [EditorBrowsable (EditorBrowsableState.Never)]
1258 public new event ControlEventHandler ControlRemoved {
1259 add { base.ControlRemoved += value; }
1260 remove { base.ControlRemoved -= value; }
1264 public new event EventHandler CursorChanged {
1265 add { base.CursorChanged += value; }
1266 remove { base.CursorChanged -= value; }
1270 public event EventHandler EndDrag {
1271 add { Events.AddHandler (EndDragEvent, value); }
1272 remove { Events.RemoveHandler (EndDragEvent, value); }
1276 public new event EventHandler ForeColorChanged {
1277 add { base.ForeColorChanged += value; }
1278 remove { base.ForeColorChanged -= value; }
1281 public event ToolStripItemEventHandler ItemAdded {
1282 add { Events.AddHandler (ItemAddedEvent, value); }
1283 remove { Events.RemoveHandler (ItemAddedEvent, value); }
1286 public event ToolStripItemClickedEventHandler ItemClicked {
1287 add { Events.AddHandler (ItemClickedEvent, value); }
1288 remove { Events.RemoveHandler (ItemClickedEvent, value); }
1291 public event ToolStripItemEventHandler ItemRemoved {
1292 add { Events.AddHandler (ItemRemovedEvent, value); }
1293 remove { Events.RemoveHandler (ItemRemovedEvent, value); }
1296 public event EventHandler LayoutCompleted {
1297 add { Events.AddHandler (LayoutCompletedEvent, value); }
1298 remove { Events.RemoveHandler (LayoutCompletedEvent, value); }
1301 public event EventHandler LayoutStyleChanged {
1302 add { Events.AddHandler (LayoutStyleChangedEvent, value); }
1303 remove { Events.RemoveHandler (LayoutStyleChangedEvent, value); }
1306 public event PaintEventHandler PaintGrip {
1307 add { Events.AddHandler (PaintGripEvent, value); }
1308 remove { Events.RemoveHandler (PaintGripEvent, value); }
1311 public event EventHandler RendererChanged {
1312 add { Events.AddHandler (RendererChangedEvent, value); }
1313 remove { Events.RemoveHandler (RendererChangedEvent, value); }
1317 #region Internal Properties
1318 internal virtual bool KeyboardActive
1320 get { return this.keyboard_active; }
1322 if (this.keyboard_active != value) {
1323 this.keyboard_active = value;
1326 Application.KeyboardCapture = this;
1327 else if (Application.KeyboardCapture == this) {
1328 Application.KeyboardCapture = null;
1329 ToolStripManager.ActivatedByKeyboard = false;
1332 // Redraw for mnemonic underlines
1339 #region Private Methods
1340 internal virtual Rectangle CalculateConnectedArea ()
1342 return Rectangle.Empty;
1345 internal void ChangeSelection (ToolStripItem nextItem)
1347 if (Application.KeyboardCapture != this)
1348 ToolStripManager.SetActiveToolStrip (this, ToolStripManager.ActivatedByKeyboard);
1350 foreach (ToolStripItem tsi in this.Items)
1351 if (tsi != nextItem)
1352 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1354 ToolStripItem current = GetCurrentlySelectedItem ();
1356 if (current != null && !(current is ToolStripControlHost))
1357 this.FocusInternal (true);
1359 if (nextItem is ToolStripControlHost)
1360 (nextItem as ToolStripControlHost).Focus ();
1364 if (nextItem.Parent is MenuStrip && (nextItem.Parent as MenuStrip).MenuDroppedDown)
1365 (nextItem as ToolStripMenuItem).HandleAutoExpansion ();
1368 internal virtual void Dismiss ()
1370 this.Dismiss (ToolStripDropDownCloseReason.AppClicked);
1373 internal virtual void Dismiss (ToolStripDropDownCloseReason reason)
1375 // Release our stranglehold on the keyboard
1376 this.KeyboardActive = false;
1378 // Set our drop down flag to false;
1379 this.menu_selected = false;
1381 // Make sure all of our items are deselected and repainted
1382 foreach (ToolStripItem tsi in this.Items)
1383 tsi.Dismiss (reason);
1385 // We probably need to redraw for mnemonic underlines
1389 internal ToolStripItem GetCurrentlySelectedItem ()
1391 foreach (ToolStripItem tsi in this.DisplayedItems)
1398 internal ToolStripItem GetCurrentlyFocusedItem ()
1400 foreach (ToolStripItem tsi in this.DisplayedItems)
1401 if ((tsi is ToolStripControlHost) && (tsi as ToolStripControlHost).Control.Focused)
1407 internal override Size GetPreferredSizeCore (Size proposedSize)
1409 return GetToolStripPreferredSize (proposedSize);
1412 internal virtual Size GetToolStripPreferredSize (Size proposedSize)
1414 Size new_size = Size.Empty;
1416 // TODO: This is total duct tape. We really have to call into the correct
1417 // layout engine, do a dry run of the layout, and find out our true
1418 // preferred dimensions.
1419 if (this.LayoutStyle == ToolStripLayoutStyle.Flow) {
1420 Point currentLocation = Point.Empty;
1423 foreach (ToolStripItem tsi in items) {
1424 if ((DisplayRectangle.Width - currentLocation.X) < (tsi.Width + tsi.Margin.Horizontal)) {
1426 currentLocation.Y += tallest;
1429 currentLocation.X = DisplayRectangle.Left;
1432 // Offset the left margin and set the control to our point
1433 currentLocation.Offset (tsi.Margin.Left, 0);
1434 tallest = Math.Max (tallest, tsi.Height + tsi.Margin.Vertical);
1436 // Update our location pointer
1437 currentLocation.X += tsi.Width + tsi.Margin.Right;
1440 currentLocation.Y += tallest;
1441 return new Size (currentLocation.X, currentLocation.Y);
1444 if (this.orientation == Orientation.Vertical) {
1445 foreach (ToolStripItem tsi in this.items)
1446 if (tsi.Available) {
1447 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1448 new_size.Height += tsi_preferred.Height + tsi.Margin.Top + tsi.Margin.Bottom;
1450 if (new_size.Width < (this.Padding.Horizontal + tsi_preferred.Width + tsi.Margin.Horizontal))
1451 new_size.Width = (this.Padding.Horizontal + tsi_preferred.Width + tsi.Margin.Horizontal);
1454 new_size.Height += (this.GripRectangle.Height + this.GripMargin.Vertical + this.Padding.Vertical + 4);
1456 if (new_size.Width == 0)
1457 new_size.Width = ExplicitBounds.Width;
1461 foreach (ToolStripItem tsi in this.items)
1462 if (tsi.Available) {
1463 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1464 new_size.Width += tsi_preferred.Width + tsi.Margin.Left + tsi.Margin.Right;
1466 if (new_size.Height < (this.Padding.Vertical + tsi_preferred.Height + tsi.Margin.Vertical))
1467 new_size.Height = (this.Padding.Vertical + tsi_preferred.Height + tsi.Margin.Vertical);
1470 new_size.Width += (this.GripRectangle.Width + this.GripMargin.Horizontal + this.Padding.Horizontal + 4);
1472 if (new_size.Height == 0)
1473 new_size.Height = ExplicitBounds.Height;
1475 if (this is StatusStrip)
1476 new_size.Height = Math.Max (new_size.Height, 22);
1482 internal virtual ToolStrip GetTopLevelToolStrip ()
1487 internal virtual void HandleItemClick (ToolStripItem dismissingItem)
1489 this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.ItemClicked);
1492 internal void HideMenus (bool release, ToolStripDropDownCloseReason reason)
1494 if (this is MenuStrip && release && menu_selected)
1495 (this as MenuStrip).FireMenuDeactivate ();
1498 menu_selected = false;
1500 NotifySelectedChanged (null);
1503 internal void NotifySelectedChanged (ToolStripItem tsi)
1505 foreach (ToolStripItem tsi2 in this.DisplayedItems)
1507 if (tsi2 is ToolStripDropDownItem)
1508 (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1510 if (this.OverflowButton != null) {
1511 ToolStripItemCollection tsic = this.OverflowButton.DropDown.DisplayedItems;
1513 foreach (ToolStripItem tsi2 in tsic)
1515 if (tsi2 is ToolStripDropDownItem)
1516 (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1518 this.OverflowButton.HideDropDown ();
1521 foreach (ToolStripItem tsi2 in this.Items)
1523 tsi2.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1526 internal virtual bool OnMenuKey ()
1531 internal virtual bool ProcessArrowKey (Keys keyData)
1537 tsi = this.GetCurrentlySelectedItem ();
1539 if (tsi is ToolStripControlHost)
1542 tsi = this.SelectNextToolStripItem (tsi, true);
1544 if (tsi is ToolStripControlHost)
1545 (tsi as ToolStripControlHost).Focus ();
1549 tsi = this.GetCurrentlySelectedItem ();
1551 tsi = this.SelectNextToolStripItem (tsi, true);
1553 if (tsi is ToolStripControlHost)
1554 (tsi as ToolStripControlHost).Focus ();
1558 tsi = this.GetCurrentlySelectedItem ();
1560 if (tsi is ToolStripControlHost)
1563 tsi = this.SelectNextToolStripItem (tsi, false);
1565 if (tsi is ToolStripControlHost)
1566 (tsi as ToolStripControlHost).Focus ();
1569 case Keys.Shift | Keys.Tab:
1570 tsi = this.GetCurrentlySelectedItem ();
1572 tsi = this.SelectNextToolStripItem (tsi, false);
1574 if (tsi is ToolStripControlHost)
1575 (tsi as ToolStripControlHost).Focus ();
1583 internal virtual ToolStripItem SelectNextToolStripItem (ToolStripItem start, bool forward)
1585 ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Right : ArrowDirection.Left);
1587 if (next_item == null)
1590 this.ChangeSelection (next_item);
1592 if (next_item is ToolStripControlHost)
1593 (next_item as ToolStripControlHost).Focus ();
1598 #region Stuff for ToolTips
1599 private void MouseEnteredItem (ToolStripItem item)
1601 if (this.show_item_tool_tips && !(item is ToolStripTextBox)) {
1602 tooltip_currently_showing = item;
1603 ToolTipTimer.Start ();
1607 private void MouseLeftItem (ToolStripItem item)
1609 ToolTipTimer.Stop ();
1610 ToolTipWindow.Hide (this);
1611 tooltip_currently_showing = null;
1614 private Timer ToolTipTimer {
1616 if (tooltip_timer == null) {
1617 tooltip_timer = new Timer ();
1618 tooltip_timer.Enabled = false;
1619 tooltip_timer.Interval = 500;
1620 tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
1623 return tooltip_timer;
1627 private ToolTip ToolTipWindow {
1629 if (tooltip_window == null)
1630 tooltip_window = new ToolTip ();
1632 return tooltip_window;
1636 private void ToolTipTimer_Tick (object o, EventArgs args)
1638 string tooltip = tooltip_currently_showing.GetToolTip ();
1640 if (!string.IsNullOrEmpty (tooltip))
1641 ToolTipWindow.Present (this, tooltip);
1643 tooltip_currently_showing.FireEvent (EventArgs.Empty, ToolStripItemEventType.MouseHover);
1645 ToolTipTimer.Stop ();
1649 #region Stuff for Merging
1650 internal ToolStrip CurrentlyMergedWith {
1651 get { return this.currently_merged_with; }
1652 set { this.currently_merged_with = value; }
1655 internal List<ToolStripItem> HiddenMergedItems {
1657 if (this.hidden_merged_items == null)
1658 this.hidden_merged_items = new List<ToolStripItem> ();
1660 return this.hidden_merged_items;
1664 internal bool IsCurrentlyMerged {
1665 get { return this.is_currently_merged; }
1667 this.is_currently_merged = value;
1669 if (!value && this is MenuStrip)
1670 foreach (ToolStripMenuItem tsmi in this.Items)
1671 tsmi.DropDown.IsCurrentlyMerged = value;
1675 internal void BeginMerge ()
1677 if (!IsCurrentlyMerged) {
1678 IsCurrentlyMerged = true;
1680 if (this.pre_merge_items == null) {
1681 this.pre_merge_items = new List<ToolStripItem> ();
1683 foreach (ToolStripItem tsi in this.Items)
1684 this.pre_merge_items.Add (tsi);
1689 internal void RevertMergeItem (ToolStripItem item)
1693 // Remove it from it's current Parent
1694 if (item.Parent != null && item.Parent != this) {
1695 if (item.Parent is ToolStripOverflow)
1696 (item.Parent as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1698 item.Parent.Items.RemoveNoOwnerOrLayout (item);
1700 item.Parent = item.Owner;
1703 // Find where the item was before the merge
1704 index = item.Owner.pre_merge_items.IndexOf (item);
1706 // Find the first pre-merge item that was after this item, that
1707 // is currently in the Items collection. Insert our item before
1709 for (int i = index; i < this.pre_merge_items.Count; i++) {
1710 if (this.Items.Contains (this.pre_merge_items[i])) {
1711 item.Owner.Items.InsertNoOwnerOrLayout (this.Items.IndexOf (this.pre_merge_items[i]), item);
1716 // There aren't any items that are supposed to be after this item,
1717 // so just append it to the end.
1718 item.Owner.Items.AddNoOwnerOrLayout (item);
1723 #region ToolStripAccessibleObject
1725 public class ToolStripAccessibleObject : ControlAccessibleObject
1727 #region Public Constructor
1728 public ToolStripAccessibleObject (ToolStrip owner) : base (owner)
1733 #region Public Properties
1734 public override AccessibleRole Role {
1735 get { return AccessibleRole.ToolBar; }
1739 #region Public Methods
1740 public override AccessibleObject GetChild (int index)
1742 return base.GetChild (index);
1745 public override int GetChildCount ()
1747 return (owner as ToolStrip).Items.Count;
1750 public override AccessibleObject HitTest (int x, int y)
1752 return base.HitTest (x, y);