2
0
Эх сурвалжийг харах

Implementing context menu and localization on TextView. (#1631)

* Only allows an open menu bar at a time.

* Implementing context menu and localization on TextView.

* Fixes the WindowsDriver dirty redrawn on resizing if HeightAsBuffer is true.

* Change CheckType to MenuItemCheckStyle.Checked
BDisp 3 жил өмнө
parent
commit
177465fae2

+ 14 - 13
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -881,17 +881,15 @@ namespace Terminal.Gui {
 				break;
 
 			case WindowsConsole.EventType.WindowBufferSize:
-				if (HeightAsBuffer) {
-					var winSize = WinConsole.GetConsoleBufferWindow (out Point pos);
-					left = pos.X;
-					top = pos.Y;
-					cols = inputEvent.WindowBufferSizeEvent.size.X;
-					rows = inputEvent.WindowBufferSizeEvent.size.Y;
-					//System.Diagnostics.Debug.WriteLine ($"{HeightAsBuffer},{cols},{rows}");
-					ResizeScreen ();
-					UpdateOffScreen ();
-					TerminalResized?.Invoke ();
-				}
+				var winSize = WinConsole.GetConsoleBufferWindow (out Point pos);
+				left = pos.X;
+				top = pos.Y;
+				cols = inputEvent.WindowBufferSizeEvent.size.X;
+				rows = inputEvent.WindowBufferSizeEvent.size.Y;
+				//System.Diagnostics.Debug.WriteLine ($"{HeightAsBuffer},{cols},{rows}");
+				ResizeScreen ();
+				UpdateOffScreen ();
+				TerminalResized?.Invoke ();
 				break;
 
 			case WindowsConsole.EventType.Focus:
@@ -1566,7 +1564,10 @@ namespace Terminal.Gui {
 			//};
 
 			WinConsole.WriteToConsole (new Size (Cols, Rows), OutputBuffer, bufferCoords, damageRegion);
-			UpdateCursor ();
+
+			// The views that wants to display the cursor must call UpdateCursor explicitly.
+			//UpdateCursor ();
+
 			// System.Diagnostics.Debugger.Log (0, "debug", $"Region={damageRegion.Right - damageRegion.Left},{damageRegion.Bottom - damageRegion.Top}\n");
 			WindowsConsole.SmallRect.MakeEmpty (ref damageRegion);
 		}
@@ -1868,7 +1869,7 @@ namespace Terminal.Gui {
 		void IMainLoopDriver.MainIteration ()
 		{
 			while (resultQueue.Count > 0) {
-				var inputEvent = resultQueue.Dequeue()[0];
+				var inputEvent = resultQueue.Dequeue () [0];
 				ProcessInput?.Invoke (inputEvent);
 			}
 			if (winChanged) {

+ 73 - 2
Terminal.Gui/Views/TextView.cs

@@ -25,11 +25,13 @@
 
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Text;
+using System.Threading;
 using NStack;
-
+using Terminal.Gui.Resources;
 using Rune = System.Rune;
 
 namespace Terminal.Gui {
@@ -1136,6 +1138,7 @@ namespace Terminal.Gui {
 		bool allowsReturn = true;
 		bool multiline = true;
 		HistoryText historyText = new HistoryText ();
+		CultureInfo currentCulture;
 
 		/// <summary>
 		/// Raised when the <see cref="Text"/> of the <see cref="TextView"/> changes.
@@ -1233,6 +1236,12 @@ namespace Terminal.Gui {
 			AddCommand (Command.PreviousView, () => ProcessMovePreviousView ());
 			AddCommand (Command.Undo, () => { UndoChanges (); return true; });
 			AddCommand (Command.Redo, () => { RedoChanges (); return true; });
+			AddCommand (Command.DeleteAll, () => { DeleteAll (); return true; });
+			AddCommand (Command.Accept, () => {
+				ContextMenu.Position = new Point (CursorPosition.X - leftColumn + 2, CursorPosition.Y - topRow + 2);
+				ShowContextMenu ();
+				return true;
+			});
 
 			// Default keybindings for this view
 			AddKeyBinding (Key.PageDown, Command.PageDown);
@@ -1327,6 +1336,32 @@ namespace Terminal.Gui {
 
 			AddKeyBinding (Key.Z | Key.CtrlMask, Command.Undo);
 			AddKeyBinding (Key.R | Key.CtrlMask, Command.Redo);
+			AddKeyBinding (Key.D | Key.CtrlMask | Key.ShiftMask, Command.DeleteAll);
+
+			currentCulture = Thread.CurrentThread.CurrentUICulture;
+
+			ContextMenu = new ContextMenu () { MenuItens = 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);
 		}
 
 		private void Model_LinesLoaded ()
@@ -1714,6 +1749,11 @@ namespace Terminal.Gui {
 		/// </summary>
 		public bool HasHistoryChanges => historyText.HasHistoryChanges;
 
+		/// <summary>
+		/// Get the <see cref="ContextMenu"/> for this view.
+		/// </summary>
+		public ContextMenu ContextMenu { get; private set; }
+
 		int GetSelectedLength ()
 		{
 			return SelectedText.Length;
@@ -3428,6 +3468,33 @@ namespace Terminal.Gui {
 			return true;
 		}
 
+		void ShowContextMenu ()
+		{
+			if (currentCulture != Thread.CurrentThread.CurrentUICulture) {
+
+				currentCulture = Thread.CurrentThread.CurrentUICulture;
+
+				ContextMenu.MenuItens = BuildContextMenuBarItem ();
+			}
+			ContextMenu.Show ();
+		}
+
+		/// <summary>
+		/// Deletes all text.
+		/// </summary>
+		public void DeleteAll ()
+		{
+			if (Lines == 0) {
+				return;
+			}
+
+			selectionStartColumn = 0;
+			selectionStartRow = 0;
+			MoveBottomEndExtend ();
+			DeleteCharLeft ();
+			SetNeedsDisplay ();
+		}
+
 		///<inheritdoc/>
 		public override bool OnKeyUp (KeyEvent kb)
 		{
@@ -3942,7 +4009,8 @@ namespace Terminal.Gui {
 				&& !ev.Flags.HasFlag (MouseFlags.WheeledDown) && !ev.Flags.HasFlag (MouseFlags.WheeledUp)
 				&& !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
 				&& !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked | MouseFlags.ButtonShift)
-				&& !ev.Flags.HasFlag (MouseFlags.Button1TripleClicked)) {
+				&& !ev.Flags.HasFlag (MouseFlags.Button1TripleClicked)
+				&& !ev.Flags.HasFlag (ContextMenu.MouseFlags)) {
 				return false;
 			}
 
@@ -4079,6 +4147,9 @@ namespace Terminal.Gui {
 				PositionCursor ();
 				lastWasKill = false;
 				columnTrack = currentColumn;
+			} else if (ev.Flags == ContextMenu.MouseFlags) {
+				ContextMenu.Position = new Point (ev.X + 2, ev.Y + 2);
+				ShowContextMenu ();
 			}
 
 			return true;

+ 54 - 0
UICatalog/Scenarios/Editor.cs

@@ -4,6 +4,8 @@ using System.Text;
 using Terminal.Gui;
 using System.Linq;
 using System.Text.RegularExpressions;
+using System.Threading;
+using System.Globalization;
 
 namespace UICatalog.Scenarios {
 	[ScenarioMetadata (Name: "Editor", Description: "A Terminal.Gui Text Editor via TextView")]
@@ -24,6 +26,9 @@ namespace UICatalog.Scenarios {
 		private bool _matchWholeWord;
 		private Window winDialog;
 		private TabView _tabView;
+		private MenuItem miForceMinimumPosToZero;
+		private bool forceMinimumPosToZero = true;
+		private readonly List<CultureInfo> cultureInfos = Application.SupportedCultures;
 
 		public override void Init (Toplevel top, ColorScheme colorScheme)
 		{
@@ -94,6 +99,13 @@ namespace UICatalog.Scenarios {
 					CreateEnabledChecked (),
 					CreateVisibleChecked ()
 				}),
+				new MenuBarItem ("Conte_xtMenu", new MenuItem [] {
+					miForceMinimumPosToZero = new MenuItem ("ForceMinimumPosTo_Zero", "", () => {
+						miForceMinimumPosToZero.Checked = forceMinimumPosToZero = !forceMinimumPosToZero;
+						_textView.ContextMenu.ForceMinimumPosToZero = forceMinimumPosToZero;
+					}) { CheckType = MenuItemCheckStyle.Checked, Checked = forceMinimumPosToZero },
+					new MenuBarItem ("_Languages", GetSupportedCultures ())
+				})
 			});
 			Top.Add (menu);
 
@@ -175,6 +187,8 @@ namespace UICatalog.Scenarios {
 					e.Handled = true;
 				}
 			};
+
+			Top.Closed += (_) => Thread.CurrentThread.CurrentUICulture = new CultureInfo ("en-US");
 		}
 
 		private void DisposeWinDialog ()
@@ -446,6 +460,46 @@ namespace UICatalog.Scenarios {
 			sw.Close ();
 		}
 
+		private MenuItem [] GetSupportedCultures ()
+		{
+			List<MenuItem> supportedCultures = new List<MenuItem> ();
+			var index = -1;
+
+			foreach (var c in cultureInfos) {
+				var culture = new MenuItem {
+					CheckType = MenuItemCheckStyle.Checked
+				};
+				if (index == -1) {
+					culture.Title = "_English";
+					culture.Help = "en-US";
+					culture.Checked = Thread.CurrentThread.CurrentUICulture.Name == "en-US";
+					CreateAction (supportedCultures, culture);
+					supportedCultures.Add (culture);
+					index++;
+					culture = new MenuItem {
+						CheckType = MenuItemCheckStyle.Checked
+					};
+				}
+				culture.Title = $"_{c.Parent.EnglishName}";
+				culture.Help = c.Name;
+				culture.Checked = Thread.CurrentThread.CurrentUICulture.Name == c.Name;
+				CreateAction (supportedCultures, culture);
+				supportedCultures.Add (culture);
+			}
+			return supportedCultures.ToArray ();
+
+			void CreateAction (List<MenuItem> supportedCultures, MenuItem culture)
+			{
+				culture.Action += () => {
+					Thread.CurrentThread.CurrentUICulture = new CultureInfo (culture.Help.ToString ());
+					culture.Checked = true;
+					foreach (var item in supportedCultures) {
+						item.Checked = item.Help.ToString () == Thread.CurrentThread.CurrentUICulture.Name;
+					}
+				};
+			}
+		}
+
 		private MenuItem [] CreateKeepChecked ()
 		{
 			var item = new MenuItem ();