Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs/class
diff options
context:
space:
mode:
authorNikita Voronchev <nikita.voronchev@ru.axxonsoft.com>2020-01-28 18:30:46 +0300
committerAlexander Köplinger <alex.koeplinger@outlook.com>2020-01-28 18:30:46 +0300
commitc191dba87dee8d8bd25ed3d7247ae47a782cc1c6 (patch)
treea7bd56efc7ec8363fa12d743bd81f387d7399924 /mcs/class
parent726a9134c8523f849cb265000c27ed3c5b426d19 (diff)
[WinForms] Make `ContextMenuStrip` behavior closer to the reference one (#18598)
* [WinForms] Make `ContextMenuStrip` behavior closer to the reference one * Bump API snapshot submodule Co-authored-by: monojenkins <jo.shields+jenkins@xamarin.com>
Diffstat (limited to 'mcs/class')
-rw-r--r--mcs/class/System.Windows.Forms/System.Windows.Forms/ContextMenuStrip.cs19
-rw-r--r--mcs/class/System.Windows.Forms/System.Windows.Forms/Control.cs30
-rw-r--r--mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripDropDown.cs51
-rw-r--r--mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripMenuItem.cs6
-rw-r--r--mcs/class/System.Windows.Forms/System.Windows.Forms_test.dll.sources1
-rw-r--r--mcs/class/System.Windows.Forms/Test/System.Windows.Forms/ContextMenuStripTest.cs166
6 files changed, 217 insertions, 56 deletions
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/ContextMenuStrip.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/ContextMenuStrip.cs
index 1df14883d09..c95804739f9 100644
--- a/mcs/class/System.Windows.Forms/System.Windows.Forms/ContextMenuStrip.cs
+++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/ContextMenuStrip.cs
@@ -35,27 +35,23 @@ namespace System.Windows.Forms
[DefaultEvent ("Opening")]
public class ContextMenuStrip : ToolStripDropDownMenu
{
- Control source_control;
- internal Control container;
+ internal Control AssociatedControl;
#region Public Construtors
public ContextMenuStrip () : base ()
{
- source_control = null;
}
- public ContextMenuStrip (IContainer container) : base ()
+ public ContextMenuStrip (IContainer container) : this ()
{
- source_control = null;
+ // TODO: handle `container` argument
}
#endregion
#region Public Properties
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- public Control SourceControl {
- get { return this.source_control; }
- }
+ public Control SourceControl { get; protected set; }
#endregion
#region Protected Methods
@@ -70,11 +66,12 @@ namespace System.Windows.Forms
if (visible)
XplatUI.SetTopmost (this.Handle, true);
}
- #endregion
- internal void SetSourceControl (Control source_control)
+ protected override void SetOwnerControl (Control control)
{
- container = this.source_control = source_control;
+ base.SetOwnerControl (control);
+ SourceControl = control;
}
+ #endregion
}
}
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/Control.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/Control.cs
index ecd8c90e51b..d85c52dff6e 100644
--- a/mcs/class/System.Windows.Forms/System.Windows.Forms/Control.cs
+++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/Control.cs
@@ -2426,7 +2426,7 @@ namespace System.Windows.Forms
if (this.context_menu_strip != value) {
this.context_menu_strip = value;
if (value != null)
- value.container = this;
+ value.AssociatedControl = this;
OnContextMenuStripChanged (EventArgs.Empty);
}
}
@@ -5497,22 +5497,21 @@ namespace System.Windows.Forms
return;
}
- // If there isn't a regular context menu, show the Strip version
- if (context_menu == null && context_menu_strip != null) {
- Point pt;
+ // If there isn't a regular context menu, show the Strip version
+ if (context_menu == null && context_menu_strip != null) {
+ Point pt;
- pt = new Point (LowOrder ((int)m.LParam.ToInt32 ()), HighOrder ((int)m.LParam.ToInt32 ()));
-
- if (pt.X == -1 || pt.Y == -1) {
- pt.X = (this.Width / 2) + this.Left;
- pt.Y = (this.Height /2) + this.Top;
- pt = this.PointToScreen (pt);
- }
-
- context_menu_strip.SetSourceControl (this);
- context_menu_strip.Show (this, PointToClient (pt));
- return;
+ pt = new Point (LowOrder ((int)m.LParam.ToInt32 ()), HighOrder ((int)m.LParam.ToInt32 ()));
+
+ if (pt.X == -1 || pt.Y == -1) {
+ pt.X = (this.Width / 2) + this.Left;
+ pt.Y = (this.Height /2) + this.Top;
+ pt = this.PointToScreen (pt);
}
+
+ context_menu_strip.Show (this, PointToClient (pt));
+ return;
+ }
DefWndProc(ref m);
}
@@ -6499,7 +6498,6 @@ namespace System.Windows.Forms
remove { Events.RemoveHandler (ContextMenuStripChangedEvent, value);}
}
-
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Browsable(true)]
public event ControlEventHandler ControlAdded {
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripDropDown.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripDropDown.cs
index 33eb3c50b99..2bf32495378 100644
--- a/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripDropDown.cs
+++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripDropDown.cs
@@ -383,26 +383,36 @@ namespace System.Windows.Forms
[EditorBrowsable (EditorBrowsableState.Never)]
public new void Show ()
{
- Show (Location, DefaultDropDownDirection);
+ Show (Location);
+ }
+
+ public void Show (int x, int y)
+ {
+ Show (new Point (x, y));
}
public void Show (Point screenLocation)
{
+ SetOwnerControl (null);
Show (screenLocation, DefaultDropDownDirection);
}
-
+
+ public void Show (Control control, int x, int y)
+ {
+ Show (control, new Point (x, y));
+ }
+
public void Show (Control control, Point position)
{
- if (control == null)
- throw new ArgumentNullException ("control");
-
- XplatUI.SetOwner (Handle, control.Handle);
- Show (control.PointToScreen (position), DefaultDropDownDirection);
+ Show (control, position, DefaultDropDownDirection);
}
- public void Show (int x, int y)
+ public void Show (Control control, Point position, ToolStripDropDownDirection direction)
{
- Show (new Point (x, y), DefaultDropDownDirection);
+ if (control == null)
+ throw new ArgumentNullException ("control");
+ SetOwnerControl (control);
+ Show (control.PointToScreen (position), direction);
}
public void Show (Point position, ToolStripDropDownDirection direction)
@@ -522,26 +532,17 @@ namespace System.Windows.Forms
this.OnOpened (EventArgs.Empty);
}
-
- public void Show (Control control, int x, int y)
- {
- if (control == null)
- throw new ArgumentNullException ("control");
- Show (control, new Point (x, y));
- }
-
- public void Show (Control control, Point position, ToolStripDropDownDirection direction)
- {
- if (control == null)
- throw new ArgumentNullException ("control");
-
- XplatUI.SetOwner (Handle, control.Handle);
- Show (control.PointToScreen (position), direction);
- }
#endregion
#region Protected Methods
+
+ protected virtual void SetOwnerControl (Control ownerControl)
+ {
+ var ownerControlHandle = (ownerControl == null) ? IntPtr.Zero : ownerControl.Handle;
+ XplatUI.SetOwner (Handle, ownerControlHandle);
+ }
+
protected override AccessibleObject CreateAccessibilityInstance ()
{
return new ToolStripDropDownAccessibleObject (this);
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripMenuItem.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripMenuItem.cs
index 4df33979088..7a60ac82f29 100644
--- a/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripMenuItem.cs
+++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/ToolStripMenuItem.cs
@@ -419,10 +419,8 @@ namespace System.Windows.Forms
if (item.Owner == null)
return null;
- if (item.Owner is ContextMenuStrip) {
- Control container = ((ContextMenuStrip)item.Owner).container;
- return container == null ? null : container.TopLevelControl;
- }
+ if (item.Owner is ContextMenuStrip ownerContextMenuStrip)
+ return ownerContextMenuStrip.SourceControl?.TopLevelControl;
// MainMenuStrip
return item.Owner.TopLevelControl;
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms_test.dll.sources b/mcs/class/System.Windows.Forms/System.Windows.Forms_test.dll.sources
index a4045f284ea..c9eb6898556 100644
--- a/mcs/class/System.Windows.Forms/System.Windows.Forms_test.dll.sources
+++ b/mcs/class/System.Windows.Forms/System.Windows.Forms_test.dll.sources
@@ -26,6 +26,7 @@ System.Windows.Forms/Common.cs
System.Windows.Forms/CommonDialogsTest.cs
System.Windows.Forms/ContainerControlTest.cs
System.Windows.Forms/ContextMenuTest.cs
+System.Windows.Forms/ContextMenuStripTest.cs
System.Windows.Forms/ControlBindingsCollectionTest.cs
System.Windows.Forms/ControlBindingsConverterTest.cs
System.Windows.Forms/ControlCollectionTest.cs
diff --git a/mcs/class/System.Windows.Forms/Test/System.Windows.Forms/ContextMenuStripTest.cs b/mcs/class/System.Windows.Forms/Test/System.Windows.Forms/ContextMenuStripTest.cs
new file mode 100644
index 00000000000..f5f62d6d330
--- /dev/null
+++ b/mcs/class/System.Windows.Forms/Test/System.Windows.Forms/ContextMenuStripTest.cs
@@ -0,0 +1,166 @@
+//
+// ContextMenuTestStrip.cs: Test cases for ContextMenuStrip
+//
+// Author:
+// Nikita Voronchev (nikita.voronchev@ru.axxonsoft.com)
+//
+// (C) 2020 AxxonSoft (https://www.axxonsoft.com/)
+//
+
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using NUnit.Framework;
+
+namespace MonoTests.System.Windows.Forms
+{
+ // TODO:
+ // -- Tests around `OwnerItem`.
+
+ [TestFixture]
+ public class ContextMenuStripTest : TestHelper
+ {
+ static TestExtendedForm form;
+ static Label explicitMenuSrcLabel;
+ static TestExtendedLabel testExtendedLabel;
+ static ContextMenuStrip contextMenuStrip;
+
+ static readonly Lazy<Control>[] testCaseExplicitMenuSources = new Lazy<Control>[] {
+ new Lazy<Control>(() => null),
+ new Lazy<Control>(() => explicitMenuSrcLabel)
+ }; // Involve `Lazy` to use `TestCaseSource` attribute.
+
+ static readonly Lazy<ITestExtendedControl>[] testCaseAssociatedControls = new Lazy<ITestExtendedControl>[] {
+ new Lazy<ITestExtendedControl>(() => form),
+ new Lazy<ITestExtendedControl>(() => testExtendedLabel)
+ }; // Involve `Lazy` to use `TestCaseSource` attribute.
+
+ [SetUp]
+ public void SetUp()
+ {
+ form = new TestExtendedForm ();
+ explicitMenuSrcLabel = new Label ();
+ testExtendedLabel = new TestExtendedLabel ();
+ contextMenuStrip = new ContextMenuStrip ();
+
+ form.ShowInTaskbar = false;
+ form.Controls.Add (explicitMenuSrcLabel);
+ form.Controls.Add (testExtendedLabel);
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ contextMenuStrip.Close ();
+ form.Controls.Clear ();
+
+ contextMenuStrip.Dispose ();
+ testExtendedLabel.Dispose ();
+ explicitMenuSrcLabel.Dispose ();
+ form.Dispose ();
+ }
+
+ [Test, TestCaseSource ("testCaseExplicitMenuSources")]
+ public void DirectShowTest01 (Lazy<Control> explicitMenuSrc)
+ {
+ AssingOwner (explicitMenuSrc.Value);
+ contextMenuStrip.Show ();
+ Assert.IsNull (contextMenuStrip.SourceControl, "SourceControl");
+ }
+
+ [Test, TestCaseSource ("testCaseExplicitMenuSources")]
+ public void DirectShowTest02 (Lazy<Control> explicitMenuSrc)
+ {
+ AssingOwner (explicitMenuSrc.Value);
+ contextMenuStrip.Show (form, Point.Empty);
+ Assert.AreEqual (form, contextMenuStrip.SourceControl, "SourceControl");
+ }
+
+ [Test, TestCaseSource ("testCaseExplicitMenuSources")]
+ public void DirectShowTest03 (Lazy<Control> explicitMenuSrc)
+ {
+ AssingOwner (explicitMenuSrc.Value);
+ contextMenuStrip.Show (explicitMenuSrcLabel, Point.Empty);
+ Assert.AreEqual (explicitMenuSrcLabel, contextMenuStrip.SourceControl, "SourceControl");
+ }
+
+ [Test, TestCaseSource ("testCaseExplicitMenuSources")]
+ public void DirectShowTest04 (Lazy<Control> explicitMenuSrc)
+ {
+ AssingOwner (explicitMenuSrc.Value);
+ contextMenuStrip.Show (testExtendedLabel, Point.Empty);
+ Assert.AreEqual (testExtendedLabel, contextMenuStrip.SourceControl, "SourceControl");
+ }
+
+ [Test, TestCaseSource ("testCaseExplicitMenuSources")]
+ public void DirectShowTest05 (Lazy<Control> explicitMenuSrc)
+ {
+ AssingOwner (explicitMenuSrc.Value);
+ contextMenuStrip.Show (form, Point.Empty);
+ contextMenuStrip.Close ();
+ contextMenuStrip.Show ();
+ Assert.IsNull (contextMenuStrip.SourceControl, "SourceControl");
+ }
+
+ [Test, TestCaseSource("testCaseAssociatedControls")]
+ public void ContextShowTest (Lazy<ITestExtendedControl> associatedControl)
+ {
+ bool menuHasBeenOpened = false;
+ contextMenuStrip.Opened += (sender, args) => { menuHasBeenOpened = true; };
+
+ var assCtrl = associatedControl.Value;
+ assCtrl.ContextMenuStrip = contextMenuStrip;
+
+ Assert.IsFalse (menuHasBeenOpened, "menuHasBeenOpened");
+ assCtrl.EmulateWmContextMenu ();
+ Assert.IsTrue (menuHasBeenOpened, "menuHasBeenOpened");
+ Assert.AreEqual (assCtrl, contextMenuStrip.SourceControl, "SourceControl");
+
+ }
+
+ #region Helpers
+
+ private void AssingOwner (Control explicitMenuSrc)
+ {
+ if (explicitMenuSrc != null)
+ explicitMenuSrc.ContextMenuStrip = contextMenuStrip;
+ }
+
+ public interface ITestExtendedControl
+ {
+ void EmulateWmContextMenu ();
+ ContextMenuStrip ContextMenuStrip { set; }
+ }
+
+ class TestExtendedForm : Form, ITestExtendedControl
+ {
+ public void EmulateWmContextMenu ()
+ {
+ var m = TestExtendedControlHelper.MakeWmContextMenu ();
+ WndProc (ref m);
+ }
+ }
+
+ class TestExtendedLabel : Label, ITestExtendedControl
+ {
+ public void EmulateWmContextMenu ()
+ {
+ var m = TestExtendedControlHelper.MakeWmContextMenu ();
+ WndProc (ref m);
+ }
+ }
+
+ static class TestExtendedControlHelper
+ {
+ public static Message MakeWmContextMenu ()
+ {
+ return new Message () {
+ Msg = (int)Msg.WM_CONTEXTMENU,
+ LParam = IntPtr.Zero
+ };
+ }
+ }
+
+ #endregion // end of Helpers
+ }
+}