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

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

Fixes TextField context menu not showing with the current localization.
Tig Kindel преди 3 години
родител
ревизия
38d5e6c2bf
променени са 4 файла, в които са добавени 130 реда и са изтрити 13 реда
  1. 6 1
      Terminal.Gui/Core/ContextMenu.cs
  2. 47 1
      Terminal.Gui/Views/Menu.cs
  3. 25 11
      Terminal.Gui/Views/TextField.cs
  4. 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)
 		{

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

@@ -7,7 +7,9 @@
 
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
+using System.Threading;
 using NStack;
 using Terminal.Gui.Resources;
 using Rune = System.Rune;
@@ -25,6 +27,7 @@ namespace Terminal.Gui {
 		int selectedStart = -1; // -1 represents there is no text selection.
 		ustring selectedText;
 		HistoryText historyText = new HistoryText ();
+		CultureInfo currentCulture;
 
 		/// <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
@@ -202,22 +205,27 @@ namespace Terminal.Gui {
 			AddKeyBinding (Key.T | Key.CtrlMask, Command.SelectAll);
 			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;
 
 			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)
 		{
 			ReplaceKeyBinding (obj, ContextMenu.Key);
@@ -921,6 +929,12 @@ namespace Terminal.Gui {
 
 		void ShowContextMenu ()
 		{
+			if (currentCulture != Thread.CurrentThread.CurrentUICulture) {
+
+				currentCulture = Thread.CurrentThread.CurrentUICulture;
+
+				ContextMenu.MenuItens = BuildContextMenuBarItem ();
+			}
 			ContextMenu.Show ();
 		}
 

+ 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);
+		}
 	}
 }