New tests.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStripMenuItem.cs
index fe01e5b77f2f2a8c2cba419373e495294bf1cbb0..326a3c81247288a6d9aa378a6e4464e8f78814b1 100644 (file)
@@ -31,14 +31,17 @@ using System;
 using System.Drawing;
 using System.ComponentModel;
 using System.Windows.Forms.Design;
+using System.ComponentModel.Design.Serialization;
 
 namespace System.Windows.Forms
 {
        [ToolStripItemDesignerAvailability (ToolStripItemDesignerAvailability.MenuStrip | ToolStripItemDesignerAvailability.ContextMenuStrip)]
+       [DesignerSerializer ("System.Windows.Forms.Design.ToolStripMenuItemCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
        public class ToolStripMenuItem : ToolStripDropDownItem
        {
                private CheckState checked_state;
                private bool check_on_click;
+               private bool close_on_mouse_release;
                private string shortcut_display_string;
                private Keys shortcut_keys = Keys.None;
                private bool show_shortcut_keys = true;
@@ -106,18 +109,19 @@ namespace System.Windows.Forms
                                }
                        }
                        set {
-                               if (this.checked_state != (value ? CheckState.Checked : CheckState.Unchecked)) {
-                                       this.checked_state = value ? CheckState.Checked : CheckState.Unchecked;
-                                       this.Invalidate ();
-                                       this.OnCheckedChanged (EventArgs.Empty);
-                               }
+                               CheckState = value ? CheckState.Checked : CheckState.Unchecked;
                        }
                }
 
                [DefaultValue (false)]
                public bool CheckOnClick {
                        get { return this.check_on_click; }
-                       set { this.check_on_click = value; }
+                       set {
+                               if (this.check_on_click != value) {
+                                       this.check_on_click = value;
+                                       OnUIACheckOnClickChangedEvent (EventArgs.Empty);
+                               }
+                       }
                }
 
                [Bindable (true)]
@@ -130,8 +134,12 @@ namespace System.Windows.Forms
                                if (!Enum.IsDefined (typeof (CheckState), value))
                                        throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for CheckState", value));
 
+                               if (value == checked_state)
+                                       return;
+
                                this.checked_state = value;
                                this.Invalidate ();
+                               this.OnCheckedChanged (EventArgs.Empty);
                                this.OnCheckStateChanged (EventArgs.Empty);
                        }
                }
@@ -152,7 +160,6 @@ namespace System.Windows.Forms
                        set { base.Overflow = value; }
                }
                
-               [MonoTODO ("Renderer doesn't support shortcut keys yet, they will never show.")]
                [Localizable (true)]
                [DefaultValue (true)]
                public bool ShowShortcutKeys {
@@ -160,7 +167,6 @@ namespace System.Windows.Forms
                        set { this.show_shortcut_keys = value; }
                }
                
-               [MonoTODO ("Keyboard navigation not implemented.")]
                [Localizable (true)]
                [DefaultValue (null)]
                public string ShortcutKeyDisplayString {
@@ -168,12 +174,18 @@ namespace System.Windows.Forms
                        set { this.shortcut_display_string = value; }
                }
                
-               [MonoTODO ("Keyboard navigation not implemented.")]
                [Localizable (true)]
                [DefaultValue (Keys.None)]
                public Keys ShortcutKeys {
                        get { return this.shortcut_keys; }
-                       set { this.shortcut_keys = value; }
+                       set { 
+                               if (this.shortcut_keys != value) {
+                                       this.shortcut_keys = value;
+                                       
+                                       if (this.Parent != null)
+                                               ToolStripManager.AddToolStripMenuItem (this);
+                               }
+                        }
                }
                #endregion
 
