ToolStrip.cs :  » 2.6.4-mono-.net-core » System.Windows.Forms » System » Windows » Forms » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Windows.Forms 
System.Windows.Forms » System » Windows » Forms » ToolStrip.cs
//
// 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 (monkey@jpobst.com)
//

#if NET_2_0
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms.Layout;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;

namespace System.Windows.Forms{
  [ComVisible (true)]
  [ClassInterface (ClassInterfaceType.AutoDispatch)]
  [DefaultEvent ("ItemClicked")]
  [DefaultProperty ("Items")]
  [Designer ("System.Windows.Forms.Design.ToolStripDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
  [DesignerSerializer ("System.Windows.Forms.Design.ToolStripCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
  public class ToolStrip : ScrollableControl, 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 (ControlStyles.AllPaintingInWmPaint, true);
      SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
      SetStyle (ControlStyles.Selectable, false);
      SetStyle (ControlStyles.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 = Control.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 = Control.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 ControlCollection Controls {
      get { return base.Controls; }
    }

    [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 (ControlStyles.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 Control GetChildAtPoint (Point point)
    {
      return base.GetChildAtPoint (point);
    }

    [EditorBrowsable (EditorBrowsableState.Never)]
    public new Control 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 ControlCollection CreateControlsInstance ()
    {
      return base.CreateControlsInstance ();
    }

    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) {
        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.HideMenus (true, 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 ToolStripControlHost) && mouse_currently_over.Enabled) {
        // Fire our ItemClicked event
        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.Control | 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.Control | 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 ToolStripControlHost)
            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) && Control.IsMnemonic (charCode, tsi.Text))
          return tsi.ProcessMnemonic (charCode);

      string code = Char.ToUpper (charCode).ToString ();
      
      // If any item's text starts with our letter, it gets the message
      if ((Control.ModifierKeys & Keys.Alt) != 0 || this is ToolStripDropDownMenu)
        foreach (ToolStripItem tsi in this.Items)
          if (tsi.Enabled && tsi.Visible && !string.IsNullOrEmpty (tsi.Text) && tsi.Text.ToUpper ().StartsWith (code) && !(tsi is ToolStripControlHost))
            return tsi.ProcessMnemonic (charCode);

      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 ControlEventHandler ControlAdded {
      add { base.ControlAdded += value; }
      remove { base.ControlAdded -= value; }
    }

    [Browsable (false)]
    [EditorBrowsable (EditorBrowsableState.Never)]
    public new event ControlEventHandler ControlRemoved {
      add { base.ControlRemoved += value; }
      remove { base.ControlRemoved -= 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 ToolStripControlHost))
        this.FocusInternal (true);

      if (nextItem is ToolStripControlHost)
        (nextItem as ToolStripControlHost).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 ToolStripControlHost) && (tsi as ToolStripControlHost).Control.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 ((DisplayRectangle.Width - currentLocation.X) < (tsi.Width + tsi.Margin.Horizontal)) {

            currentLocation.Y += tallest;
            tallest = 0;
            
            currentLocation.X = DisplayRectangle.Left;
          }

          // Offset the left margin and set the control to our point
          currentLocation.Offset (tsi.Margin.Left, 0);
          tallest = Math.Max (tallest, tsi.Height + tsi.Margin.Vertical);
          
          // Update our location pointer
          currentLocation.X += tsi.Width + tsi.Margin.Right;
        }

        currentLocation.Y += tallest;
        return new Size (currentLocation.X, currentLocation.Y);
      }
        
      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 HideMenus (bool release, ToolStripDropDownCloseReason reason)
    {
      if (this is MenuStrip && release && menu_selected)
        (this as MenuStrip).FireMenuDeactivate ();
        
      if (release)
        menu_selected = false;
        
      NotifySelectedChanged (null);
    }

    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 ToolStripControlHost)
            return false;
          
          tsi = this.SelectNextToolStripItem (tsi, true);
          
          if (tsi is ToolStripControlHost)
            (tsi as ToolStripControlHost).Focus ();
            
          return true;
        case Keys.Tab:
          tsi = this.GetCurrentlySelectedItem ();

          tsi = this.SelectNextToolStripItem (tsi, true);

          if (tsi is ToolStripControlHost)
            (tsi as ToolStripControlHost).Focus ();
            
          return true;
        case Keys.Left:
          tsi = this.GetCurrentlySelectedItem ();

          if (tsi is ToolStripControlHost)
            return false;

          tsi = this.SelectNextToolStripItem (tsi, false);

          if (tsi is ToolStripControlHost)
            (tsi as ToolStripControlHost).Focus ();

          return true;
        case Keys.Shift | Keys.Tab:
          tsi = this.GetCurrentlySelectedItem ();
          
          tsi = this.SelectNextToolStripItem (tsi, false);

          if (tsi is ToolStripControlHost)
            (tsi as ToolStripControlHost).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 ToolStripControlHost)
        (next_item as ToolStripControlHost).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 : ControlAccessibleObject
    {
      #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
  }
}
#endif
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.