Prevent right click from triggering ToolStrip.OnItemClicked
[mono-project.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStrip.cs
blob0c505ead94ad1c5aad4fc0a093081c4b6363bbf2
1 //
2 // ToolStrip.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Copyright (c) 2006 Jonathan Pobst
25 // Authors:
26 // Jonathan Pobst (monkey@jpobst.com)
29 using System;
30 using System.Runtime.InteropServices;
31 using System.ComponentModel;
32 using System.Drawing;
33 using System.Windows.Forms.Layout;
34 using System.Collections.Generic;
35 using System.ComponentModel.Design.Serialization;
37 namespace System.Windows.Forms
39 [ComVisible (true)]
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;
76 private bool stretch;
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;
85 #endregion
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);
130 #endregion
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; }
157 [Browsable (false)]
158 [EditorBrowsable (EditorBrowsableState.Never)]
159 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
160 public override bool AutoScroll {
161 get { return base.AutoScroll; }
162 set { base.AutoScroll = value; }
165 [Browsable (false)]
166 [EditorBrowsable (EditorBrowsableState.Never)]
167 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
168 public new Size AutoScrollMargin {
169 get { return base.AutoScrollMargin; }
170 set { base.AutoScrollMargin = value; }
173 [Browsable (false)]
174 [EditorBrowsable (EditorBrowsableState.Never)]
175 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
176 public new Size AutoScrollMinSize {
177 get { return base.AutoScrollMinSize; }
178 set { base.AutoScrollMinSize = value; }
181 [Browsable (false)]
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)]
190 [Browsable (true)]
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; }
214 [Browsable (false)]
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; }
227 [Browsable (false)]
228 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
229 public override Cursor Cursor {
230 get { return base.Cursor; }
231 set { base.Cursor = value; }
234 [Browsable (false)]
235 public virtual ToolStripDropDownDirection DefaultDropDownDirection {
236 get { return this.default_drop_down_direction; }
237 set {
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 {
246 get {
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);
250 else
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);
252 else
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);
255 else
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; }
263 set {
264 if (base.Dock != value) {
265 base.Dock = value;
267 switch (value) {
268 case DockStyle.Top:
269 case DockStyle.Bottom:
270 case DockStyle.None:
271 this.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
272 break;
273 case DockStyle.Left:
274 case DockStyle.Right:
275 this.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
276 break;
282 public override Font Font {
283 get { return base.Font; }
284 set {
285 if (base.Font != value) {
286 base.Font = value;
288 foreach (ToolStripItem tsi in this.Items)
289 tsi.OnOwnerFontChanged (EventArgs.Empty);
294 [Browsable (false)]
295 public new Color ForeColor {
296 get { return this.fore_color; }
297 set {
298 if (this.fore_color != value) {
299 this.fore_color = value;
300 this.OnForeColorChanged (EventArgs.Empty);
305 [Browsable (false)]
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; }
312 set {
313 if (this.grip_margin != value) {
314 this.grip_margin = value;
315 this.PerformLayout ();
320 [Browsable (false)]
321 public Rectangle GripRectangle {
322 get {
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);
328 else
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; }
336 set {
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");
346 [Browsable (false)]
347 [EditorBrowsable (EditorBrowsableState.Never)]
348 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
349 public new bool HasChildren {
350 get { return base.HasChildren; }
353 [Browsable (false)]
354 [EditorBrowsable (EditorBrowsableState.Never)]
355 public new HScrollProperties HorizontalScroll {
356 get { return base.HorizontalScroll; }
359 [Browsable (false)]
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.")]
373 [Browsable (false)]
374 [EditorBrowsable (EditorBrowsableState.Advanced)]
375 public bool IsCurrentlyDragging {
376 get { return false; }
379 [Browsable (false)]
380 public bool IsDropDown {
381 get {
382 if (this is ToolStripDropDown)
383 return true;
385 return false;
389 [MergableProperty (false)]
390 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
391 public virtual ToolStripItemCollection Items {
392 get { return this.items; }
395 public override LayoutEngine LayoutEngine {
396 get {
397 if (layout_engine == null)
398 this.layout_engine = new ToolStripSplitStackLayout ();
400 return this.layout_engine;
404 [Browsable (false)]
405 [DefaultValue (null)]
406 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
407 public LayoutSettings LayoutSettings {
408 get { return this.layout_settings; }
409 set {
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; }
420 set {
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 ();
429 else
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;
435 else
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);
452 [Browsable (false)]
453 public Orientation Orientation {
454 get { return this.orientation; }
457 [Browsable (false)]
458 [EditorBrowsable (EditorBrowsableState.Advanced)]
459 public ToolStripOverflowButton OverflowButton {
460 get { return this.overflow_button; }
463 [Browsable (false)]
464 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
465 public ToolStripRenderer Renderer {
466 get {
467 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
468 return ToolStripManager.Renderer;
470 return this.renderer;
472 set {
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; }
484 set {
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)]
512 [DispId(-516)]
513 public new bool TabStop {
514 get { return base.TabStop; }
515 set {
516 base.TabStop = value;
517 SetStyle (ControlStyles.Selectable, value);
521 [DefaultValue (ToolStripTextDirection.Horizontal)]
522 public virtual ToolStripTextDirection TextDirection {
523 get { return this.text_direction; }
524 set {
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");
533 this.Invalidate ();
538 [Browsable (false)]
539 [EditorBrowsable (EditorBrowsableState.Never)]
540 public new VScrollProperties VerticalScroll {
541 get { return base.VerticalScroll; }
543 #endregion
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); }
556 #endregion
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))
575 return tsi;
577 return null;
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;
593 switch (direction) {
594 case ArrowDirection.Right:
595 current_best_point = int.MaxValue;
597 if (start != null)
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;
611 break;
612 case ArrowDirection.Up:
613 current_best_point = int.MinValue;
615 if (start != null)
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;
629 break;
630 case ArrowDirection.Left:
631 current_best_point = int.MinValue;
633 if (start != null)
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;
647 break;
648 case ArrowDirection.Down:
649 current_best_point = int.MaxValue;
651 if (start != null)
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;
665 break;
668 return current_best;
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 ());
687 #endregion
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)
702 if (text == "-")
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:
721 default:
722 return null;
726 protected override void Dispose (bool disposing)
728 if (!IsDisposed) {
730 if(disposing) {
731 // Event Handler must be stopped before disposing Items.
732 Events.Dispose();
734 CloseToolTip (null);
735 // ToolStripItem.Dispose modifes the collection,
736 // so we iterate it in reverse order
737 for (int i = Items.Count - 1; i >= 0; i--)
738 Items [i].Dispose ();
740 if (this.overflow_button != null && this.overflow_button.drop_down != null)
741 this.overflow_button.drop_down.Dispose ();
743 ToolStripManager.RemoveToolStrip (this);
745 base.Dispose (disposing);
749 [MonoTODO ("Stub, never called")]
750 protected virtual void OnBeginDrag (EventArgs e)
752 EventHandler eh = (EventHandler)(Events[BeginDragEvent]);
753 if (eh != null)
754 eh (this, e);
757 protected override void OnDockChanged (EventArgs e)
759 base.OnDockChanged (e);
762 [MonoTODO ("Stub, never called")]
763 protected virtual void OnEndDrag (EventArgs e)
765 EventHandler eh = (EventHandler)(Events[EndDragEvent]);
766 if (eh != null)
767 eh (this, e);
770 protected override bool IsInputChar (char charCode)
772 return base.IsInputChar (charCode);
775 protected override bool IsInputKey (Keys keyData)
777 return base.IsInputKey (keyData);
780 protected override void OnEnabledChanged (EventArgs e)
782 base.OnEnabledChanged (e);
784 foreach (ToolStripItem tsi in this.Items)
785 tsi.OnParentEnabledChanged (EventArgs.Empty);
788 protected override void OnFontChanged (EventArgs e)
790 base.OnFontChanged (e);
793 protected override void OnHandleCreated (EventArgs e)
795 base.OnHandleCreated (e);
798 protected override void OnHandleDestroyed (EventArgs e)
800 base.OnHandleDestroyed (e);
803 protected override void OnInvalidated (InvalidateEventArgs e)
805 base.OnInvalidated (e);
808 protected internal virtual void OnItemAdded (ToolStripItemEventArgs e)
810 if (e.Item.InternalVisible)
811 e.Item.Available = true;
813 e.Item.SetPlacement (ToolStripItemPlacement.Main);
815 if (this.Created)
816 this.PerformLayout ();
818 ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemAddedEvent]);
819 if (eh != null)
820 eh (this, e);
823 protected virtual void OnItemClicked (ToolStripItemClickedEventArgs e)
825 if (this.KeyboardActive)
826 ToolStripManager.SetActiveToolStrip (null, false);
828 ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [ItemClickedEvent]);
829 if (eh != null)
830 eh (this, e);
833 protected internal virtual void OnItemRemoved (ToolStripItemEventArgs e)
835 ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemRemovedEvent]);
836 if (eh != null)
837 eh (this, e);
840 protected override void OnLayout (LayoutEventArgs e)
842 base.OnLayout (e);
844 this.SetDisplayedItems ();
845 this.OnLayoutCompleted (EventArgs.Empty);
846 this.Invalidate ();
849 protected virtual void OnLayoutCompleted (EventArgs e)
851 EventHandler eh = (EventHandler)(Events [LayoutCompletedEvent]);
852 if (eh != null)
853 eh (this, e);
856 protected virtual void OnLayoutStyleChanged (EventArgs e)
858 EventHandler eh = (EventHandler)(Events[LayoutStyleChangedEvent]);
859 if (eh != null)
860 eh (this, e);
863 protected override void OnLeave (EventArgs e)
865 base.OnLeave (e);
868 protected override void OnLostFocus (EventArgs e)
870 base.OnLostFocus (e);
873 protected override void OnMouseCaptureChanged (EventArgs e)
875 base.OnMouseCaptureChanged (e);
878 protected override void OnMouseDown (MouseEventArgs mea)
880 if (mouse_currently_over != null)
882 ToolStripItem focused = GetCurrentlyFocusedItem ();
884 if (focused != null && focused != mouse_currently_over)
885 this.FocusInternal (true);
887 if (this is MenuStrip && !menu_selected) {
888 (this as MenuStrip).FireMenuActivate ();
889 menu_selected = true;
892 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseDown);
894 if (this is MenuStrip && mouse_currently_over is ToolStripMenuItem && !(mouse_currently_over as ToolStripMenuItem).HasDropDownItems)
895 return;
896 } else {
897 this.Dismiss (ToolStripDropDownCloseReason.AppClicked);
900 if (this is MenuStrip)
901 this.Capture = false;
903 base.OnMouseDown (mea);
906 protected override void OnMouseLeave (EventArgs e)
908 if (mouse_currently_over != null) {
909 MouseLeftItem (mouse_currently_over);
910 mouse_currently_over.FireEvent (e, ToolStripItemEventType.MouseLeave);
911 mouse_currently_over = null;
914 base.OnMouseLeave (e);
917 protected override void OnMouseMove (MouseEventArgs mea)
919 ToolStripItem tsi;
920 // Find the item we are now
921 if (this.overflow_button != null && this.overflow_button.Visible && this.overflow_button.Bounds.Contains (mea.Location))
922 tsi = this.overflow_button;
923 else
924 tsi = this.GetItemAt (mea.X, mea.Y);
926 if (tsi != null) {
927 // If we were already hovering on this item, just send a mouse move
928 if (tsi == mouse_currently_over)
929 tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
930 else {
931 // If we were over a different item, fire a mouse leave on it
932 if (mouse_currently_over != null) {
933 MouseLeftItem (tsi);
934 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
937 // Set the new item we are currently over
938 mouse_currently_over = tsi;
940 // Fire mouse enter and mouse move
941 tsi.FireEvent (mea, ToolStripItemEventType.MouseEnter);
942 MouseEnteredItem (tsi);
943 tsi.FireEvent (mea, ToolStripItemEventType.MouseMove);
945 // If we're over something with a drop down, show it
946 if (menu_selected && mouse_currently_over.Enabled && mouse_currently_over is ToolStripDropDownItem && (mouse_currently_over as ToolStripDropDownItem).HasDropDownItems)
947 (mouse_currently_over as ToolStripDropDownItem).ShowDropDown ();
949 } else {
950 // We're not over anything now, just fire the mouse leave on what we used to be over
951 if (mouse_currently_over != null) {
952 MouseLeftItem (tsi);
953 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave);
954 mouse_currently_over = null;
958 base.OnMouseMove (mea);
961 protected override void OnMouseUp (MouseEventArgs mea)
963 // If we're currently over an item (set in MouseMove)
964 if (mouse_currently_over != null && !(mouse_currently_over is ToolStripControlHost) && mouse_currently_over.Enabled) {
965 // Fire our ItemClicked event, but only for a left mouse click.
966 if (mea.Button == MouseButtons.Left)
967 OnItemClicked (new ToolStripItemClickedEventArgs (mouse_currently_over));
969 // Fire the item's MouseUp event
970 if (mouse_currently_over != null)
971 mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseUp);
973 // The event handler may have blocked until the mouse moved off of the ToolStripItem
974 if (mouse_currently_over == null)
975 return;
978 base.OnMouseUp (mea);
981 protected override void OnPaint (PaintEventArgs e)
983 base.OnPaint (e);
985 // Draw the grip
986 this.OnPaintGrip (e);
988 // Make each item draw itself
989 for (int i = 0; i < displayed_items.Count; i++) {
990 ToolStripItem tsi = displayed_items[i];
992 if (tsi.Visible) {
993 e.Graphics.TranslateTransform (tsi.Bounds.Left, tsi.Bounds.Top);
994 tsi.FireEvent (e, ToolStripItemEventType.Paint);
995 e.Graphics.ResetTransform ();
999 // Paint the Overflow button if it's visible
1000 if (this.overflow_button != null && this.overflow_button.Visible) {
1001 e.Graphics.TranslateTransform (this.overflow_button.Bounds.Left, this.overflow_button.Bounds.Top);
1002 this.overflow_button.FireEvent (e, ToolStripItemEventType.Paint);
1003 e.Graphics.ResetTransform ();
1006 Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size);
1008 ToolStripRenderEventArgs pevent = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, Color.Empty);
1009 pevent.InternalConnectedArea = CalculateConnectedArea ();
1011 this.Renderer.DrawToolStripBorder (pevent);
1014 [EditorBrowsable (EditorBrowsableState.Advanced)]
1015 protected override void OnPaintBackground (PaintEventArgs e)
1017 base.OnPaintBackground (e);
1019 Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size);
1020 ToolStripRenderEventArgs tsrea = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, SystemColors.Control);
1022 this.Renderer.DrawToolStripBackground (tsrea);
1025 protected internal virtual void OnPaintGrip (PaintEventArgs e)
1027 // Never draw a grip with these two layouts
1028 if (this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table)
1029 return;
1031 PaintEventHandler eh = (PaintEventHandler)(Events [PaintGripEvent]);
1032 if (eh != null)
1033 eh (this, e);
1035 if (!(this is MenuStrip)) {
1036 if (this.orientation == Orientation.Horizontal)
1037 e.Graphics.TranslateTransform (2, 0);
1038 else
1039 e.Graphics.TranslateTransform (0, 2);
1042 this.Renderer.DrawGrip (new ToolStripGripRenderEventArgs (e.Graphics, this, this.GripRectangle, this.GripDisplayStyle, this.grip_style));
1043 e.Graphics.ResetTransform ();
1046 protected virtual void OnRendererChanged (EventArgs e)
1048 EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
1049 if (eh != null)
1050 eh (this, e);
1053 [EditorBrowsable (EditorBrowsableState.Advanced)]
1054 protected override void OnRightToLeftChanged (EventArgs e)
1056 base.OnRightToLeftChanged (e);
1058 foreach (ToolStripItem tsi in this.Items)
1059 tsi.OnParentRightToLeftChanged (e);
1062 protected override void OnScroll (ScrollEventArgs se)
1064 base.OnScroll (se);
1067 protected override void OnTabStopChanged (EventArgs e)
1069 base.OnTabStopChanged (e);
1072 protected override void OnVisibleChanged (EventArgs e)
1074 if (!Visible)
1075 CloseToolTip (null);
1077 base.OnVisibleChanged (e);
1080 protected override bool ProcessCmdKey (ref Message m, Keys keyData)
1082 return base.ProcessCmdKey (ref m, keyData);
1085 protected override bool ProcessDialogKey (Keys keyData)
1087 if (!this.KeyboardActive)
1088 return false;
1090 // Give each item a chance to handle the key
1091 foreach (ToolStripItem tsi in this.Items)
1092 if (tsi.ProcessDialogKey (keyData))
1093 return true;
1095 // See if I want to handle it
1096 if (this.ProcessArrowKey (keyData))
1097 return true;
1099 ToolStrip ts = null;
1101 switch (keyData) {
1102 case Keys.Escape:
1103 this.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1104 return true;
1106 case Keys.Control | Keys.Tab:
1107 ts = ToolStripManager.GetNextToolStrip (this, true);
1109 if (ts != null) {
1110 foreach (ToolStripItem tsi in this.Items)
1111 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1113 ToolStripManager.SetActiveToolStrip (ts, true);
1114 ts.SelectNextToolStripItem (null, true);
1117 return true;
1118 case Keys.Control | Keys.Shift | Keys.Tab:
1119 ts = ToolStripManager.GetNextToolStrip (this, false);
1121 if (ts != null) {
1122 foreach (ToolStripItem tsi in this.Items)
1123 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1125 ToolStripManager.SetActiveToolStrip (ts, true);
1126 ts.SelectNextToolStripItem (null, true);
1129 return true;
1130 case Keys.Down:
1131 case Keys.Up:
1132 case Keys.Left:
1133 case Keys.Right:
1134 if (GetCurrentlySelectedItem () is ToolStripControlHost)
1135 return false;
1136 break;
1139 return base.ProcessDialogKey (keyData);
1142 protected override bool ProcessMnemonic (char charCode)
1144 // If any item has an explicit mnemonic, it gets the message
1145 foreach (ToolStripItem tsi in this.Items)
1146 if (tsi.Enabled && tsi.Visible && !string.IsNullOrEmpty (tsi.Text) && Control.IsMnemonic (charCode, tsi.Text))
1147 return tsi.ProcessMnemonic (charCode);
1149 // Do not try to match any further here. See Xamarin bug 23532.
1151 return base.ProcessMnemonic (charCode);
1154 [MonoTODO ("Stub, does nothing")]
1155 [EditorBrowsable (EditorBrowsableState.Advanced)]
1156 protected virtual void RestoreFocus ()
1160 protected override void Select (bool directed, bool forward)
1162 foreach (ToolStripItem tsi in this.DisplayedItems)
1163 if (tsi.CanSelect) {
1164 tsi.Select ();
1165 break;
1169 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
1171 base.SetBoundsCore (x, y, width, height, specified);
1174 protected virtual void SetDisplayedItems ()
1176 this.displayed_items.ClearInternal ();
1178 foreach (ToolStripItem tsi in this.items)
1179 if (tsi.Placement == ToolStripItemPlacement.Main && tsi.Available) {
1180 this.displayed_items.AddNoOwnerOrLayout (tsi);
1181 tsi.Parent = this;
1183 else if (tsi.Placement == ToolStripItemPlacement.Overflow)
1184 tsi.Parent = this.OverflowButton.DropDown;
1186 if (this.OverflowButton != null)
1187 this.OverflowButton.DropDown.SetDisplayedItems ();
1190 protected internal void SetItemLocation (ToolStripItem item, Point location)
1192 if (item == null)
1193 throw new ArgumentNullException ("item");
1195 if (item.Owner != this)
1196 throw new NotSupportedException ("The item is not owned by this ToolStrip");
1198 item.SetBounds (new Rectangle (location, item.Size));
1201 protected internal static void SetItemParent (ToolStripItem item, ToolStrip parent)
1203 if (item.Owner != null) {
1204 item.Owner.Items.RemoveNoOwnerOrLayout (item);
1206 if (item.Owner is ToolStripOverflow)
1207 (item.Owner as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1210 parent.Items.AddNoOwnerOrLayout (item);
1211 item.Parent = parent;
1214 protected override void SetVisibleCore (bool visible)
1216 base.SetVisibleCore (visible);
1219 protected override void WndProc (ref Message m)
1221 base.WndProc (ref m);
1223 #endregion
1225 #region Public Events
1226 static object BeginDragEvent = new object ();
1227 static object EndDragEvent = new object ();
1228 static object ItemAddedEvent = new object ();
1229 static object ItemClickedEvent = new object ();
1230 static object ItemRemovedEvent = new object ();
1231 static object LayoutCompletedEvent = new object ();
1232 static object LayoutStyleChangedEvent = new object ();
1233 static object PaintGripEvent = new object ();
1234 static object RendererChangedEvent = new object ();
1236 [Browsable (true)]
1237 [EditorBrowsable (EditorBrowsableState.Always)]
1238 public new event EventHandler AutoSizeChanged {
1239 add { base.AutoSizeChanged += value; }
1240 remove { base.AutoSizeChanged -= value; }
1243 [MonoTODO ("Event never raised")]
1244 public event EventHandler BeginDrag {
1245 add { Events.AddHandler (BeginDragEvent, value); }
1246 remove { Events.RemoveHandler (BeginDragEvent, value); }
1249 [Browsable (false)]
1250 public new event EventHandler CausesValidationChanged {
1251 add { base.CausesValidationChanged += value; }
1252 remove { base.CausesValidationChanged -= value; }
1255 [Browsable (false)]
1256 [EditorBrowsable (EditorBrowsableState.Never)]
1257 public new event ControlEventHandler ControlAdded {
1258 add { base.ControlAdded += value; }
1259 remove { base.ControlAdded -= value; }
1262 [Browsable (false)]
1263 [EditorBrowsable (EditorBrowsableState.Never)]
1264 public new event ControlEventHandler ControlRemoved {
1265 add { base.ControlRemoved += value; }
1266 remove { base.ControlRemoved -= value; }
1269 [Browsable (false)]
1270 public new event EventHandler CursorChanged {
1271 add { base.CursorChanged += value; }
1272 remove { base.CursorChanged -= value; }
1275 [MonoTODO ("Event never raised")]
1276 public event EventHandler EndDrag {
1277 add { Events.AddHandler (EndDragEvent, value); }
1278 remove { Events.RemoveHandler (EndDragEvent, value); }
1281 [Browsable (false)]
1282 public new event EventHandler ForeColorChanged {
1283 add { base.ForeColorChanged += value; }
1284 remove { base.ForeColorChanged -= value; }
1287 public event ToolStripItemEventHandler ItemAdded {
1288 add { Events.AddHandler (ItemAddedEvent, value); }
1289 remove { Events.RemoveHandler (ItemAddedEvent, value); }
1292 public event ToolStripItemClickedEventHandler ItemClicked {
1293 add { Events.AddHandler (ItemClickedEvent, value); }
1294 remove { Events.RemoveHandler (ItemClickedEvent, value); }
1297 public event ToolStripItemEventHandler ItemRemoved {
1298 add { Events.AddHandler (ItemRemovedEvent, value); }
1299 remove { Events.RemoveHandler (ItemRemovedEvent, value); }
1302 public event EventHandler LayoutCompleted {
1303 add { Events.AddHandler (LayoutCompletedEvent, value); }
1304 remove { Events.RemoveHandler (LayoutCompletedEvent, value); }
1307 public event EventHandler LayoutStyleChanged {
1308 add { Events.AddHandler (LayoutStyleChangedEvent, value); }
1309 remove { Events.RemoveHandler (LayoutStyleChangedEvent, value); }
1312 public event PaintEventHandler PaintGrip {
1313 add { Events.AddHandler (PaintGripEvent, value); }
1314 remove { Events.RemoveHandler (PaintGripEvent, value); }
1317 public event EventHandler RendererChanged {
1318 add { Events.AddHandler (RendererChangedEvent, value); }
1319 remove { Events.RemoveHandler (RendererChangedEvent, value); }
1321 #endregion
1323 #region Internal Properties
1324 internal virtual bool KeyboardActive
1326 get { return this.keyboard_active; }
1327 set {
1328 if (this.keyboard_active != value) {
1329 this.keyboard_active = value;
1331 if (value)
1332 Application.KeyboardCapture = this;
1333 else if (Application.KeyboardCapture == this) {
1334 Application.KeyboardCapture = null;
1335 ToolStripManager.ActivatedByKeyboard = false;
1338 // Redraw for mnemonic underlines
1339 this.Invalidate ();
1343 #endregion
1345 #region Private Methods
1346 internal virtual Rectangle CalculateConnectedArea ()
1348 return Rectangle.Empty;
1351 internal void ChangeSelection (ToolStripItem nextItem)
1353 if (Application.KeyboardCapture != this)
1354 ToolStripManager.SetActiveToolStrip (this, ToolStripManager.ActivatedByKeyboard);
1356 foreach (ToolStripItem tsi in this.Items)
1357 if (tsi != nextItem)
1358 tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1360 ToolStripItem current = GetCurrentlySelectedItem ();
1362 if (current != null && !(current is ToolStripControlHost))
1363 this.FocusInternal (true);
1365 if (nextItem is ToolStripControlHost)
1366 (nextItem as ToolStripControlHost).Focus ();
1368 nextItem.Select ();
1370 if (nextItem.Parent is MenuStrip && (nextItem.Parent as MenuStrip).MenuDroppedDown)
1371 (nextItem as ToolStripMenuItem).HandleAutoExpansion ();
1374 internal virtual void Dismiss ()
1376 this.Dismiss (ToolStripDropDownCloseReason.AppClicked);
1379 internal virtual void Dismiss (ToolStripDropDownCloseReason reason)
1381 // Release our stranglehold on the keyboard
1382 this.KeyboardActive = false;
1384 // Set our drop down flag to false;
1385 this.menu_selected = false;
1387 // Make sure all of our items are deselected and repainted
1388 foreach (ToolStripItem tsi in this.Items)
1389 tsi.Dismiss (reason);
1391 // We probably need to redraw for mnemonic underlines
1392 this.Invalidate ();
1395 internal ToolStripItem GetCurrentlySelectedItem ()
1397 foreach (ToolStripItem tsi in this.DisplayedItems)
1398 if (tsi.Selected)
1399 return tsi;
1401 return null;
1404 internal ToolStripItem GetCurrentlyFocusedItem ()
1406 foreach (ToolStripItem tsi in this.DisplayedItems)
1407 if ((tsi is ToolStripControlHost) && (tsi as ToolStripControlHost).Control.Focused)
1408 return tsi;
1410 return null;
1413 internal override Size GetPreferredSizeCore (Size proposedSize)
1415 return GetToolStripPreferredSize (proposedSize);
1418 internal virtual Size GetToolStripPreferredSize (Size proposedSize)
1420 Size new_size = Size.Empty;
1422 // TODO: This is total duct tape. We really have to call into the correct
1423 // layout engine, do a dry run of the layout, and find out our true
1424 // preferred dimensions.
1425 if (this.LayoutStyle == ToolStripLayoutStyle.Flow) {
1426 Point currentLocation = Point.Empty;
1427 int tallest = 0;
1429 foreach (ToolStripItem tsi in items)
1430 if (tsi.Available) {
1431 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1433 if ((DisplayRectangle.Width - currentLocation.X) < (tsi_preferred.Width + tsi.Margin.Horizontal)) {
1435 currentLocation.Y += tallest;
1436 tallest = 0;
1438 currentLocation.X = DisplayRectangle.Left;
1441 // Offset the left margin and set the control to our point
1442 currentLocation.Offset (tsi.Margin.Left, 0);
1443 tallest = Math.Max (tallest, tsi_preferred.Height + tsi.Margin.Vertical);
1445 // Update our location pointer
1446 currentLocation.X += tsi_preferred.Width + tsi.Margin.Right;
1449 currentLocation.Y += tallest;
1450 return new Size (currentLocation.X + this.Padding.Horizontal, currentLocation.Y + this.Padding.Vertical);
1453 if (this.orientation == Orientation.Vertical) {
1454 foreach (ToolStripItem tsi in this.items)
1455 if (tsi.Available) {
1456 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1457 new_size.Height += tsi_preferred.Height + tsi.Margin.Top + tsi.Margin.Bottom;
1459 if (new_size.Width < (this.Padding.Horizontal + tsi_preferred.Width + tsi.Margin.Horizontal))
1460 new_size.Width = (this.Padding.Horizontal + tsi_preferred.Width + tsi.Margin.Horizontal);
1463 new_size.Height += (this.GripRectangle.Height + this.GripMargin.Vertical + this.Padding.Vertical + 4);
1465 if (new_size.Width == 0)
1466 new_size.Width = ExplicitBounds.Width;
1468 return new_size;
1469 } else {
1470 foreach (ToolStripItem tsi in this.items)
1471 if (tsi.Available) {
1472 Size tsi_preferred = tsi.GetPreferredSize (Size.Empty);
1473 new_size.Width += tsi_preferred.Width + tsi.Margin.Left + tsi.Margin.Right;
1475 if (new_size.Height < (this.Padding.Vertical + tsi_preferred.Height + tsi.Margin.Vertical))
1476 new_size.Height = (this.Padding.Vertical + tsi_preferred.Height + tsi.Margin.Vertical);
1479 new_size.Width += (this.GripRectangle.Width + this.GripMargin.Horizontal + this.Padding.Horizontal + 4);
1481 if (new_size.Height == 0)
1482 new_size.Height = ExplicitBounds.Height;
1484 if (this is StatusStrip)
1485 new_size.Height = Math.Max (new_size.Height, 22);
1487 return new_size;
1491 internal virtual ToolStrip GetTopLevelToolStrip ()
1493 return this;
1496 internal virtual void HandleItemClick (ToolStripItem dismissingItem)
1498 this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.ItemClicked);
1501 internal void NotifySelectedChanged (ToolStripItem tsi)
1503 foreach (ToolStripItem tsi2 in this.DisplayedItems)
1504 if (tsi != tsi2)
1505 if (tsi2 is ToolStripDropDownItem)
1506 (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1508 if (this.OverflowButton != null) {
1509 ToolStripItemCollection tsic = this.OverflowButton.DropDown.DisplayedItems;
1511 foreach (ToolStripItem tsi2 in tsic)
1512 if (tsi != tsi2)
1513 if (tsi2 is ToolStripDropDownItem)
1514 (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard);
1516 this.OverflowButton.HideDropDown ();
1519 foreach (ToolStripItem tsi2 in this.Items)
1520 if (tsi != tsi2)
1521 tsi2.Dismiss (ToolStripDropDownCloseReason.Keyboard);
1524 internal virtual bool OnMenuKey ()
1526 return false;
1529 internal virtual bool ProcessArrowKey (Keys keyData)
1531 ToolStripItem tsi;
1533 switch (keyData) {
1534 case Keys.Right:
1535 tsi = this.GetCurrentlySelectedItem ();
1537 if (tsi is ToolStripControlHost)
1538 return false;
1540 tsi = this.SelectNextToolStripItem (tsi, true);
1542 if (tsi is ToolStripControlHost)
1543 (tsi as ToolStripControlHost).Focus ();
1545 return true;
1546 case Keys.Tab:
1547 tsi = this.GetCurrentlySelectedItem ();
1549 tsi = this.SelectNextToolStripItem (tsi, true);
1551 if (tsi is ToolStripControlHost)
1552 (tsi as ToolStripControlHost).Focus ();
1554 return true;
1555 case Keys.Left:
1556 tsi = this.GetCurrentlySelectedItem ();
1558 if (tsi is ToolStripControlHost)
1559 return false;
1561 tsi = this.SelectNextToolStripItem (tsi, false);
1563 if (tsi is ToolStripControlHost)
1564 (tsi as ToolStripControlHost).Focus ();
1566 return true;
1567 case Keys.Shift | Keys.Tab:
1568 tsi = this.GetCurrentlySelectedItem ();
1570 tsi = this.SelectNextToolStripItem (tsi, false);
1572 if (tsi is ToolStripControlHost)
1573 (tsi as ToolStripControlHost).Focus ();
1575 return true;
1578 return false;
1581 internal virtual ToolStripItem SelectNextToolStripItem (ToolStripItem start, bool forward)
1583 ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Right : ArrowDirection.Left);
1585 if (next_item == null)
1586 return next_item;
1588 this.ChangeSelection (next_item);
1590 if (next_item is ToolStripControlHost)
1591 (next_item as ToolStripControlHost).Focus ();
1593 return next_item;
1596 #region Stuff for ToolTips
1597 private void MouseEnteredItem (ToolStripItem item)
1599 if (this.show_item_tool_tips && !(item is ToolStripTextBox)) {
1600 ToolTipTimer.Interval = InitialToolTipDelay;
1601 tooltip_state = ToolTip.TipState.Initial;
1602 tooltip_currently_showing = item;
1603 ToolTipTimer.Start ();
1607 private void CloseToolTip (ToolStripItem item)
1609 ToolTipTimer.Stop ();
1610 ToolTipWindow.Hide (this);
1611 tooltip_currently_showing = null;
1612 tooltip_state = ToolTip.TipState.Down;
1615 private void MouseLeftItem (ToolStripItem item)
1617 CloseToolTip (item);
1620 private Timer ToolTipTimer {
1621 get {
1622 if (tooltip_timer == null) {
1623 tooltip_timer = new Timer ();
1624 tooltip_timer.Enabled = false;
1625 tooltip_timer.Interval = InitialToolTipDelay;
1626 tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
1629 return tooltip_timer;
1633 private ToolTip ToolTipWindow {
1634 get {
1635 if (tooltip_window == null)
1636 tooltip_window = new ToolTip ();
1638 return tooltip_window;
1642 private void ShowToolTip ()
1644 string tooltip = tooltip_currently_showing.GetToolTip ();
1646 if (!string.IsNullOrEmpty (tooltip)) {
1647 ToolTipWindow.Present (this, tooltip);
1648 ToolTipTimer.Interval = ToolTipDelay;
1649 ToolTipTimer.Start ();
1650 tooltip_state = ToolTip.TipState.Show;
1653 tooltip_currently_showing.FireEvent (EventArgs.Empty, ToolStripItemEventType.MouseHover);
1656 private void ToolTipTimer_Tick (object o, EventArgs args)
1658 ToolTipTimer.Stop ();
1660 switch (tooltip_state) {
1661 case ToolTip.TipState.Initial:
1662 ShowToolTip ();
1663 break;
1664 case ToolTip.TipState.Show:
1665 CloseToolTip (null);
1666 break;
1669 #endregion
1671 #region Stuff for Merging
1672 internal ToolStrip CurrentlyMergedWith {
1673 get { return this.currently_merged_with; }
1674 set { this.currently_merged_with = value; }
1677 internal List<ToolStripItem> HiddenMergedItems {
1678 get {
1679 if (this.hidden_merged_items == null)
1680 this.hidden_merged_items = new List<ToolStripItem> ();
1682 return this.hidden_merged_items;
1686 internal bool IsCurrentlyMerged {
1687 get { return this.is_currently_merged; }
1688 set {
1689 this.is_currently_merged = value;
1691 if (!value && this is MenuStrip)
1692 foreach (ToolStripMenuItem tsmi in this.Items)
1693 tsmi.DropDown.IsCurrentlyMerged = value;
1697 internal void BeginMerge ()
1699 if (!IsCurrentlyMerged) {
1700 IsCurrentlyMerged = true;
1702 if (this.pre_merge_items == null) {
1703 this.pre_merge_items = new List<ToolStripItem> ();
1705 foreach (ToolStripItem tsi in this.Items)
1706 this.pre_merge_items.Add (tsi);
1711 internal void RevertMergeItem (ToolStripItem item)
1713 int index = 0;
1715 // Remove it from it's current Parent
1716 if (item.Parent != null && item.Parent != this) {
1717 if (item.Parent is ToolStripOverflow)
1718 (item.Parent as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item);
1719 else
1720 item.Parent.Items.RemoveNoOwnerOrLayout (item);
1722 item.Parent = item.Owner;
1725 // Find where the item was before the merge
1726 index = item.Owner.pre_merge_items.IndexOf (item);
1728 // Find the first pre-merge item that was after this item, that
1729 // is currently in the Items collection. Insert our item before
1730 // that one.
1731 for (int i = index; i < this.pre_merge_items.Count; i++) {
1732 if (this.Items.Contains (this.pre_merge_items[i])) {
1733 item.Owner.Items.InsertNoOwnerOrLayout (this.Items.IndexOf (this.pre_merge_items[i]), item);
1734 return;
1738 // There aren't any items that are supposed to be after this item,
1739 // so just append it to the end.
1740 item.Owner.Items.AddNoOwnerOrLayout (item);
1742 #endregion
1743 #endregion
1745 #region ToolStripAccessibleObject
1746 [ComVisible (true)]
1747 public class ToolStripAccessibleObject : ControlAccessibleObject
1749 #region Public Constructor
1750 public ToolStripAccessibleObject (ToolStrip owner) : base (owner)
1753 #endregion
1755 #region Public Properties
1756 public override AccessibleRole Role {
1757 get { return AccessibleRole.ToolBar; }
1759 #endregion
1761 #region Public Methods
1762 public override AccessibleObject GetChild (int index)
1764 return base.GetChild (index);
1767 public override int GetChildCount ()
1769 return (owner as ToolStrip).Items.Count;
1772 public override AccessibleObject HitTest (int x, int y)
1774 return base.HitTest (x, y);
1776 #endregion
1778 #endregion