@@ -192,6 +204,12 @@ namespace System.Windows.Forms
                #endregion
 
                #region Protected Methods
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected override AccessibleObject CreateAccessibilityInstance ()
+               {
+                       return new ToolStripMenuItemAccessibleObject ();
+               }
+               
                protected override ToolStripDropDown CreateDefaultDropDown ()
                {
                        ToolStripDropDownMenu tsddm = new ToolStripDropDownMenu ();
@@ -223,30 +241,19 @@ namespace System.Windows.Forms
                        if (!this.Enabled)
                                return;
                                
-                       if (this.IsOnDropDown) {
-                               if (this.HasDropDownItems)
-                                       return;
+                       if (this.HasDropDownItems) {
+                               base.OnClick (e);
+                               return;
+                       }
+                               
+                       if (this.OwnerItem is ToolStripDropDownItem)
+                               (this.OwnerItem as ToolStripDropDownItem).OnDropDownItemClicked (new ToolStripItemClickedEventArgs (this));
 
-                               this.HideDropDown (ToolStripDropDownCloseReason.ItemClicked);
+                       if (this.IsOnDropDown) {
+                               ToolStrip ts = this.GetTopLevelToolStrip ();
                                
-                               (this.Parent as ToolStripDropDown).Close (ToolStripDropDownCloseReason.ItemClicked);
-                               ToolStripManager.FireAppFocusChanged (this.Parent);
-
-                               Object parent = this.Parent;
-
-                               // Find the top level MenuStrip to inform it to close all open
-                               // dropdowns because this one was clicked
-                               while (parent != null) {
-                                       if (parent is MenuStrip)
-                                               (parent as MenuStrip).HideMenus (true, ToolStripDropDownCloseReason.ItemClicked);
-
-                                       if (parent is ToolStripDropDown)
-                                               parent = (parent as ToolStripDropDown).OwnerItem;
-                                       else if (parent is ToolStripItem)
-                                               parent = (parent as ToolStripItem).Parent;
-                                       else
-                                               break;
-                               }
+                               if (ts != null)
+                                       ts.Dismiss (ToolStripDropDownCloseReason.ItemClicked);
                        }
 
                        if (this.IsMdiWindowListEntry) {
@@ -258,6 +265,13 @@ namespace System.Windows.Forms
                                this.Checked = !this.Checked;
 
                        base.OnClick (e);
+                       
+                       if (!this.IsOnDropDown && !this.HasDropDownItems) {
+                               ToolStrip ts = this.GetTopLevelToolStrip ();
+
+                               if (ts != null)
+                                       ts.Dismiss (ToolStripDropDownCloseReason.ItemClicked);
+                       }
                }
 
                protected override void OnDropDownHide (EventArgs e)
@@ -277,9 +291,11 @@ namespace System.Windows.Forms
 
                protected override void OnMouseDown (MouseEventArgs e)
                {
-                       if (this.HasDropDownItems && Enabled)
-                               if (!this.DropDown.Visible)
-                                       this.ShowDropDown ();
+                       if (!this.IsOnDropDown && this.HasDropDownItems && this.DropDown.Visible)
+                               this.close_on_mouse_release = true;
+                               
+                       if (Enabled && !this.DropDown.Visible)
+                               this.ShowDropDown ();
 
                        base.OnMouseDown (e);
                }
@@ -299,6 +315,15 @@ namespace System.Windows.Forms
 
                protected override void OnMouseUp (MouseEventArgs e)
                {
+                       if (this.close_on_mouse_release) {
+                               this.DropDown.Dismiss (ToolStripDropDownCloseReason.ItemClicked);
+                               this.Invalidate ();
+                               this.close_on_mouse_release = false;
+                               
+                               if (!this.IsOnDropDown && this.Parent is MenuStrip)
+                                       (this.Parent as MenuStrip).MenuDroppedDown = false;
+                       }
+                               
                        if (!this.HasDropDownItems && Enabled)
                                base.OnMouseUp (e);
                }
@@ -312,52 +337,119 @@ namespace System.Windows.Forms
                {
                        base.OnPaint (e);
 
-                       if (this.Owner != null) {
-                               Color font_color = this.Enabled ? this.ForeColor : SystemColors.GrayText;
-                               Image draw_image = this.Enabled ? this.Image : ToolStripRenderer.CreateDisabledImage (this.Image);
-
-                               if (this.IsOnDropDown)
-                                       this.Owner.Renderer.DrawMenuItemBackground (new System.Windows.Forms.ToolStripItemRenderEventArgs (e.Graphics, this));
-                               else
-                                       this.Owner.Renderer.DrawButtonBackground (new System.Windows.Forms.ToolStripItemRenderEventArgs (e.Graphics, this));
+                       // Can't render without an owner
+                       if (this.Owner == null)
+                               return;
+                               
+                       // If DropDown.ShowImageMargin is false, we don't display the image
+                       Image draw_image = this.UseImageMargin ? this.Image : null;
+                       
+                       // Disable this color detection until we do the color detection for ToolStrip *completely*
+                       // Color font_color = this.ForeColor == SystemColors.ControlText ? SystemColors.MenuText : this.ForeColor;
+                       Color font_color = ForeColor;
+                       
+                       if ((this.Selected || this.Pressed) && this.IsOnDropDown && font_color == SystemColors.MenuText)
+                               font_color = SystemColors.HighlightText;
+                       
+                       if (!this.Enabled && this.ForeColor == SystemColors.ControlText)
+                               font_color = SystemColors.GrayText;
+                       
+                       // Gray stuff out if we're disabled
+                       draw_image = this.Enabled ? draw_image : ToolStripRenderer.CreateDisabledImage (draw_image);
+                               
+                       // Draw our background
+                       this.Owner.Renderer.DrawMenuItemBackground (new ToolStripItemRenderEventArgs (e.Graphics, this));
 
-                               Rectangle text_layout_rect;
-                               Rectangle image_layout_rect;
+                       // Figure out where our text and image go
+                       Rectangle text_layout_rect;
+                       Rectangle image_layout_rect;
 
-                               this.CalculateTextAndImageRectangles (out text_layout_rect, out image_layout_rect);
+                       this.CalculateTextAndImageRectangles (out text_layout_rect, out image_layout_rect);
 
-                               if (this.IsOnDropDown) {
+                       if (this.IsOnDropDown) {
+                               if (!this.UseImageMargin) {
+                                       image_layout_rect = Rectangle.Empty;
+                                       text_layout_rect = new Rectangle (8, text_layout_rect.Top, text_layout_rect.Width, text_layout_rect.Height);
+                               } else {
                                        text_layout_rect = new Rectangle (35, text_layout_rect.Top, text_layout_rect.Width, text_layout_rect.Height);
+                               
                                        if (image_layout_rect != Rectangle.Empty)
-                                               image_layout_rect = new Rectangle (4, 3, draw_image.Width, draw_image.Height);
-
-                                       if (this.Checked)
-                                               this.Owner.Renderer.DrawItemCheck (new ToolStripItemImageRenderEventArgs (e.Graphics, this, new Rectangle (2, 1, 19, 19)));
+                                               image_layout_rect = new Rectangle (new Point (4, 3), base.GetImageSize ());
                                }
-                               if (text_layout_rect != Rectangle.Empty)
-                                       this.Owner.Renderer.DrawItemText (new System.Windows.Forms.ToolStripItemTextRenderEventArgs (e.Graphics, this, this.Text, text_layout_rect, font_color, this.Font, this.TextAlign));
 
-                               string key_string = GetShortcutDisplayString ();
+                               if (this.Checked && this.ShowMargin)
+                                       this.Owner.Renderer.DrawItemCheck (new ToolStripItemImageRenderEventArgs (e.Graphics, this, new Rectangle (2, 1, 19, 19)));
+                       }
+                       if (text_layout_rect != Rectangle.Empty)
+                               this.Owner.Renderer.DrawItemText (new ToolStripItemTextRenderEventArgs (e.Graphics, this, this.Text, text_layout_rect, font_color, this.Font, this.TextAlign));
+
+                       string key_string = GetShortcutDisplayString ();
+                       
+                       if (!string.IsNullOrEmpty (key_string) && !this.HasDropDownItems) {
+                               int offset = 15;
+                               Size key_string_size = TextRenderer.MeasureText (key_string, this.Font);
+                               Rectangle key_string_rect = new Rectangle (this.ContentRectangle.Right - key_string_size.Width - offset, text_layout_rect.Top, key_string_size.Width, text_layout_rect.Height);
+                               this.Owner.Renderer.DrawItemText (new ToolStripItemTextRenderEventArgs (e.Graphics, this, key_string, key_string_rect, font_color, this.Font, this.TextAlign));
+                       }
                                
-                               if (!string.IsNullOrEmpty (key_string) && !this.HasDropDownItems) {
-                                       int offset = 15;
-                                       Size key_string_size = TextRenderer.MeasureText (key_string, this.Font);
-                                       Rectangle key_string_rect = new Rectangle (this.ContentRectangle.Right - key_string_size.Width - offset, text_layout_rect.Top, key_string_size.Width, text_layout_rect.Height);
-                                       this.Owner.Renderer.DrawItemText (new System.Windows.Forms.ToolStripItemTextRenderEventArgs (e.Graphics, this, key_string, key_string_rect, font_color, this.Font, this.TextAlign));
-                               }
-                                       
-                               if (image_layout_rect != Rectangle.Empty)
-                                       this.Owner.Renderer.DrawItemImage (new System.Windows.Forms.ToolStripItemImageRenderEventArgs (e.Graphics, this, draw_image, image_layout_rect));
+                       if (image_layout_rect != Rectangle.Empty)
+                               this.Owner.Renderer.DrawItemImage (new ToolStripItemImageRenderEventArgs (e.Graphics, this, draw_image, image_layout_rect));
 
-                               if (this.IsOnDropDown && this.HasDropDownItems)
-                                       this.Owner.Renderer.DrawArrow (new ToolStripArrowRenderEventArgs (e.Graphics, this, new Rectangle (this.Bounds.Width - 17, 2, 10, 20), Color.Black, ArrowDirection.Right));
-                               return;
+                       if (this.IsOnDropDown && this.HasDropDownItems && this.Parent is ToolStripDropDownMenu)
+                               this.Owner.Renderer.DrawArrow (new ToolStripArrowRenderEventArgs (e.Graphics, this, new Rectangle (this.Bounds.Width - 17, 2, 10, 20), Color.Black, ArrowDirection.Right));
+                       
+                       return;
+               }
+
+               protected internal override bool ProcessCmdKey (ref Message m, Keys keyData)
+               {
+                       Control source = Control.FromHandle (m.HWnd);
+                       Form f = source == null ? null : (Form)source.TopLevelControl;
+
+                       if (this.Enabled && keyData == this.shortcut_keys && GetTopLevelControl () == f) {
+                               this.FireEvent (EventArgs.Empty, ToolStripItemEventType.Click);
+                               return true;
+                       }
+                               
+                       return base.ProcessCmdKey (ref m, keyData);
+               }
+
+               Control GetTopLevelControl ()
+               {
+                       ToolStripItem item = this;
+                       while (item.OwnerItem != null)
+                               item = item.OwnerItem;
+
+                       if (item.Owner == null)
+                               return null;
+
+                       if (item.Owner is ContextMenuStrip) {
+                               Control container = ((ContextMenuStrip)item.Owner).container;
+                               return container == null ? null : container.TopLevelControl;
                        }
+
+                       // MainMenuStrip
+                       return item.Owner.TopLevelControl;
                }
 
-               protected internal override void SetBounds (Rectangle bounds)
+               protected internal override bool ProcessMnemonic (char charCode)
                {
-                       base.SetBounds (bounds);
+                       if (!this.Selected)
+                               this.Parent.ChangeSelection (this);
+                               
+                       if (this.HasDropDownItems) {
+                               ToolStripManager.SetActiveToolStrip (this.Parent, true);
+                               this.ShowDropDown ();
+                               this.DropDown.SelectNextToolStripItem (null, true);
+                       } else
+                               this.PerformClick ();
+                       
+                       return true;
+               }
+               
+               protected internal override void SetBounds (Rectangle rect)
+               {
+                       base.SetBounds (rect);
                }
                #endregion
 
@@ -376,6 +468,23 @@ namespace System.Windows.Forms
                }
                #endregion
 
+               #region UIA Framework Events
+               static object UIACheckOnClickChangedEvent = new object ();
+               
+               internal event EventHandler UIACheckOnClickChanged {
+                       add { Events.AddHandler (UIACheckOnClickChangedEvent, value); }
+                       remove { Events.RemoveHandler (UIACheckOnClickChangedEvent, value); }
+               }
+
+               internal void OnUIACheckOnClickChangedEvent (EventArgs args)
+               {
+                       EventHandler eh
+                               = (EventHandler) Events [UIACheckOnClickChangedEvent];
+                       if (eh != null)
+                               eh (this, args);
+               }
+               #endregion
+
                #region Internal Properties
                internal Form MdiClientForm {
                        get { return this.mdi_client_form; }
@@ -400,20 +509,44 @@ namespace System.Windows.Forms
                
                internal string GetShortcutDisplayString ()
                {
-                       if (this.show_shortcut_keys == false || this.shortcut_keys == Keys.None)
+                       if (this.show_shortcut_keys == false)
                                return string.Empty;
-
-                       string key_string;
+                       if (this.Parent == null || !(this.Parent is ToolStripDropDownMenu))
+                               return string.Empty;
+                               
+                       string key_string = string.Empty;
 
                        if (!string.IsNullOrEmpty (this.shortcut_display_string))
                                key_string = this.shortcut_display_string;
-                       else {
+                       else if (this.shortcut_keys != Keys.None) {
                                KeysConverter kc = new KeysConverter ();
                                key_string = kc.ConvertToString (this.shortcut_keys);
                        }
                        
                        return key_string;
                }
+               
+               internal void HandleAutoExpansion ()
+               {
+                       if (this.HasDropDownItems) {
+                               this.ShowDropDown ();
+                               this.DropDown.SelectNextToolStripItem (null, true);
+                       }
+               }
+
+               internal override void HandleClick (int mouse_clicks, EventArgs e)
+               {
+                       this.OnClick (e);
+                       
+                       if (Parent != null)
+                               Parent.Invalidate ();
+               }
+               #endregion
+
+               #region ToolStripMenuItemAccessibleObject
+               private class ToolStripMenuItemAccessibleObject : AccessibleObject
+               {
+               }
                #endregion
        }
 }