浏览代码

Implemented ShortCut in the View class within the UICatalog example.

BDisp 4 年之前
父节点
当前提交
b1cc2f8035

+ 59 - 0
Terminal.Gui/Core/ShortCutHelper.cs

@@ -29,6 +29,32 @@ namespace Terminal.Gui {
 		/// </summary>
 		public virtual ustring ShortCutTag => GetShortCutTag (shortCut);
 
+		/// <summary>
+		/// The action to run if the <see cref="ShortCut"/> is defined.
+		/// </summary>
+		public virtual Action ShortCutAction { get; set; }
+
+		/// <summary>
+		/// Gets the key with all the keys modifiers, especially the shift key that sometimes have to be injected later.
+		/// </summary>
+		/// <param name="kb">The <see cref="KeyEvent"/> to check.</param>
+		/// <returns>The <see cref="KeyEvent.Key"/> with all the keys modifiers.</returns>
+		public static Key GetModifiersKey (KeyEvent kb)
+		{
+			var key = kb.Key;
+			if (kb.IsAlt && (key & Key.AltMask) == 0) {
+				key |= Key.AltMask;
+			}
+			if (kb.IsCtrl && (key & Key.CtrlMask) == 0) {
+				key |= Key.CtrlMask;
+			}
+			if (kb.IsShift && (key & Key.ShiftMask) == 0) {
+				key |= Key.ShiftMask;
+			}
+
+			return key;
+		}
+
 		/// <summary>
 		/// Get the <see cref="ShortCut"/> key as string.
 		/// </summary>
@@ -202,5 +228,38 @@ namespace Terminal.Gui {
 			}
 			return false;
 		}
+
+		/// <summary>
+		/// Allows a view to run a <see cref="View.ShortCutAction"/> if defined.
+		/// </summary>
+		/// <param name="kb">The <see cref="KeyEvent"/></param>
+		/// <param name="view">The <see cref="View"/></param>
+		/// <returns><c>true</c> if defined <c>false</c>otherwise.</returns>
+		public static bool FindAndOpenByShortCut (KeyEvent kb, View view = null)
+		{
+			if (view == null) {
+				return false;			}
+
+			var key = kb.KeyValue;
+			var keys = GetModifiersKey (kb);
+			key |= (int)keys;
+			foreach (var v in view.Subviews) {
+				if (v.ShortCut != Key.Null && v.ShortCut == (Key)key) {
+					var action = v.ShortCutAction;
+					if (action != null) {
+						Application.MainLoop.AddIdle (() => {
+							action ();
+							return false;
+						});
+					}
+					return true;
+				}
+				if (FindAndOpenByShortCut (kb, v)) {
+					return true;
+				}
+			}
+
+			return false;
+		}
 	}
 }

+ 13 - 0
Terminal.Gui/Core/Toplevel.cs

@@ -213,6 +213,19 @@ namespace Terminal.Gui {
 			return false;
 		}
 
