Преглед на файлове

Only allows an open menu bar at a time.

BDisp преди 3 години
родител
ревизия
17ed8dbed0
променени са 3 файла, в които са добавени 105 реда и са изтрити 2 реда
  1. 6 1
      Terminal.Gui/Core/ContextMenu.cs
  2. 47 1
      Terminal.Gui/Views/Menu.cs
  3. 52 0
      UnitTests/ContextMenuTests.cs

+ 6 - 1
Terminal.Gui/Core/ContextMenu.cs

@@ -132,7 +132,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		public void Hide ()
 		{
-			menuBar.CloseAllMenus ();
+			menuBar.CleanUp ();
 			Dispose ();
 		}
 
@@ -196,5 +196,10 @@ namespace Terminal.Gui {
 		/// if the left or right position are negative.
 		/// </summary>
 		public bool ForceMinimumPosToZero { get; set; } = true;
+
+		/// <summary>
+		/// Gets the <see cref="Gui.MenuBar"/> that is hosting this context menu.
+		/// </summary>
+		public MenuBar MenuBar { get => menuBar; }
 	}
 }

+ 47 - 1
Terminal.Gui/Views/Menu.cs

@@ -377,7 +377,7 @@ namespace Terminal.Gui {
 
 	class Menu : View {
 		internal MenuBarItem barItems;
-		MenuBar host;
+		internal MenuBar host;
 		internal int current;
 		internal View previousSubFocused;
 
@@ -905,6 +905,11 @@ namespace Terminal.Gui {
 					// The right way to do this is to SetFocus(MenuBar), but for some reason
 					// that faults.
 
+					var mbar = GetMouseGrabViewInstance (this);
+					if (mbar != null) {
+						mbar.CleanUp ();
+					}
+
 					//Activate (0);
 					//StartMenu ();
 					IsMenuOpen = true;
@@ -1173,6 +1178,11 @@ namespace Terminal.Gui {
 		/// </summary>
 		public void OpenMenu ()
 		{
+			var mbar = GetMouseGrabViewInstance (this);
+			if (mbar != null) {
+				mbar.CleanUp ();
+			}
+
 			if (openMenu != null)
 				return;
 			selected = 0;
@@ -1662,6 +1672,8 @@ namespace Terminal.Gui {
 								var menu = new Menu (this, i, 0, Menus [i]);
 								menu.Run (Menus [i].Action);
 								menu.Dispose ();
+							} else if (!IsMenuOpen) {
+								Activate (i);
 							}
 						} else if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked || me.Flags == MouseFlags.Button1TripleClicked) {
 							if (IsMenuOpen && !Menus [i].IsTopLevel) {
@@ -1696,6 +1708,16 @@ namespace Terminal.Gui {
 		{
 			if (Application.mouseGrabView != null) {
 				if (me.View is MenuBar || me.View is Menu) {
+					var mbar = GetMouseGrabViewInstance (me.View);
+					if (mbar != null) {
+						if (me.Flags == MouseFlags.Button1Clicked) {
+							mbar.CleanUp ();
+							Application.GrabMouse (me.View);
+						} else {
+							handled = false;
+							return false;
+						}
+					}
 					if (me.View != current) {
 						Application.UngrabMouse ();
 						var v = me.View;
@@ -1791,6 +1813,30 @@ namespace Terminal.Gui {
 			return true;
 		}
 
+		MenuBar GetMouseGrabViewInstance (View view)
+		{
+			if (view == null || Application.mouseGrabView == null) {
+				return null;
+			}
+
+			MenuBar hostView = null;
+			if (view is MenuBar) {
+				hostView = (MenuBar)view;
+			} else if (view is Menu) {
+				hostView = ((Menu)view).host;
+			}
+
+			var grabView = Application.mouseGrabView;
+			MenuBar hostGrabView = null;
+			if (grabView is MenuBar) {
+				hostGrabView = (MenuBar)grabView;
+			} else if (grabView is Menu) {
+				hostGrabView = ((Menu)grabView).host;
+			}
+
+			return hostView != hostGrabView ? hostGrabView : null;
+		}
+
 		///<inheritdoc/>
 		public override bool OnEnter (View view)
 		{

+ 52 - 0
UnitTests/ContextMenuTests.cs

@@ -463,5 +463,57 @@ namespace Terminal.Gui.Core {
 			pos = GraphViewTests.AssertDriverContentsWithPosAre (expected, output);
 			Assert.Equal (new Point (1, 0), pos);
 		}
+
+		[Fact, AutoInitShutdown]
+		public void ContextMenu_Is_Closed_If_Another_MenuBar_Is_Open_Or_Vice_Versa ()
+		{
+			var cm = new ContextMenu (10, 5,
+				new MenuBarItem (new MenuItem [] {
+					new MenuItem ("One", "", null),
+					new MenuItem ("Two", "", null)
+				})
+			);
+
+			var menu = new MenuBar (new MenuBarItem [] {
+					new MenuBarItem ("File", "", null),
+					new MenuBarItem ("Edit", "", null)
+				});
+
+			Application.Top.Add (menu);
+
+			Assert.Null (Application.mouseGrabView);
+
+			cm.Show ();
+			Assert.True (ContextMenu.IsShow);
+			Assert.Equal (cm.MenuBar, Application.mouseGrabView);
+			Assert.False (menu.IsMenuOpen);
+			Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ())));
+			Assert.False (ContextMenu.IsShow);
+			Assert.Equal (menu, Application.mouseGrabView);
+			Assert.True (menu.IsMenuOpen);
+
+			cm.Show ();
+			Assert.True (ContextMenu.IsShow);
+			Assert.Equal (cm.MenuBar, Application.mouseGrabView);
+			Assert.False (menu.IsMenuOpen);
+			Assert.False (menu.OnKeyDown (new KeyEvent (Key.Null, new KeyModifiers () { Alt = true })));
+			Assert.True (menu.OnKeyUp (new KeyEvent (Key.Null, new KeyModifiers () { Alt = true })));
+			Assert.False (ContextMenu.IsShow);
+			Assert.Equal (menu, Application.mouseGrabView);
+			Assert.True (menu.IsMenuOpen);
+
+			cm.Show ();
+			Assert.True (ContextMenu.IsShow);
+			Assert.Equal (cm.MenuBar, Application.mouseGrabView);
+			Assert.False (menu.IsMenuOpen);
+			Assert.False (menu.MouseEvent (new MouseEvent () { X = 1, Flags = MouseFlags.ReportMousePosition, View = menu }));
+			Assert.True (ContextMenu.IsShow);
+			Assert.Equal (cm.MenuBar, Application.mouseGrabView);
+			Assert.False (menu.IsMenuOpen);
+			Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Flags = MouseFlags.Button1Clicked, View = menu }));
+			Assert.False (ContextMenu.IsShow);
+			Assert.Equal (menu, Application.mouseGrabView);
+			Assert.True (menu.IsMenuOpen);
+		}
 	}
 }