349 lines
9.8 KiB
C#
349 lines
9.8 KiB
C#
|
//
|
||
|
// ToolStripDropDownItem.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)
|
||
|
//
|
||
|
|
||
|
using System;
|
||
|
using System.Drawing;
|
||
|
using System.ComponentModel;
|
||
|
using System.Threading;
|
||
|
|
||
|
namespace System.Windows.Forms
|
||
|
{
|
||
|
[DefaultProperty ("DropDownItems")]
|
||
|
[Designer ("System.Windows.Forms.Design.ToolStripMenuItemDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
|
||
|
public abstract class ToolStripDropDownItem : ToolStripItem
|
||
|
{
|
||
|
internal ToolStripDropDown drop_down;
|
||
|
private ToolStripDropDownDirection drop_down_direction;
|
||
|
|
||
|
#region Protected Constructors
|
||
|
protected ToolStripDropDownItem () : this (string.Empty, null, null, string.Empty)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected ToolStripDropDownItem (string text, Image image, EventHandler onClick)
|
||
|
: this (text, image, onClick, string.Empty)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected ToolStripDropDownItem (string text, Image image, params ToolStripItem[] dropDownItems)
|
||
|
: this (text, image, null, string.Empty)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected ToolStripDropDownItem (string text, Image image, EventHandler onClick, string name)
|
||
|
: base (text, image, onClick, name)
|
||
|
{
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Public Properties
|
||
|
[TypeConverter (typeof (ReferenceConverter))]
|
||
|
public ToolStripDropDown DropDown {
|
||
|
get {
|
||
|
if (this.drop_down == null) {
|
||
|
this.drop_down = CreateDefaultDropDown ();
|
||
|
this.drop_down.ItemAdded += new ToolStripItemEventHandler (DropDown_ItemAdded);
|
||
|
}
|
||
|
|
||
|
return this.drop_down;
|
||
|
}
|
||
|
set {
|
||
|
this.drop_down = value;
|
||
|
this.drop_down.OwnerItem = this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
public ToolStripDropDownDirection DropDownDirection {
|
||
|
get { return this.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.drop_down_direction = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
|
||
|
public ToolStripItemCollection DropDownItems {
|
||
|
get { return this.DropDown.Items; }
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
public virtual bool HasDropDownItems {
|
||
|
get { return this.drop_down != null && this.DropDown.Items.Count != 0; }
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
public override bool Pressed {
|
||
|
get { return base.Pressed || (this.drop_down != null && this.DropDown.Visible); }
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Protected Properties
|
||
|
protected internal virtual Point DropDownLocation {
|
||
|
get {
|
||
|
Point p;
|
||
|
|
||
|
if (this.IsOnDropDown) {
|
||
|
p = Parent.PointToScreen (new Point (this.Bounds.Left, this.Bounds.Top - 1));
|
||
|
p.X += this.Bounds.Width;
|
||
|
p.Y += this.Bounds.Left;
|
||
|
return p;
|
||
|
}
|
||
|
else
|
||
|
p = new Point (this.Bounds.Left, this.Bounds.Bottom - 1);
|
||
|
|
||
|
return Parent.PointToScreen (p);
|
||
|
}
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Public Methods
|
||
|
public void HideDropDown ()
|
||
|
{
|
||
|
if (this.drop_down == null || !this.DropDown.Visible)
|
||
|
return;
|
||
|
|
||
|
// OnDropDownHide is called before actually closing DropDown
|
||
|
this.OnDropDownHide (EventArgs.Empty);
|
||
|
this.DropDown.Close (ToolStripDropDownCloseReason.CloseCalled);
|
||
|
this.is_pressed = false;
|
||
|
this.Invalidate ();
|
||
|
}
|
||
|
|
||
|
public void ShowDropDown ()
|
||
|
{
|
||
|
// Don't go through this whole deal if
|
||
|
// the DropDown is already visible
|
||
|
if (this.DropDown.Visible)
|
||
|
return;
|
||
|
|
||
|
// Call this before the HasDropDownItems check to give
|
||
|
// users a chance to handle it and add drop down items
|
||
|
this.OnDropDownShow (EventArgs.Empty);
|
||
|
|
||
|
if (!this.HasDropDownItems)
|
||
|
return;
|
||
|
|
||
|
this.Invalidate ();
|
||
|
this.DropDown.Show (this.DropDownLocation);
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Protected Methods
|
||
|
protected override AccessibleObject CreateAccessibilityInstance ()
|
||
|
{
|
||
|
return new ToolStripDropDownItemAccessibleObject (this);
|
||
|
}
|
||
|
|
||
|
protected virtual ToolStripDropDown CreateDefaultDropDown ()
|
||
|
{
|
||
|
ToolStripDropDown tsdd = new ToolStripDropDown ();
|
||
|
tsdd.OwnerItem = this;
|
||
|
return tsdd;
|
||
|
}
|
||
|
|
||
|
protected override void Dispose (bool disposing)
|
||
|
{
|
||
|
if (!IsDisposed) {
|
||
|
if(disposing) {
|
||
|
if (this.HasDropDownItems)
|
||
|
foreach (ToolStripItem tsi in this.DropDownItems)
|
||
|
if (tsi is ToolStripMenuItem)
|
||
|
ToolStripManager.RemoveToolStripMenuItem ((ToolStripMenuItem)tsi);
|
||
|
|
||
|
if (drop_down != null)
|
||
|
ToolStripManager.RemoveToolStrip (drop_down);
|
||
|
}
|
||
|
base.Dispose (disposing);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void OnBoundsChanged ()
|
||
|
{
|
||
|
base.OnBoundsChanged ();
|
||
|
}
|
||
|
|
||
|
protected internal virtual void OnDropDownClosed (EventArgs e)
|
||
|
{
|
||
|
EventHandler eh = (EventHandler)(Events [DropDownClosedEvent]);
|
||
|
if (eh != null)
|
||
|
eh (this, e);
|
||
|
}
|
||
|
|
||
|
protected virtual void OnDropDownHide (EventArgs e)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected internal virtual void OnDropDownItemClicked (ToolStripItemClickedEventArgs e)
|
||
|
{
|
||
|
ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [DropDownItemClickedEvent]);
|
||
|
if (eh != null)
|
||
|
eh (this, e);
|
||
|
}
|
||
|
|
||
|
protected internal virtual void OnDropDownOpened (EventArgs e)
|
||
|
{
|
||
|
EventHandler eh = (EventHandler)(Events [DropDownOpenedEvent]);
|
||
|
if (eh != null)
|
||
|
eh (this, e);
|
||
|
}
|
||
|
|
||
|
protected virtual void OnDropDownShow (EventArgs e)
|
||
|
{
|
||
|
EventHandler eh = (EventHandler)(Events[DropDownOpeningEvent]);
|
||
|
if (eh != null)
|
||
|
eh (this, e);
|
||
|
}
|
||
|
|
||
|
protected override void OnFontChanged (EventArgs e)
|
||
|
{
|
||
|
base.OnFontChanged (e);
|
||
|
|
||
|
// don't use DropDown directly, since doing that
|
||
|
// would created the DropDown control
|
||
|
if (drop_down != null)
|
||
|
drop_down.Font = Font;
|
||
|
}
|
||
|
|
||
|
protected override void OnRightToLeftChanged (EventArgs e)
|
||
|
{
|
||
|
base.OnRightToLeftChanged (e);
|
||
|
}
|
||
|
|
||
|
protected internal override bool ProcessCmdKey (ref Message m, Keys keyData)
|
||
|
{
|
||
|
if (this.HasDropDownItems)
|
||
|
foreach (ToolStripItem tsi in this.DropDownItems)
|
||
|
if (tsi.ProcessCmdKey (ref m, keyData) == true)
|
||
|
return true;
|
||
|
|
||
|
return base.ProcessCmdKey (ref m, keyData);
|
||
|
}
|
||
|
|
||
|
protected internal override bool ProcessDialogKey (Keys keyData)
|
||
|
{
|
||
|
if (!this.Selected || !this.HasDropDownItems)
|
||
|
return base.ProcessDialogKey (keyData);
|
||
|
|
||
|
if (!this.IsOnDropDown) {
|
||
|
if (this.Parent.Orientation == Orientation.Horizontal) {
|
||
|
if (keyData == Keys.Down || keyData == Keys.Enter) {
|
||
|
if (this.Parent is MenuStrip)
|
||
|
(this.Parent as MenuStrip).MenuDroppedDown = true;
|
||
|
this.ShowDropDown ();
|
||
|
this.DropDown.SelectNextToolStripItem (null, true);
|
||
|
return true;
|
||
|
}
|
||
|
} else {
|
||
|
if (keyData == Keys.Right || keyData == Keys.Enter) {
|
||
|
if (this.Parent is MenuStrip)
|
||
|
(this.Parent as MenuStrip).MenuDroppedDown = true;
|
||
|
this.ShowDropDown ();
|
||
|
this.DropDown.SelectNextToolStripItem (null, true);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if (keyData == Keys.Right || keyData == Keys.Enter) {
|
||
|
if (this.HasDropDownItems) {
|
||
|
this.ShowDropDown ();
|
||
|
this.DropDown.SelectNextToolStripItem (null, true);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return base.ProcessDialogKey (keyData);
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Public Events
|
||
|
static object DropDownClosedEvent = new object ();
|
||
|
static object DropDownItemClickedEvent = new object ();
|
||
|
static object DropDownOpenedEvent = new object ();
|
||
|
static object DropDownOpeningEvent = new object ();
|
||
|
|
||
|
public event EventHandler DropDownClosed {
|
||
|
add { Events.AddHandler (DropDownClosedEvent, value); }
|
||
|
remove { Events.RemoveHandler (DropDownClosedEvent, value); }
|
||
|
}
|
||
|
|
||
|
public event ToolStripItemClickedEventHandler DropDownItemClicked {
|
||
|
add { Events.AddHandler (DropDownItemClickedEvent, value); }
|
||
|
remove { Events.RemoveHandler (DropDownItemClickedEvent, value); }
|
||
|
}
|
||
|
|
||
|
public event EventHandler DropDownOpened {
|
||
|
add { Events.AddHandler (DropDownOpenedEvent, value); }
|
||
|
remove { Events.RemoveHandler (DropDownOpenedEvent, value); }
|
||
|
}
|
||
|
|
||
|
public event EventHandler DropDownOpening {
|
||
|
add { Events.AddHandler (DropDownOpeningEvent, value); }
|
||
|
remove { Events.RemoveHandler (DropDownOpeningEvent, value); }
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Internal Methods
|
||
|
internal override void Dismiss (ToolStripDropDownCloseReason reason)
|
||
|
{
|
||
|
if (this.HasDropDownItems && this.DropDown.Visible)
|
||
|
this.DropDown.Dismiss (reason);
|
||
|
|
||
|
base.Dismiss (reason);
|
||
|
}
|
||
|
|
||
|
internal override void HandleClick (int mouse_clicks, EventArgs e)
|
||
|
{
|
||
|
OnClick (e);
|
||
|
}
|
||
|
|
||
|
internal void HideDropDown (ToolStripDropDownCloseReason reason)
|
||
|
{
|
||
|
if (this.drop_down == null || !this.DropDown.Visible)
|
||
|
return;
|
||
|
|
||
|
// OnDropDownHide is called before actually closing DropDown
|
||
|
this.OnDropDownHide (EventArgs.Empty);
|
||
|
this.DropDown.Close (reason);
|
||
|
this.is_pressed = false;
|
||
|
this.Invalidate ();
|
||
|
}
|
||
|
|
||
|
private void DropDown_ItemAdded (object sender, ToolStripItemEventArgs e)
|
||
|
{
|
||
|
e.Item.owner_item = this;
|
||
|
}
|
||
|
#endregion
|
||
|
}
|
||
|
}
|