+		///<inheritdoc/>
+		public override bool ProcessColdKey (KeyEvent keyEvent)
+		{
+			if (base.ProcessColdKey (keyEvent)) {
+				return true;
+			}
+
+			if (ShortCutHelper.FindAndOpenByShortCut(keyEvent, this)) {
+				return true;
+			}
+			return false;
+		}
+
 		View GetDeepestFocusedSubview (View view)
 		{
 			if (view == null) {

+ 30 - 21
Terminal.Gui/Core/View.cs

@@ -125,6 +125,8 @@ namespace Terminal.Gui {
 
 		TextFormatter textFormatter;
 
+		ShortCutHelper shortCutHelper;
+
 		/// <summary>
 		/// Event fired when a subview is being added to this view.
 		/// </summary>
@@ -170,6 +172,28 @@ namespace Terminal.Gui {
 		/// </summary>
 		public Rune HotKeySpecifier { get => textFormatter.HotKeySpecifier; set => textFormatter.HotKeySpecifier = value; }
 
+		/// <summary>
+		/// This is the global setting that can be used as a global shortcut to invoke an action if provided.
+		/// </summary>
+		public Key ShortCut {
+			get => shortCutHelper.ShortCut;
+			set {
+				if (shortCutHelper.ShortCut != value && (ShortCutHelper.PostShortCutValidation (value) || value == Key.Null)) {
+					shortCutHelper.ShortCut = value;
+				}
+			}
+		}
+
+		/// <summary>
+		/// The keystroke combination used in the <see cref="ShortCut"/> as string.
+		/// </summary>
+		public ustring ShortCutTag => ShortCutHelper.GetShortCutTag (shortCutHelper.ShortCut);
+
+		/// <summary>
+		/// The action to run if the <see cref="ShortCut"/> is defined.
+		/// </summary>
+		public virtual Action ShortCutAction { get; set; }
+
 		/// <summary>
 		/// Gets or sets arbitrary data for the view.
 		/// </summary>
@@ -550,6 +574,8 @@ namespace Terminal.Gui {
 			textFormatter = new TextFormatter ();
 			this.Text = ustring.Empty;
 
+			shortCutHelper = new ShortCutHelper ();
+
 			this.Frame = frame;
 			LayoutStyle = LayoutStyle.Absolute;
 		}
@@ -612,6 +638,8 @@ namespace Terminal.Gui {
 		{
 			textFormatter = new TextFormatter ();
 			this.Text = text;
+
+			shortCutHelper = new ShortCutHelper ();
 		}
 
 		/// <summary>
@@ -633,6 +661,8 @@ namespace Terminal.Gui {
 			textFormatter = new TextFormatter ();
 			this.Text = text;
 
+			shortCutHelper = new ShortCutHelper ();
+
 			CanFocus = false;
 			TabIndex = -1;
 			TabStop = false;
@@ -2055,26 +2085,5 @@ namespace Terminal.Gui {
 
 			return true;
 		}
-
-		/// <summary>
-		/// Gets the key with all the keys modifiers, especially the shift key that sometimes have to be injected later.
-		/// </summary>
-		/// <param name="kb">The <see cref="KeyEvent"/> to check.</param>
-		/// <returns>The <see cref="KeyEvent.Key"/> with all the keys modifiers.</returns>
-		public Key GetModifiersKey (KeyEvent kb)
-		{
-			var key = kb.Key;
-			if (kb.IsAlt && (key & Key.AltMask) == 0) {
-				key |= Key.AltMask;
-			}
-			if (kb.IsCtrl && (key & Key.CtrlMask) == 0) {
-				key |= Key.CtrlMask;
-			}
-			if (kb.IsShift && (key & Key.ShiftMask) == 0) {
-				key |= Key.ShiftMask;
-			}
-
-			return key;
-		}
 	}
 }

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

@@ -1328,14 +1328,8 @@ namespace Terminal.Gui {
 			}
 
 			var key = kb.KeyValue;
-			var keys = GetModifiersKey (kb);
+			var keys = ShortCutHelper.GetModifiersKey (kb);
 			key |= (int)keys;
-			//if (kb.IsShift) {
-			//	key |= (int)Key.ShiftMask;
-			//}
-			//if (kb.IsAlt) {
-			//	key |= unchecked((int)Key.AltMask);
-			//}
 			for (int i = 0; i < children.Length; i++) {
 				var mi = children [i];
 				if (mi == null) {

+ 1 - 1
Terminal.Gui/Views/TextField.cs

@@ -345,7 +345,7 @@ namespace Terminal.Gui {
 			// Needed for the Elmish Wrapper issue https://github.com/DieselMeister/Terminal.Gui.Elmish/issues/2
 			var oldCursorPos = point;
 
-			switch (GetModifiersKey (kb)) {
+			switch (ShortCutHelper.GetModifiersKey (kb)) {
 			case Key.DeleteChar:
 			case Key.D | Key.CtrlMask:
 				if (ReadOnly)

+ 2 - 2
UICatalog/Scenarios/DynamicMenuBar.cs

@@ -725,7 +725,7 @@ namespace UICatalog {
 					return;
 				}
 
-				var k = GetModifiersKey (e.KeyEvent);
+				var k = ShortCutHelper.GetModifiersKey (e.KeyEvent);
 				if (CheckShortCut (k, true)) {
 					e.Handled = true;
 				}
@@ -764,7 +764,7 @@ namespace UICatalog {
 			}
 
 			_txtShortCut.KeyUp += (e) => {
-				var k = GetModifiersKey (e.KeyEvent);
+				var k = ShortCutHelper.GetModifiersKey (e.KeyEvent);
 				if (CheckShortCut (k, false)) {
 					e.Handled = true;
 				}

+ 9 - 5
UICatalog/UICatalog.cs

@@ -105,7 +105,7 @@ namespace UICatalog {
 					_rightPane.SetFocus ();
 					_top.Ready -= ReadyHandler;
 				}
-				
+
 				_top.Ready += ReadyHandler;
 
 #if DEBUG_IDISPOSABLE
@@ -114,7 +114,7 @@ namespace UICatalog {
 				foreach (var inst in Responder.Instances) {
 					Debug.Assert (inst.WasDisposed);
 				}
-				Responder.Instances.Clear();
+				Responder.Instances.Clear ();
 #endif
 			}
 
@@ -174,8 +174,10 @@ namespace UICatalog {
 				Width = 25,
 				Height = Dim.Fill (1),
 				CanFocus = false,
+				ShortCut = Key.CtrlMask | Key.C
 			};
-
+			_leftPane.Title = $"{_leftPane.Title} ({_leftPane.ShortCutTag})";
+			_leftPane.ShortCutAction = () => _leftPane.SetFocus ();
 
 			_categories = Scenario.GetAllCategories ().OrderBy (c => c).ToList ();
 			_categoryListView = new ListView (_categories) {
@@ -198,8 +200,10 @@ namespace UICatalog {
 				Width = Dim.Fill (),
 				Height = Dim.Fill (1),
 				CanFocus = true,
-
+				ShortCut = Key.CtrlMask | Key.S
 			};
+			_rightPane.Title = $"{_rightPane.Title} ({_rightPane.ShortCutTag})";
+			_rightPane.ShortCutAction = () => _rightPane.SetFocus ();
 
 			_nameColumnWidth = Scenario.ScenarioMetadata.GetName (_scenarios.OrderByDescending (t => Scenario.ScenarioMetadata.GetName (t).Length).FirstOrDefault ()).Length;
 
@@ -222,7 +226,7 @@ namespace UICatalog {
 			_numlock = new StatusItem (Key.CharMask, "Num", null);
 			_scrolllock = new StatusItem (Key.CharMask, "Scroll", null);
 
-			_statusBar = new StatusBar () { 
+			_statusBar = new StatusBar () {
 				Visible = true,
 			};
 			_statusBar.Items = new StatusItem [] {