diff options
| author | MichaelTheShifter <[email protected]> | 2016-07-20 09:40:36 -0400 |
|---|---|---|
| committer | MichaelTheShifter <[email protected]> | 2016-07-20 09:40:36 -0400 |
| commit | d40fed5ce2bc806a91245adb18039634eac13ed0 (patch) | |
| tree | f1d7168aee6db109ac2c738ad18c9db667a6ba69 /source/ShiftUI/ToolStrip/ToolStrip.cs | |
| parent | f1856e8ed30ed882229fd3fa2a4038122a5fb441 (diff) | |
| download | shiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.tar.gz shiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.tar.bz2 shiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.zip | |
Move ShiftUI source code to ShiftOS
This'll be a lot easier to work on.
Diffstat (limited to 'source/ShiftUI/ToolStrip/ToolStrip.cs')
| -rw-r--r-- | source/ShiftUI/ToolStrip/ToolStrip.cs | 1778 |
1 files changed, 1778 insertions, 0 deletions
diff --git a/source/ShiftUI/ToolStrip/ToolStrip.cs b/source/ShiftUI/ToolStrip/ToolStrip.cs new file mode 100644 index 0000000..b784458 --- /dev/null +++ b/source/ShiftUI/ToolStrip/ToolStrip.cs @@ -0,0 +1,1778 @@ +// +// ToolStrip.cs +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2006 Jonathan Pobst +// +// Authors: +// Jonathan Pobst ([email protected]) +// + +using System; +using System.Runtime.InteropServices; +using System.ComponentModel; +using System.Drawing; +using ShiftUI.Layout; +using System.Collections.Generic; +using System.ComponentModel.Design.Serialization; + +namespace ShiftUI +{ + [ComVisible (true)] + [ClassInterface (ClassInterfaceType.AutoDispatch)] + [DefaultEvent ("ItemClicked")] + [DefaultProperty ("Items")] + public class ToolStrip : ScrollableWidget, IComponent, IDisposable, IToolStripData + { + #region Private Variables + private bool allow_item_reorder; + private bool allow_merge; + private Color back_color; + private bool can_overflow; + private ToolStrip currently_merged_with; + private ToolStripDropDownDirection default_drop_down_direction; + internal ToolStripItemCollection displayed_items; + private Color fore_color; + private Padding grip_margin; + private ToolStripGripStyle grip_style; + private List<ToolStripItem> hidden_merged_items; + private ImageList image_list; + private Size image_scaling_size; + private bool is_currently_merged; + private ToolStripItemCollection items; + private bool keyboard_active; + private LayoutEngine layout_engine; + private LayoutSettings layout_settings; + private ToolStripLayoutStyle layout_style; + private Orientation orientation; + private ToolStripOverflowButton overflow_button; + private List<ToolStripItem> pre_merge_items; + private ToolStripRenderer renderer; + private ToolStripRenderMode render_mode; + private ToolStripTextDirection text_direction; + private Timer tooltip_timer; + private ToolTip tooltip_window; + private bool show_item_tool_tips; + private bool stretch; + + private ToolStripItem mouse_currently_over; + internal bool menu_selected; + private ToolStripItem tooltip_currently_showing; + private ToolTip.TipState tooltip_state; + + const int InitialToolTipDelay = 500; + const int ToolTipDelay = 5000; + #endregion + + #region Public Constructors + public ToolStrip () : this (null) + { + } + + public ToolStrip (params ToolStripItem[] items) : base () + { + SetStyle (Widgetstyles.AllPaintingInWmPaint, true); + SetStyle (Widgetstyles.OptimizedDoubleBuffer, true); + SetStyle (Widgetstyles.Selectable, false); + SetStyle (Widgetstyles.SupportsTransparentBackColor, true); + + this.SuspendLayout (); + + this.items = new ToolStripItemCollection (this, items, true); + this.allow_merge = true; + base.AutoSize = true; + this.SetAutoSizeMode (AutoSizeMode.GrowAndShrink); + this.back_color = Widget.DefaultBackColor; + this.can_overflow = true; + base.CausesValidation = false; + this.default_drop_down_direction = ToolStripDropDownDirection.BelowRight; + this.displayed_items = new ToolStripItemCollection (this, null, true); + this.Dock = this.DefaultDock; + base.Font = new Font ("Tahoma", 8.25f); + this.fore_color = Widget.DefaultForeColor; + this.grip_margin = this.DefaultGripMargin; + this.grip_style = ToolStripGripStyle.Visible; + this.image_scaling_size = new Size (16, 16); + this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow; + this.orientation = Orientation.Horizontal; + if (!(this is ToolStripDropDown)) + this.overflow_button = new ToolStripOverflowButton (this); + this.renderer = null; + this.render_mode = ToolStripRenderMode.ManagerRenderMode; + this.show_item_tool_tips = this.DefaultShowItemToolTips; + base.TabStop = false; + this.text_direction = ToolStripTextDirection.Horizontal; + this.ResumeLayout (); + + // Register with the ToolStripManager + ToolStripManager.AddToolStrip (this); + } + #endregion + + #region Public Properties + [MonoTODO ("Stub, does nothing")] + public override bool AllowDrop { + get { return base.AllowDrop; } + set { base.AllowDrop = value; } + } + + [MonoTODO ("Stub, does nothing")] + [DefaultValue (false)] + public bool AllowItemReorder { + get { return this.allow_item_reorder; } + set { this.allow_item_reorder = value; } + } + + [DefaultValue (true)] + public bool AllowMerge { + get { return this.allow_merge; } + set { this.allow_merge = value; } + } + + public override AnchorStyles Anchor { + get { return base.Anchor; } + set { base.Anchor = value; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public override bool AutoScroll { + get { return base.AutoScroll; } + set { base.AutoScroll = value; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public new Size AutoScrollMargin { + get { return base.AutoScrollMargin; } + set { base.AutoScrollMargin = value; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public new Size AutoScrollMinSize { + get { return base.AutoScrollMinSize; } + set { base.AutoScrollMinSize = value; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public new Point AutoScrollPosition { + get { return base.AutoScrollPosition; } + set { base.AutoScrollPosition = value; } + } + + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)] + [Browsable (true)] + //[EditorBrowsable (EditorBrowsableState.Always)] + [DefaultValue (true)] + public override bool AutoSize { + get { return base.AutoSize; } + set { base.AutoSize = value; } + } + + new public Color BackColor { + get { return this.back_color; } + set { this.back_color = value; } + } + + public override BindingContext BindingContext { + get { return base.BindingContext; } + set { base.BindingContext = value; } + } + + [DefaultValue (true)] + public bool CanOverflow { + get { return this.can_overflow; } + set { this.can_overflow = value; } + } + + [Browsable (false)] + [DefaultValue (false)] + public new bool CausesValidation { + get { return base.CausesValidation; } + set { base.CausesValidation = value; } + } + + //[EditorBrowsable (EditorBrowsableState.Never)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public new WidgetCollection Widgets { + get { return base.Widgets; } + } + + [Browsable (false)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public override Cursor Cursor { + get { return base.Cursor; } + set { base.Cursor = value; } + } + + [Browsable (false)] + public virtual ToolStripDropDownDirection DefaultDropDownDirection { + get { return this.default_drop_down_direction; } + set { + if (!Enum.IsDefined (typeof (ToolStripDropDownDirection), value)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripDropDownDirection", value)); + + this.default_drop_down_direction = value; + } + } + + public override Rectangle DisplayRectangle { + get { + if (this.orientation == Orientation.Horizontal) + if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table) + return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical); + else + 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); + else + if (this.grip_style == ToolStripGripStyle.Hidden || this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table) + return new Rectangle (this.Padding.Left, this.Padding.Top, this.Width - this.Padding.Horizontal, this.Height - this.Padding.Vertical); + else + 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); + } + } + + [DefaultValue (DockStyle.Top)] + public override DockStyle Dock { + get { return base.Dock; } + set { + if (base.Dock != value) { + base.Dock = value; + + switch (value) { + case DockStyle.Top: + case DockStyle.Bottom: + case DockStyle.None: + this.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow; + break; + case DockStyle.Left: + case DockStyle.Right: + this.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow; + break; + } + } + } + } + + public override Font Font { + get { return base.Font; } + set { + if (base.Font != value) { + base.Font = value; + + foreach (ToolStripItem tsi in this.Items) + tsi.OnOwnerFontChanged (EventArgs.Empty); + } + } + } + + [Browsable (false)] + public new Color ForeColor { + get { return this.fore_color; } + set { + if (this.fore_color != value) { + this.fore_color = value; + this.OnForeColorChanged (EventArgs.Empty); + } + } + } + + [Browsable (false)] + public ToolStripGripDisplayStyle GripDisplayStyle { + get { return this.orientation == Orientation.Vertical ? ToolStripGripDisplayStyle.Horizontal : ToolStripGripDisplayStyle.Vertical; } + } + + public Padding GripMargin { + get { return this.grip_margin; } + set { + if (this.grip_margin != value) { + this.grip_margin = value; + this.PerformLayout (); + } + } + } + + [Browsable (false)] + public Rectangle GripRectangle { + get { + if (this.grip_style == ToolStripGripStyle.Hidden) + return Rectangle.Empty; + + if (this.orientation == Orientation.Horizontal) + return new Rectangle (this.grip_margin.Left + this.Padding.Left, this.Padding.Top, 3, this.Height); + else + return new Rectangle (this.Padding.Left, this.grip_margin.Top + this.Padding.Top, this.Width, 3); + } + } + + [DefaultValue (ToolStripGripStyle.Visible)] + public ToolStripGripStyle GripStyle { + get { return this.grip_style; } + set { + if (this.grip_style != value) { + if (!Enum.IsDefined (typeof (ToolStripGripStyle), value)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripGripStyle", value)); + this.grip_style = value; + this.PerformLayout (this, "GripStyle"); + } + } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public new bool HasChildren { + get { return base.HasChildren; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + public new HScrollProperties HorizontalScroll { + get { return base.HorizontalScroll; } + } + + [Browsable (false)] + [DefaultValue (null)] + public ImageList ImageList { + get { return this.image_list; } + set { this.image_list = value; } + } + + [DefaultValue ("{Width=16, Height=16}")] + public Size ImageScalingSize { + get { return this.image_scaling_size; } + set { this.image_scaling_size = value; } + } + + [MonoTODO ("Always returns false, dragging not implemented yet.")] + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Advanced)] + public bool IsCurrentlyDragging { + get { return false; } + } + + [Browsable (false)] + public bool IsDropDown { + get { + if (this is ToolStripDropDown) + return true; + + return false; + } + } + + [MergableProperty (false)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] + public virtual ToolStripItemCollection Items { + get { return this.items; } + } + + public override LayoutEngine LayoutEngine { + get { + if (layout_engine == null) + this.layout_engine = new ToolStripSplitStackLayout (); + + return this.layout_engine; + } + } + + [Browsable (false)] + [DefaultValue (null)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public LayoutSettings LayoutSettings { + get { return this.layout_settings; } + set { + if (this.layout_settings != value) { + this.layout_settings = value; + PerformLayout (this, "LayoutSettings"); + } + } + } + + [AmbientValue (ToolStripLayoutStyle.StackWithOverflow)] + public ToolStripLayoutStyle LayoutStyle { + get { return layout_style; } + set { + if (this.layout_style != value) { + if (!Enum.IsDefined (typeof (ToolStripLayoutStyle), value)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripLayoutStyle", value)); + + this.layout_style = value; + + if (this.layout_style == ToolStripLayoutStyle.Flow) + this.layout_engine = new FlowLayout (); + else + this.layout_engine = new ToolStripSplitStackLayout (); + + if (this.layout_style == ToolStripLayoutStyle.StackWithOverflow) { + if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right) + this.layout_style = ToolStripLayoutStyle.VerticalStackWithOverflow; + else + this.layout_style = ToolStripLayoutStyle.HorizontalStackWithOverflow; + } + + if (this.layout_style == ToolStripLayoutStyle.HorizontalStackWithOverflow) + this.orientation = Orientation.Horizontal; + else if (this.layout_style == ToolStripLayoutStyle.VerticalStackWithOverflow) + this.orientation = Orientation.Vertical; + + this.layout_settings = this.CreateLayoutSettings (value); + + this.PerformLayout (this, "LayoutStyle"); + this.OnLayoutStyleChanged (EventArgs.Empty); + } + } + } + + [Browsable (false)] + public Orientation Orientation { + get { return this.orientation; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Advanced)] + public ToolStripOverflowButton OverflowButton { + get { return this.overflow_button; } + } + + [Browsable (false)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public ToolStripRenderer Renderer { + get { + if (this.render_mode == ToolStripRenderMode.ManagerRenderMode) + return ToolStripManager.Renderer; + + return this.renderer; + } + set { + if (this.renderer != value) { + this.renderer = value; + this.render_mode = ToolStripRenderMode.Custom; + this.PerformLayout (this, "Renderer"); + this.OnRendererChanged (EventArgs.Empty); + } + } + } + + public ToolStripRenderMode RenderMode { + get { return this.render_mode; } + set { + if (!Enum.IsDefined (typeof (ToolStripRenderMode), value)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value)); + + if (value == ToolStripRenderMode.Custom && this.renderer == null) + throw new NotSupportedException ("Must set Renderer property before setting RenderMode to Custom"); + else if (value == ToolStripRenderMode.Professional) + this.Renderer = new ToolStripProfessionalRenderer (); + else if (value == ToolStripRenderMode.System) + this.Renderer = new ToolStripSystemRenderer (); + + this.render_mode = value; + } + } + + [DefaultValue (true)] + public bool ShowItemToolTips { + get { return this.show_item_tool_tips; } + set { this.show_item_tool_tips = value; } + } + + [DefaultValue (false)] + public bool Stretch { + get { return this.stretch; } + set { this.stretch = value; } + } + + [DefaultValue (false)] + [DispId(-516)] + public new bool TabStop { + get { return base.TabStop; } + set { + base.TabStop = value; + SetStyle (Widgetstyles.Selectable, value); + } + } + + [DefaultValue (ToolStripTextDirection.Horizontal)] + public virtual ToolStripTextDirection TextDirection { + get { return this.text_direction; } + set { + if (!Enum.IsDefined (typeof (ToolStripTextDirection), value)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripTextDirection", value)); + + if (this.text_direction != value) { + this.text_direction = value; + + this.PerformLayout (this, "TextDirection"); + + this.Invalidate (); + } + } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + public new VScrollProperties VerticalScroll { + get { return base.VerticalScroll; } + } + #endregion + + #region Protected Properties + protected virtual DockStyle DefaultDock { get { return DockStyle.Top; } } + protected virtual Padding DefaultGripMargin { get { return new Padding (2); } } + protected override Padding DefaultMargin { get { return Padding.Empty; } } + protected override Padding DefaultPadding { get { return new Padding (0, 0, 1, 0); } } + protected virtual bool DefaultShowItemToolTips { get { return true; } } + protected override Size DefaultSize { get { return new Size (100, 25); } } + protected internal virtual ToolStripItemCollection DisplayedItems { get { return this.displayed_items; } } + protected internal virtual Size MaxItemSize { + get { return new Size (Width - (GripStyle == ToolStripGripStyle.Hidden ? 1 : 8), Height); } + } + #endregion + + #region Public Methods + //[EditorBrowsable (EditorBrowsableState.Never)] + public new Widget GetChildAtPoint (Point point) + { + return base.GetChildAtPoint (point); + } + + //[EditorBrowsable (EditorBrowsableState.Never)] + public new Widget GetChildAtPoint (Point pt, GetChildAtPointSkip skipValue) + { + return base.GetChildAtPoint (pt, skipValue); + } + + public ToolStripItem GetItemAt (Point point) + { + foreach (ToolStripItem tsi in this.displayed_items) + if (tsi.Visible && tsi.Bounds.Contains (point)) + return tsi; + + return null; + } + + public ToolStripItem GetItemAt (int x, int y) + { + return GetItemAt (new Point (x, y)); + } + + public virtual ToolStripItem GetNextItem (ToolStripItem start, ArrowDirection direction) + { + if (!Enum.IsDefined (typeof (ArrowDirection), direction)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ArrowDirection", direction)); + + ToolStripItem current_best = null; + int current_best_point; + + switch (direction) { + case ArrowDirection.Right: + current_best_point = int.MaxValue; + + if (start != null) + foreach (ToolStripItem loop_tsi in this.DisplayedItems) + if (loop_tsi.Left >= start.Right && loop_tsi.Left < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) { + current_best = loop_tsi; + current_best_point = loop_tsi.Left; + } + + if (current_best == null) + foreach (ToolStripItem loop_tsi in this.DisplayedItems) + if (loop_tsi.Left < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) { + current_best = loop_tsi; + current_best_point = loop_tsi.Left; + } + + break; + case ArrowDirection.Up: + current_best_point = int.MinValue; + + if (start != null) + foreach (ToolStripItem loop_tsi in this.DisplayedItems) + if (loop_tsi.Bottom <= start.Top && loop_tsi.Top > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) { + current_best = loop_tsi; + current_best_point = loop_tsi.Top; + } + + if (current_best == null) + foreach (ToolStripItem loop_tsi in this.DisplayedItems) + if (loop_tsi.Top > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) { + current_best = loop_tsi; + current_best_point = loop_tsi.Top; + } + + break; + case ArrowDirection.Left: + current_best_point = int.MinValue; + + if (start != null) + foreach (ToolStripItem loop_tsi in this.DisplayedItems) + if (loop_tsi.Right <= start.Left && loop_tsi.Left > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) { + current_best = loop_tsi; + current_best_point = loop_tsi.Left; + } + + if (current_best == null) + foreach (ToolStripItem loop_tsi in this.DisplayedItems) + if (loop_tsi.Left > current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) { + current_best = loop_tsi; + current_best_point = loop_tsi.Left; + } + + break; + case ArrowDirection.Down: + current_best_point = int.MaxValue; + + if (start != null) + foreach (ToolStripItem loop_tsi in this.DisplayedItems) + if (loop_tsi.Top >= start.Bottom && loop_tsi.Bottom < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) { + current_best = loop_tsi; + current_best_point = loop_tsi.Top; + } + + if (current_best == null) + foreach (ToolStripItem loop_tsi in this.DisplayedItems) + if (loop_tsi.Top < current_best_point && loop_tsi.Visible && loop_tsi.CanSelect) { + current_best = loop_tsi; + current_best_point = loop_tsi.Top; + } + + break; + } + + return current_best; + } + + //[EditorBrowsable (EditorBrowsableState.Never)] + public void ResetMinimumSize () + { + this.MinimumSize = new Size (-1, -1); + } + + //[EditorBrowsable (EditorBrowsableState.Never)] + public new void SetAutoScrollMargin (int x, int y) + { + base.SetAutoScrollMargin (x, y); + } + + public override string ToString () + { + return String.Format ("{0}, Name: {1}, Items: {2}", base.ToString(), this.Name, this.items.Count.ToString ()); + } + #endregion + + #region Protected Methods + protected override AccessibleObject CreateAccessibilityInstance () + { + return new ToolStripAccessibleObject (this); + } + + protected override WidgetCollection CreateWidgetsInstance () + { + return base.CreateWidgetsInstance (); + } + + protected internal virtual ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick) + { + if (text == "-") + return new ToolStripSeparator (); + + if (this is ToolStripDropDown) + return new ToolStripMenuItem (text, image, onClick); + + return new ToolStripButton (text, image, onClick); + } + + protected virtual LayoutSettings CreateLayoutSettings (ToolStripLayoutStyle layoutStyle) + { + switch (layoutStyle) { + case ToolStripLayoutStyle.Flow: + return new FlowLayoutSettings (this); + case ToolStripLayoutStyle.Table: + //return new TableLayoutSettings (); + case ToolStripLayoutStyle.StackWithOverflow: + case ToolStripLayoutStyle.HorizontalStackWithOverflow: + case ToolStripLayoutStyle.VerticalStackWithOverflow: + default: + return null; + } + } + + protected override void Dispose (bool disposing) + { + if (!IsDisposed) { + + if(disposing) { + // Event Handler must be stopped before disposing Items. + Events.Dispose(); + + CloseToolTip (null); + // ToolStripItem.Dispose modifes the collection, + // so we iterate it in reverse order + for (int i = Items.Count - 1; i >= 0; i--) + Items [i].Dispose (); + + if (this.overflow_button != null && this.overflow_button.drop_down != null) + this.overflow_button.drop_down.Dispose (); + + ToolStripManager.RemoveToolStrip (this); + } + base.Dispose (disposing); + } + } + + [MonoTODO ("Stub, never called")] + protected virtual void OnBeginDrag (EventArgs e) + { + EventHandler eh = (EventHandler)(Events[BeginDragEvent]); + if (eh != null) + eh (this, e); + } + + protected override void OnDockChanged (EventArgs e) + { + base.OnDockChanged (e); + } + + [MonoTODO ("Stub, never called")] + protected virtual void OnEndDrag (EventArgs e) + { + EventHandler eh = (EventHandler)(Events[EndDragEvent]); + if (eh != null) + eh (this, e); + } + + protected override bool IsInputChar (char charCode) + { + return base.IsInputChar (charCode); + } + + protected override bool IsInputKey (Keys keyData) + { + return base.IsInputKey (keyData); + } + + protected override void OnEnabledChanged (EventArgs e) + { + base.OnEnabledChanged (e); + + foreach (ToolStripItem tsi in this.Items) + tsi.OnParentEnabledChanged (EventArgs.Empty); + } + + protected override void OnFontChanged (EventArgs e) + { + base.OnFontChanged (e); + } + + protected override void OnHandleCreated (EventArgs e) + { + base.OnHandleCreated (e); + } + + protected override void OnHandleDestroyed (EventArgs e) + { + base.OnHandleDestroyed (e); + } + + protected override void OnInvalidated (InvalidateEventArgs e) + { + base.OnInvalidated (e); + } + + protected internal virtual void OnItemAdded (ToolStripItemEventArgs e) + { + if (e.Item.InternalVisible) + e.Item.Available = true; + + e.Item.SetPlacement (ToolStripItemPlacement.Main); + + if (this.Created) + this.PerformLayout (); + + ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemAddedEvent]); + if (eh != null) + eh (this, e); + } + + protected virtual void OnItemClicked (ToolStripItemClickedEventArgs e) + { + if (this.KeyboardActive) + ToolStripManager.SetActiveToolStrip (null, false); + + ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [ItemClickedEvent]); + if (eh != null) + eh (this, e); + } + + protected internal virtual void OnItemRemoved (ToolStripItemEventArgs e) + { + ToolStripItemEventHandler eh = (ToolStripItemEventHandler)(Events [ItemRemovedEvent]); + if (eh != null) + eh (this, e); + } + + protected override void OnLayout (LayoutEventArgs e) + { + base.OnLayout (e); + + this.SetDisplayedItems (); + this.OnLayoutCompleted (EventArgs.Empty); + this.Invalidate (); + } + + protected virtual void OnLayoutCompleted (EventArgs e) + { + EventHandler eh = (EventHandler)(Events [LayoutCompletedEvent]); + if (eh != null) + eh (this, e); + } + + protected virtual void OnLayoutStyleChanged (EventArgs e) + { + EventHandler eh = (EventHandler)(Events[LayoutStyleChangedEvent]); + if (eh != null) + eh (this, e); + } + + protected override void OnLeave (EventArgs e) + { + base.OnLeave (e); + } + + protected override void OnLostFocus (EventArgs e) + { + base.OnLostFocus (e); + } + + protected override void OnMouseCaptureChanged (EventArgs e) + { + base.OnMouseCaptureChanged (e); + } + + protected override void OnMouseDown (MouseEventArgs mea) + { + if (mouse_currently_over != null) + { + ToolStripItem focused = GetCurrentlyFocusedItem (); + + if (focused != null && focused != mouse_currently_over) + this.FocusInternal (true); + + if (this is MenuStrip && !menu_selected) { + (this as MenuStrip).FireMenuActivate (); + menu_selected = true; + } + + mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseDown); + + if (this is MenuStrip && mouse_currently_over is ToolStripMenuItem && !(mouse_currently_over as ToolStripMenuItem).HasDropDownItems) + return; + } else { + this.Dismiss (ToolStripDropDownCloseReason.AppClicked); + } + + if (this is MenuStrip) + this.Capture = false; + + base.OnMouseDown (mea); + } + + protected override void OnMouseLeave (EventArgs e) + { + if (mouse_currently_over != null) { + MouseLeftItem (mouse_currently_over); + mouse_currently_over.FireEvent (e, ToolStripItemEventType.MouseLeave); + mouse_currently_over = null; + } + + base.OnMouseLeave (e); + } + + protected override void OnMouseMove (MouseEventArgs mea) + { + ToolStripItem tsi; + // Find the item we are now + if (this.overflow_button != null && this.overflow_button.Visible && this.overflow_button.Bounds.Contains (mea.Location)) + tsi = this.overflow_button; + else + tsi = this.GetItemAt (mea.X, mea.Y); + + if (tsi != null) { + // If we were already hovering on this item, just send a mouse move + if (tsi == mouse_currently_over) + tsi.FireEvent (mea, ToolStripItemEventType.MouseMove); + else { + // If we were over a different item, fire a mouse leave on it + if (mouse_currently_over != null) { + MouseLeftItem (tsi); + mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave); + } + + // Set the new item we are currently over + mouse_currently_over = tsi; + + // Fire mouse enter and mouse move + tsi.FireEvent (mea, ToolStripItemEventType.MouseEnter); + MouseEnteredItem (tsi); + tsi.FireEvent (mea, ToolStripItemEventType.MouseMove); + + // If we're over something with a drop down, show it + if (menu_selected && mouse_currently_over.Enabled && mouse_currently_over is ToolStripDropDownItem && (mouse_currently_over as ToolStripDropDownItem).HasDropDownItems) + (mouse_currently_over as ToolStripDropDownItem).ShowDropDown (); + } + } else { + // We're not over anything now, just fire the mouse leave on what we used to be over + if (mouse_currently_over != null) { + MouseLeftItem (tsi); + mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseLeave); + mouse_currently_over = null; + } + } + + base.OnMouseMove (mea); + } + + protected override void OnMouseUp (MouseEventArgs mea) + { + // If we're currently over an item (set in MouseMove) + if (mouse_currently_over != null && !(mouse_currently_over is ToolStripWidgetHost) && mouse_currently_over.Enabled) { + // Fire our ItemClicked event, but only for a left mouse click. + if (mea.Button == MouseButtons.Left) + OnItemClicked (new ToolStripItemClickedEventArgs (mouse_currently_over)); + + // Fire the item's MouseUp event + if (mouse_currently_over != null) + mouse_currently_over.FireEvent (mea, ToolStripItemEventType.MouseUp); + + // The event handler may have blocked until the mouse moved off of the ToolStripItem + if (mouse_currently_over == null) + return; + } + + base.OnMouseUp (mea); + } + + protected override void OnPaint (PaintEventArgs e) + { + base.OnPaint (e); + + // Draw the grip + this.OnPaintGrip (e); + + // Make each item draw itself + for (int i = 0; i < displayed_items.Count; i++) { + ToolStripItem tsi = displayed_items[i]; + + if (tsi.Visible) { + e.Graphics.TranslateTransform (tsi.Bounds.Left, tsi.Bounds.Top); + tsi.FireEvent (e, ToolStripItemEventType.Paint); + e.Graphics.ResetTransform (); + } + } + + // Paint the Overflow button if it's visible + if (this.overflow_button != null && this.overflow_button.Visible) { + e.Graphics.TranslateTransform (this.overflow_button.Bounds.Left, this.overflow_button.Bounds.Top); + this.overflow_button.FireEvent (e, ToolStripItemEventType.Paint); + e.Graphics.ResetTransform (); + } + + Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size); + + ToolStripRenderEventArgs pevent = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, Color.Empty); + pevent.InternalConnectedArea = CalculateConnectedArea (); + + this.Renderer.DrawToolStripBorder (pevent); + } + + //[EditorBrowsable (EditorBrowsableState.Advanced)] + protected override void OnPaintBackground (PaintEventArgs e) + { + base.OnPaintBackground (e); + + Rectangle affected_bounds = new Rectangle (Point.Empty, this.Size); + ToolStripRenderEventArgs tsrea = new ToolStripRenderEventArgs (e.Graphics, this, affected_bounds, SystemColors.Control); + + this.Renderer.DrawToolStripBackground (tsrea); + } + + protected internal virtual void OnPaintGrip (PaintEventArgs e) + { + // Never draw a grip with these two layouts + if (this.layout_style == ToolStripLayoutStyle.Flow || this.layout_style == ToolStripLayoutStyle.Table) + return; + + PaintEventHandler eh = (PaintEventHandler)(Events [PaintGripEvent]); + if (eh != null) + eh (this, e); + + if (!(this is MenuStrip)) { + if (this.orientation == Orientation.Horizontal) + e.Graphics.TranslateTransform (2, 0); + else + e.Graphics.TranslateTransform (0, 2); + } + + this.Renderer.DrawGrip (new ToolStripGripRenderEventArgs (e.Graphics, this, this.GripRectangle, this.GripDisplayStyle, this.grip_style)); + e.Graphics.ResetTransform (); + } + + protected virtual void OnRendererChanged (EventArgs e) + { + EventHandler eh = (EventHandler)(Events [RendererChangedEvent]); + if (eh != null) + eh (this, e); + } + + //[EditorBrowsable (EditorBrowsableState.Advanced)] + protected override void OnRightToLeftChanged (EventArgs e) + { + base.OnRightToLeftChanged (e); + + foreach (ToolStripItem tsi in this.Items) + tsi.OnParentRightToLeftChanged (e); + } + + protected override void OnScroll (ScrollEventArgs se) + { + base.OnScroll (se); + } + + protected override void OnTabStopChanged (EventArgs e) + { + base.OnTabStopChanged (e); + } + + protected override void OnVisibleChanged (EventArgs e) + { + if (!Visible) + CloseToolTip (null); + + base.OnVisibleChanged (e); + } + + protected override bool ProcessCmdKey (ref Message m, Keys keyData) + { + return base.ProcessCmdKey (ref m, keyData); + } + + protected override bool ProcessDialogKey (Keys keyData) + { + if (!this.KeyboardActive) + return false; + + // Give each item a chance to handle the key + foreach (ToolStripItem tsi in this.Items) + if (tsi.ProcessDialogKey (keyData)) + return true; + + // See if I want to handle it + if (this.ProcessArrowKey (keyData)) + return true; + + ToolStrip ts = null; + + switch (keyData) { + case Keys.Escape: + this.Dismiss (ToolStripDropDownCloseReason.Keyboard); + return true; + + case Keys.Widget | Keys.Tab: + ts = ToolStripManager.GetNextToolStrip (this, true); + + if (ts != null) { + foreach (ToolStripItem tsi in this.Items) + tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard); + + ToolStripManager.SetActiveToolStrip (ts, true); + ts.SelectNextToolStripItem (null, true); + } + + return true; + case Keys.Widget | Keys.Shift | Keys.Tab: + ts = ToolStripManager.GetNextToolStrip (this, false); + + if (ts != null) { + foreach (ToolStripItem tsi in this.Items) + tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard); + + ToolStripManager.SetActiveToolStrip (ts, true); + ts.SelectNextToolStripItem (null, true); + } + + return true; + case Keys.Down: + case Keys.Up: + case Keys.Left: + case Keys.Right: + if (GetCurrentlySelectedItem () is ToolStripWidgetHost) + return false; + break; + } + + return base.ProcessDialogKey (keyData); + } + + protected override bool ProcessMnemonic (char charCode) + { + // If any item has an explicit mnemonic, it gets the message + foreach (ToolStripItem tsi in this.Items) + if (tsi.Enabled && tsi.Visible && !string.IsNullOrEmpty (tsi.Text) && Widget.IsMnemonic (charCode, tsi.Text)) + return tsi.ProcessMnemonic (charCode); + + // Do not try to match any further here. See Xamarin bug 23532. + + return base.ProcessMnemonic (charCode); + } + + [MonoTODO ("Stub, does nothing")] + //[EditorBrowsable (EditorBrowsableState.Advanced)] + protected virtual void RestoreFocus () + { + } + + protected override void Select (bool directed, bool forward) + { + foreach (ToolStripItem tsi in this.DisplayedItems) + if (tsi.CanSelect) { + tsi.Select (); + break; + } + } + + protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified) + { + base.SetBoundsCore (x, y, width, height, specified); + } + + protected virtual void SetDisplayedItems () + { + this.displayed_items.ClearInternal (); + + foreach (ToolStripItem tsi in this.items) + if (tsi.Placement == ToolStripItemPlacement.Main && tsi.Available) { + this.displayed_items.AddNoOwnerOrLayout (tsi); + tsi.Parent = this; + } + else if (tsi.Placement == ToolStripItemPlacement.Overflow) + tsi.Parent = this.OverflowButton.DropDown; + + if (this.OverflowButton != null) + this.OverflowButton.DropDown.SetDisplayedItems (); + } + + protected internal void SetItemLocation (ToolStripItem item, Point location) + { + if (item == null) + throw new ArgumentNullException ("item"); + + if (item.Owner != this) + throw new NotSupportedException ("The item is not owned by this ToolStrip"); + + item.SetBounds (new Rectangle (location, item.Size)); + } + + protected internal static void SetItemParent (ToolStripItem item, ToolStrip parent) + { + if (item.Owner != null) { + item.Owner.Items.RemoveNoOwnerOrLayout (item); + + if (item.Owner is ToolStripOverflow) + (item.Owner as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item); + } + + parent.Items.AddNoOwnerOrLayout (item); + item.Parent = parent; + } + + protected override void SetVisibleCore (bool visible) + { + base.SetVisibleCore (visible); + } + + protected override void WndProc (ref Message m) + { + base.WndProc (ref m); + } + #endregion + + #region Public Events + static object BeginDragEvent = new object (); + static object EndDragEvent = new object (); + static object ItemAddedEvent = new object (); + static object ItemClickedEvent = new object (); + static object ItemRemovedEvent = new object (); + static object LayoutCompletedEvent = new object (); + static object LayoutStyleChangedEvent = new object (); + static object PaintGripEvent = new object (); + static object RendererChangedEvent = new object (); + + [Browsable (true)] + //[EditorBrowsable (EditorBrowsableState.Always)] + public new event EventHandler AutoSizeChanged { + add { base.AutoSizeChanged += value; } + remove { base.AutoSizeChanged -= value; } + } + + [MonoTODO ("Event never raised")] + public event EventHandler BeginDrag { + add { Events.AddHandler (BeginDragEvent, value); } + remove { Events.RemoveHandler (BeginDragEvent, value); } + } + + [Browsable (false)] + public new event EventHandler CausesValidationChanged { + add { base.CausesValidationChanged += value; } + remove { base.CausesValidationChanged -= value; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + public new event WidgetEventHandler WidgetAdded { + add { base.WidgetAdded += value; } + remove { base.WidgetAdded -= value; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + public new event WidgetEventHandler WidgetRemoved { + add { base.WidgetRemoved += value; } + remove { base.WidgetRemoved -= value; } + } + + [Browsable (false)] + public new event EventHandler CursorChanged { + add { base.CursorChanged += value; } + remove { base.CursorChanged -= value; } + } + + [MonoTODO ("Event never raised")] + public event EventHandler EndDrag { + add { Events.AddHandler (EndDragEvent, value); } + remove { Events.RemoveHandler (EndDragEvent, value); } + } + + [Browsable (false)] + public new event EventHandler ForeColorChanged { + add { base.ForeColorChanged += value; } + remove { base.ForeColorChanged -= value; } + } + + public event ToolStripItemEventHandler ItemAdded { + add { Events.AddHandler (ItemAddedEvent, value); } + remove { Events.RemoveHandler (ItemAddedEvent, value); } + } + + public event ToolStripItemClickedEventHandler ItemClicked { + add { Events.AddHandler (ItemClickedEvent, value); } + remove { Events.RemoveHandler (ItemClickedEvent, value); } + } + + public event ToolStripItemEventHandler ItemRemoved { + add { Events.AddHandler (ItemRemovedEvent, value); } + remove { Events.RemoveHandler (ItemRemovedEvent, value); } + } + + public event EventHandler LayoutCompleted { + add { Events.AddHandler (LayoutCompletedEvent, value); } + remove { Events.RemoveHandler (LayoutCompletedEvent, value); } + } + + public event EventHandler LayoutStyleChanged { + add { Events.AddHandler (LayoutStyleChangedEvent, value); } + remove { Events.RemoveHandler (LayoutStyleChangedEvent, value); } + } + + public event PaintEventHandler PaintGrip { + add { Events.AddHandler (PaintGripEvent, value); } + remove { Events.RemoveHandler (PaintGripEvent, value); } + } + + public event EventHandler RendererChanged { + add { Events.AddHandler (RendererChangedEvent, value); } + remove { Events.RemoveHandler (RendererChangedEvent, value); } + } + #endregion + + #region Internal Properties + internal virtual bool KeyboardActive + { + get { return this.keyboard_active; } + set { + if (this.keyboard_active != value) { + this.keyboard_active = value; + + if (value) + Application.KeyboardCapture = this; + else if (Application.KeyboardCapture == this) { + Application.KeyboardCapture = null; + ToolStripManager.ActivatedByKeyboard = false; + } + + // Redraw for mnemonic underlines + this.Invalidate (); + } + } + } + #endregion + + #region Private Methods + internal virtual Rectangle CalculateConnectedArea () + { + return Rectangle.Empty; + } + + internal void ChangeSelection (ToolStripItem nextItem) + { + if (Application.KeyboardCapture != this) + ToolStripManager.SetActiveToolStrip (this, ToolStripManager.ActivatedByKeyboard); + + foreach (ToolStripItem tsi in this.Items) + if (tsi != nextItem) + tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard); + + ToolStripItem current = GetCurrentlySelectedItem (); + + if (current != null && !(current is ToolStripWidgetHost)) + this.FocusInternal (true); + + if (nextItem is ToolStripWidgetHost) + (nextItem as ToolStripWidgetHost).Focus (); + + nextItem.Select (); + + if (nextItem.Parent is MenuStrip && (nextItem.Parent as MenuStrip).MenuDroppedDown) + (nextItem as ToolStripMenuItem).HandleAutoExpansion (); + } + + internal virtual void Dismiss () + { + this.Dismiss (ToolStripDropDownCloseReason.AppClicked); + } + + internal virtual void Dismiss (ToolStripDropDownCloseReason reason) + { + // Release our stranglehold on the keyboard + this.KeyboardActive = false; + + // Set our drop down flag to false; + this.menu_selected = false; + + // Make sure all of our items are deselected and repainted + foreach (ToolStripItem tsi in this.Items) + tsi.Dismiss (reason); + + // We probably need to redraw for mnemonic underlines + this.Invalidate (); + } + + internal ToolStripItem GetCurrentlySelectedItem () + { + foreach (ToolStripItem tsi in this.DisplayedItems) + if (tsi.Selected) + return tsi; + + return null; + } + + internal ToolStripItem GetCurrentlyFocusedItem () + { + foreach (ToolStripItem tsi in this.DisplayedItems) + if ((tsi is ToolStripWidgetHost) && (tsi as ToolStripWidgetHost).Widget.Focused) + return tsi; + + return null; + } + + internal override Size GetPreferredSizeCore (Size proposedSize) + { + return GetToolStripPreferredSize (proposedSize); + } + + internal virtual Size GetToolStripPreferredSize (Size proposedSize) + { + Size new_size = Size.Empty; + + // TODO: This is total duct tape. We really have to call into the correct + // layout engine, do a dry run of the layout, and find out our true + // preferred dimensions. + if (this.LayoutStyle == ToolStripLayoutStyle.Flow) { + Point currentLocation = Point.Empty; + int tallest = 0; + + foreach (ToolStripItem tsi in items) + if (tsi.Available) { + Size tsi_preferred = tsi.GetPreferredSize (Size.Empty); + + if ((DisplayRectangle.Width - currentLocation.X) < (tsi_preferred.Width + tsi.Margin.Horizontal)) { + + currentLocation.Y += tallest; + tallest = 0; + + currentLocation.X = DisplayRectangle.Left; + } + + // Offset the left margin and set the Widget to our point + currentLocation.Offset (tsi.Margin.Left, 0); + tallest = Math.Max (tallest, tsi_preferred.Height + tsi.Margin.Vertical); + + // Update our location pointer + currentLocation.X += tsi_preferred.Width + tsi.Margin.Right; + } + + currentLocation.Y += tallest; + return new Size (currentLocation.X + this.Padding.Horizontal, currentLocation.Y + this.Padding.Vertical); + } + + if (this.orientation == Orientation.Vertical) { + foreach (ToolStripItem tsi in this.items) + if (tsi.Available) { + Size tsi_preferred = tsi.GetPreferredSize (Size.Empty); + new_size.Height += tsi_preferred.Height + tsi.Margin.Top + tsi.Margin.Bottom; + + if (new_size.Width < (this.Padding.Horizontal + tsi_preferred.Width + tsi.Margin.Horizontal)) + new_size.Width = (this.Padding.Horizontal + tsi_preferred.Width + tsi.Margin.Horizontal); + } + + new_size.Height += (this.GripRectangle.Height + this.GripMargin.Vertical + this.Padding.Vertical + 4); + + if (new_size.Width == 0) + new_size.Width = ExplicitBounds.Width; + + return new_size; + } else { + foreach (ToolStripItem tsi in this.items) + if (tsi.Available) { + Size tsi_preferred = tsi.GetPreferredSize (Size.Empty); + new_size.Width += tsi_preferred.Width + tsi.Margin.Left + tsi.Margin.Right; + + if (new_size.Height < (this.Padding.Vertical + tsi_preferred.Height + tsi.Margin.Vertical)) + new_size.Height = (this.Padding.Vertical + tsi_preferred.Height + tsi.Margin.Vertical); + } + + new_size.Width += (this.GripRectangle.Width + this.GripMargin.Horizontal + this.Padding.Horizontal + 4); + + if (new_size.Height == 0) + new_size.Height = ExplicitBounds.Height; + + if (this is StatusStrip) + new_size.Height = Math.Max (new_size.Height, 22); + + return new_size; + } + } + + internal virtual ToolStrip GetTopLevelToolStrip () + { + return this; + } + + internal virtual void HandleItemClick (ToolStripItem dismissingItem) + { + this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.ItemClicked); + } + + internal void NotifySelectedChanged (ToolStripItem tsi) + { + foreach (ToolStripItem tsi2 in this.DisplayedItems) + if (tsi != tsi2) + if (tsi2 is ToolStripDropDownItem) + (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard); + + if (this.OverflowButton != null) { + ToolStripItemCollection tsic = this.OverflowButton.DropDown.DisplayedItems; + + foreach (ToolStripItem tsi2 in tsic) + if (tsi != tsi2) + if (tsi2 is ToolStripDropDownItem) + (tsi2 as ToolStripDropDownItem).HideDropDown (ToolStripDropDownCloseReason.Keyboard); + + this.OverflowButton.HideDropDown (); + } + + foreach (ToolStripItem tsi2 in this.Items) + if (tsi != tsi2) + tsi2.Dismiss (ToolStripDropDownCloseReason.Keyboard); + } + + internal virtual bool OnMenuKey () + { + return false; + } + + internal virtual bool ProcessArrowKey (Keys keyData) + { + ToolStripItem tsi; + + switch (keyData) { + case Keys.Right: + tsi = this.GetCurrentlySelectedItem (); + + if (tsi is ToolStripWidgetHost) + return false; + + tsi = this.SelectNextToolStripItem (tsi, true); + + if (tsi is ToolStripWidgetHost) + (tsi as ToolStripWidgetHost).Focus (); + + return true; + case Keys.Tab: + tsi = this.GetCurrentlySelectedItem (); + + tsi = this.SelectNextToolStripItem (tsi, true); + + if (tsi is ToolStripWidgetHost) + (tsi as ToolStripWidgetHost).Focus (); + + return true; + case Keys.Left: + tsi = this.GetCurrentlySelectedItem (); + + if (tsi is ToolStripWidgetHost) + return false; + + tsi = this.SelectNextToolStripItem (tsi, false); + + if (tsi is ToolStripWidgetHost) + (tsi as ToolStripWidgetHost).Focus (); + + return true; + case Keys.Shift | Keys.Tab: + tsi = this.GetCurrentlySelectedItem (); + + tsi = this.SelectNextToolStripItem (tsi, false); + + if (tsi is ToolStripWidgetHost) + (tsi as ToolStripWidgetHost).Focus (); + + return true; + } + + return false; + } + + internal virtual ToolStripItem SelectNextToolStripItem (ToolStripItem start, bool forward) + { + ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Right : ArrowDirection.Left); + + if (next_item == null) + return next_item; + + this.ChangeSelection (next_item); + + if (next_item is ToolStripWidgetHost) + (next_item as ToolStripWidgetHost).Focus (); + + return next_item; + } + + #region Stuff for ToolTips + private void MouseEnteredItem (ToolStripItem item) + { + if (this.show_item_tool_tips && !(item is ToolStripTextBox)) { + ToolTipTimer.Interval = InitialToolTipDelay; + tooltip_state = ToolTip.TipState.Initial; + tooltip_currently_showing = item; + ToolTipTimer.Start (); + } + } + + private void CloseToolTip (ToolStripItem item) + { + ToolTipTimer.Stop (); + ToolTipWindow.Hide (this); + tooltip_currently_showing = null; + tooltip_state = ToolTip.TipState.Down; + } + + private void MouseLeftItem (ToolStripItem item) + { + CloseToolTip (item); + } + + private Timer ToolTipTimer { + get { + if (tooltip_timer == null) { + tooltip_timer = new Timer (); + tooltip_timer.Enabled = false; + tooltip_timer.Interval = InitialToolTipDelay; + tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick); + } + + return tooltip_timer; + } + } + + private ToolTip ToolTipWindow { + get { + if (tooltip_window == null) + tooltip_window = new ToolTip (); + + return tooltip_window; + } + } + + private void ShowToolTip () + { + string tooltip = tooltip_currently_showing.GetToolTip (); + + if (!string.IsNullOrEmpty (tooltip)) { + ToolTipWindow.Present (this, tooltip); + ToolTipTimer.Interval = ToolTipDelay; + ToolTipTimer.Start (); + tooltip_state = ToolTip.TipState.Show; + } + + tooltip_currently_showing.FireEvent (EventArgs.Empty, ToolStripItemEventType.MouseHover); + } + + private void ToolTipTimer_Tick (object o, EventArgs args) + { + ToolTipTimer.Stop (); + + switch (tooltip_state) { + case ToolTip.TipState.Initial: + ShowToolTip (); + break; + case ToolTip.TipState.Show: + CloseToolTip (null); + break; + } + } + #endregion + + #region Stuff for Merging + internal ToolStrip CurrentlyMergedWith { + get { return this.currently_merged_with; } + set { this.currently_merged_with = value; } + } + + internal List<ToolStripItem> HiddenMergedItems { + get { + if (this.hidden_merged_items == null) + this.hidden_merged_items = new List<ToolStripItem> (); + + return this.hidden_merged_items; + } + } + + internal bool IsCurrentlyMerged { + get { return this.is_currently_merged; } + set { + this.is_currently_merged = value; + + if (!value && this is MenuStrip) + foreach (ToolStripMenuItem tsmi in this.Items) + tsmi.DropDown.IsCurrentlyMerged = value; + } + } + + internal void BeginMerge () + { + if (!IsCurrentlyMerged) { + IsCurrentlyMerged = true; + + if (this.pre_merge_items == null) { + this.pre_merge_items = new List<ToolStripItem> (); + + foreach (ToolStripItem tsi in this.Items) + this.pre_merge_items.Add (tsi); + } + } + } + + internal void RevertMergeItem (ToolStripItem item) + { + int index = 0; + + // Remove it from it's current Parent + if (item.Parent != null && item.Parent != this) { + if (item.Parent is ToolStripOverflow) + (item.Parent as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (item); + else + item.Parent.Items.RemoveNoOwnerOrLayout (item); + + item.Parent = item.Owner; + } + + // Find where the item was before the merge + index = item.Owner.pre_merge_items.IndexOf (item); + + // Find the first pre-merge item that was after this item, that + // is currently in the Items collection. Insert our item before + // that one. + for (int i = index; i < this.pre_merge_items.Count; i++) { + if (this.Items.Contains (this.pre_merge_items[i])) { + item.Owner.Items.InsertNoOwnerOrLayout (this.Items.IndexOf (this.pre_merge_items[i]), item); + return; + } + } + + // There aren't any items that are supposed to be after this item, + // so just append it to the end. + item.Owner.Items.AddNoOwnerOrLayout (item); + } + #endregion + #endregion + + #region ToolStripAccessibleObject + [ComVisible (true)] + public class ToolStripAccessibleObject : WidgetAccessibleObject + { + #region Public Constructor + public ToolStripAccessibleObject (ToolStrip owner) : base (owner) + { + } + #endregion + + #region Public Properties + public override AccessibleRole Role { + get { return AccessibleRole.ToolBar; } + } + #endregion + + #region Public Methods + public override AccessibleObject GetChild (int index) + { + return base.GetChild (index); + } + + public override int GetChildCount () + { + return (owner as ToolStrip).Items.Count; + } + + public override AccessibleObject HitTest (int x, int y) + { + return base.HitTest (x, y); + } + #endregion + } + #endregion + } +} |
