Bläddra i källkod

Merge pull request #1630 from BDisp/textfield-localization-fix

Fixes TextField context menu not showing with the current localization.
Tig Kindel 3 år sedan
förälder
incheckning
38d5e6c2bf

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

@@ -132,7 +132,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// </summary>
 		public void Hide ()
 		public void Hide ()
 		{
 		{
-			menuBar.CloseAllMenus ();
+			menuBar.CleanUp ();
 			Dispose ();
 			Dispose ();
 		}
 		}
 
 
@@ -196,5 +196,10 @@ namespace Terminal.Gui {
 		/// if the left or right position are negative.
 		/// if the left or right position are negative.
 		/// </summary>
 		/// </summary>
 		public bool ForceMinimumPosToZero { get; set; } = true;
 		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 {
 	class Menu : View {
 		internal MenuBarItem barItems;
 		internal MenuBarItem barItems;
-		MenuBar host;
+		internal MenuBar host;
 		internal int current;
 		internal int current;
 		internal View previousSubFocused;
 		internal View previousSubFocused;
 
 
@@ -905,6 +905,11 @@ namespace Terminal.Gui {
 					// The right way to do this is to SetFocus(MenuBar), but for some reason
 					// The right way to do this is to SetFocus(MenuBar), but for some reason
 					// that faults.
 					// that faults.
 
 
+					var mbar = GetMouseGrabViewInstance (this);
+					if (mbar != null) {
+						mbar.CleanUp ();
+					}
+
 					//Activate (0);
 					//Activate (0);
 					//StartMenu ();
 					//StartMenu ();
 					IsMenuOpen = true;
 					IsMenuOpen = true;
@@ -1173,6 +1178,11 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// </summary>
 		public void OpenMenu ()
 		public void OpenMenu ()
 		{
 		{
+			var mbar = GetMouseGrabViewInstance (this);
+			if (mbar != null) {
+				mbar.CleanUp ();
+			}
+
 			if (openMenu != null)
 			if (openMenu != null)
 				return;
 				return;
 			selected = 0;
 			selected = 0;
@@ -1662,6 +1672,8 @@ namespace Terminal.Gui {
 								var menu = new Menu (this, i, 0, Menus [i]);
 								var menu = new Menu (this, i, 0, Menus [i]);
 								menu.Run (Menus [i].Action);
 								menu.Run (Menus [i].Action);
 								menu.Dispose ();
 								menu.Dispose ();
+							} else if (!IsMenuOpen) {
+								Activate (i);
 							}
 							}
 						} else if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked || me.Flags == MouseFlags.Button1TripleClicked) {
 						} else if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked || me.Flags == MouseFlags.Button1TripleClicked) {
 							if (IsMenuOpen && !Menus [i].IsTopLevel) {
 							if (IsMenuOpen && !Menus [i].IsTopLevel) {
@@ -1696,6 +1708,16 @@ namespace Terminal.Gui {
 		{
 		{
 			if (Application.mouseGrabView != null) {
 			if (Application.mouseGrabView != null) {
 				if (me.View is MenuBar || me.View is Menu) {
 				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) {
 					if (me.View != current) {
 						Application.UngrabMouse ();
 						Application.UngrabMouse ();
 						var v = me.View;
 						var v = me.View;
@@ -1791,6 +1813,30 @@ namespace Terminal.Gui {
 			return true;
 			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/>
 		///<inheritdoc/>
 		public override bool OnEnter (View view)
 		public override bool OnEnter (View view)
 		{
 		{

+ 25 - 11
Terminal.Gui/Views/TextField.cs

@@ -7,7 +7,9 @@
 
 
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
 using System.Linq;
+using System.Threading;
 using NStack;
 using NStack;
 using Terminal.Gui.Resources;
 using Terminal.Gui.Resources;
 using Rune = System.Rune;
 using Rune = System.Rune;
@@ -25,6 +27,7 @@ namespace Terminal.Gui {
 		int selectedStart = -1; // -1 represents there is no text selection.
 		int selectedStart = -1; // -1 represents there is no text selection.
 		ustring selectedText;
 		ustring selectedText;
 		HistoryText historyText = new HistoryText ();
 		HistoryText historyText = new HistoryText ();
+		CultureInfo currentCulture;
 
 
 		/// <summary>
 		/// <summary>
 		/// Tracks whether the text field should be considered "used", that is, that the user has moved in the entry, so new input should be appended at the cursor position, rather than clearing the entry
 		/// Tracks whether the text field should be considered "used", that is, that the user has moved in the entry, so new input should be appended at the cursor position, rather than clearing the entry
@@ -202,22 +205,27 @@ namespace Terminal.Gui {
 			AddKeyBinding (Key.T | Key.CtrlMask, Command.SelectAll);
 			AddKeyBinding (Key.T | Key.CtrlMask, Command.SelectAll);
 			AddKeyBinding (Key.D | Key.CtrlMask | Key.ShiftMask, Command.DeleteAll);
 			AddKeyBinding (Key.D | Key.CtrlMask | Key.ShiftMask, Command.DeleteAll);
 
 
-			ContextMenu = new ContextMenu (this,
-				new MenuBarItem (new MenuItem [] {
-								new MenuItem (Strings.ctxSelectAll, "", () => SelectAll (), null, null, GetKeyFromCommand (Command.SelectAll)),
-								new MenuItem (Strings.ctxDeleteAll, "", () => DeleteAll (), null, null, GetKeyFromCommand (Command.DeleteAll)),
-								new MenuItem (Strings.ctxCopy, "", () => Copy (), null, null, GetKeyFromCommand (Command.Copy)),
-								new MenuItem (Strings.ctxCut, "", () => Cut (), null, null, GetKeyFromCommand (Command.Cut)),
-								new MenuItem (Strings.ctxPaste, "", () => Paste (), null, null, GetKeyFromCommand (Command.Paste)),
-								new MenuItem (Strings.ctxUndo, "", () => UndoChanges (), null, null, GetKeyFromCommand (Command.Undo)),
-								new MenuItem (Strings.ctxRedo, "", () => RedoChanges (), null, null, GetKeyFromCommand (Command.Redo)),
-				})
-			);
+			currentCulture = Thread.CurrentThread.CurrentUICulture;
+
+			ContextMenu = new ContextMenu (this, BuildContextMenuBarItem ());
 			ContextMenu.KeyChanged += ContextMenu_KeyChanged;
 			ContextMenu.KeyChanged += ContextMenu_KeyChanged;
 
 
 			AddKeyBinding (ContextMenu.Key, Command.Accept);
 			AddKeyBinding (ContextMenu.Key, Command.Accept);
 		}
 		}
 
 
+		private MenuBarItem BuildContextMenuBarItem ()
+		{
+			return new MenuBarItem (new MenuItem [] {
+					new MenuItem (Strings.ctxSelectAll, "", () => SelectAll (), null, null, GetKeyFromCommand (Command.SelectAll)),
+					new MenuItem (Strings.ctxDeleteAll, "", () => DeleteAll (), null, null, GetKeyFromCommand (Command.DeleteAll)),
+					new MenuItem (Strings.ctxCopy, "", () => Copy (), null, null, GetKeyFromCommand (Command.Copy)),
+					new MenuItem (Strings.ctxCut, "", () => Cut (), null, null, GetKeyFromCommand (Command.Cut)),
+					new MenuItem (Strings.ctxPaste, "", () => Paste (), null, null, GetKeyFromCommand (Command.Paste)),
+					new MenuItem (Strings.ctxUndo, "", () => UndoChanges (), null, null, GetKeyFromCommand (Command.Undo)),
+					new MenuItem (Strings.ctxRedo, "", () => RedoChanges (), null, null, GetKeyFromCommand (Command.Redo)),
+				});
+		}
+
 		private void ContextMenu_KeyChanged (Key obj)
 		private void ContextMenu_KeyChanged (Key obj)
 		{
 		{
 			ReplaceKeyBinding (obj, ContextMenu.Key);
 			ReplaceKeyBinding (obj, ContextMenu.Key);
@@ -921,6 +929,12 @@ namespace Terminal.Gui {
 
 
 		void ShowContextMenu ()
 		void ShowContextMenu ()
 		{
 		{
+			if (currentCulture != Thread.CurrentThread.CurrentUICulture) {
+
+				currentCulture = Thread.CurrentThread.CurrentUICulture;
+
+				ContextMenu.MenuItens = BuildContextMenuBarItem ();
+			}
 			ContextMenu.Show ();
 			ContextMenu.Show ();
 		}
 		}
 
 

+ 52 - 0
UnitTests/ContextMenuTests.cs

@@ -463,5 +463,57 @@ namespace Terminal.Gui.Core {
 			pos = GraphViewTests.AssertDriverContentsWithPosAre (expected, output);
 			pos = GraphViewTests.AssertDriverContentsWithPosAre (expected, output);
 			Assert.Equal (new Point (1, 0), pos);
 			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);
+		}
 	}
 	}
 }
 }