Quellcode durchsuchen

More refactoring. Broke CM

Tig vor 8 Monaten
Ursprung
Commit
0c7d1aee8f

+ 7 - 2
Terminal.Gui/Input/Command.cs

@@ -4,9 +4,14 @@
 namespace Terminal.Gui;
 
 /// <summary>
-///     Actions which can be performed by a <see cref="View"/>. Commands are typically invoked via
-///     <see cref="KeyBindings"/> and <see cref="MouseBindings"/>.
+///     Actions which can be performed by a <see cref="View"/>.
 /// </summary>
+/// <seealso cref="View.KeyBindings"/>
+/// <seealso cref="View.MouseBindings"/>
+/// <seealso cref="Application.KeyBindings"/>
+/// <remarks>
+///     <see cref="Application"/> supports a subset of these commands by default, which can be overriden via <see cref="Application.KeyBindings"/>.
+/// </remarks>
 public enum Command
 {
     #region Base View Commands

+ 1 - 1
Terminal.Gui/Input/Keyboard/KeyBindingScope.cs

@@ -38,6 +38,6 @@ public enum KeyBindingScope
     ///     </para>
     /// </summary>
     /// <seealso cref="View.KeyBindings"/>
-    /// <seeals cref="View.HotKey"/>
+    /// <seealso cref="View.HotKey"/>
     HotKey = 2
 }

+ 23 - 39
Terminal.Gui/View/View.Keyboard.cs

@@ -1,5 +1,6 @@
 #nullable enable
 using System.Diagnostics;
+using System.Reflection.Metadata;
 
 namespace Terminal.Gui;
 
@@ -296,6 +297,12 @@ public partial class View // Keyboard APIs
             return true;
         }
 
+        bool? handled = false;
+        if (InvokeCommandsBoundToHotKeyOnSubviews (key, ref handled))
+        {
+            return true;
+        }
+
         // After
         if (RaiseKeyDownNotHandled (key) || key.Handled)
         {
@@ -499,9 +506,12 @@ public partial class View // Keyboard APIs
 
     #region Key Bindings
 
-    /// <summary>Gets the key bindings for this view.</summary>
+    /// <summary>Gets the bindings for this view that will be invoked only if this view has focus.</summary>
     public KeyBindings KeyBindings { get; internal set; } = null!;
 
+    /// <summary>Gets the bindings for this view that will be invoked regardless of whehter this view has focus or not.</summary>
+    public KeyBindings HotKeyBindings { get; internal set; } = null!;
+
     /// <summary>
     ///     INTERNAL API: Invokes any commands bound to <paramref name="key"/> on this view, adornments, and subviews.
     /// </summary>
@@ -516,15 +526,13 @@ public partial class View // Keyboard APIs
     /// </returns>
     internal bool? InvokeCommandsBoundToKey (Key key)
     {
-        KeyBindingScope scope = KeyBindingScope.Focused | KeyBindingScope.HotKey;
-
         // * If no key binding was found, `InvokeKeyBindings` returns `null`.
         //   Continue passing the event (return `false` from `OnInvokeKeyBindings`).
         // * If key bindings were found, but none handled the key (all `Command`s returned `false`),
         //   `InvokeKeyBindings` returns `false`. Continue passing the event (return `false` from `OnInvokeKeyBindings`)..
         // * If key bindings were found, and any handled the key (at least one `Command` returned `true`),
         //   `InvokeKeyBindings` returns `true`. Continue passing the event (return `false` from `OnInvokeKeyBindings`).
-        bool?  handled = InvokeCommandsBoundToKey (key, scope);
+        bool? handled = InvokeCommandsBoundToKey (key, KeyBindingScope.Focused);
 
         if (handled is true)
         {
@@ -533,22 +541,17 @@ public partial class View // Keyboard APIs
             return handled;
         }
 
-        if (Margin is { } && InvokeCommandsBoundToKeyOnAdornment (Margin, key, scope, ref handled))
-        {
-            return true;
-        }
-
-        if (Padding is { } && InvokeCommandsBoundToKeyOnAdornment (Padding, key, scope, ref handled))
+        if (Margin is { } && InvokeCommandsBoundToKeyOnAdornment (Margin, key, KeyBindingScope.Focused, ref handled))
         {
             return true;
         }
 
-        if (Border is { } && InvokeCommandsBoundToKeyOnAdornment (Border, key, scope, ref handled))
+        if (Padding is { } && InvokeCommandsBoundToKeyOnAdornment (Padding, key, KeyBindingScope.Focused, ref handled))
         {
             return true;
         }
 
-        if (InvokeCommandsBoundToKeyOnSubviews (key, scope, ref handled))
+        if (Border is { } && InvokeCommandsBoundToKeyOnAdornment (Border, key, KeyBindingScope.Focused, ref handled))
         {
             return true;
         }
@@ -588,8 +591,14 @@ public partial class View // Keyboard APIs
         return false;
     }
 
-    private bool InvokeCommandsBoundToKeyOnSubviews (Key key, KeyBindingScope scope, ref bool? handled, bool invoke = true)
+    private bool InvokeCommandsBoundToHotKeyOnSubviews (Key key, ref bool? handled, bool invoke = true)
     {
+        bool? weHandled = InvokeCommandsBoundToKey (key, KeyBindingScope.HotKey);
+        if (weHandled is true)
+        {
+            return true;
+        }
+
         // Now, process any key bindings in the subviews that are tagged to KeyBindingScope.HotKey.
         foreach (View subview in Subviews)
         {
@@ -598,32 +607,7 @@ public partial class View // Keyboard APIs
                 continue;
             }
 
-            if (subview.KeyBindings.TryGet (key, scope, out KeyBinding binding))
-            {
-                if (binding.Scope == KeyBindingScope.Focused && !subview.HasFocus)
-                {
-                    continue;
-                }
-
-                if (!invoke)
-                {
-                    return true;
-                }
-
-                bool? subViewHandled = subview.InvokeCommandsBoundToKey (key);
-
-                if (subViewHandled is { })
-                {
-                    handled = subViewHandled;
-
-                    if ((bool)subViewHandled)
-                    {
-                        return true;
-                    }
-                }
-            }
-
-            bool recurse = subview.InvokeCommandsBoundToKeyOnSubviews (key, scope, ref handled, invoke);
+            bool recurse = subview.InvokeCommandsBoundToHotKeyOnSubviews (key, ref handled, invoke);
 
             if (recurse || (handled is { } && (bool)handled))
             {

+ 5 - 0
Terminal.Gui/Views/Menu/ContextMenu.cs

@@ -110,6 +110,8 @@ public sealed class ContextMenu : IDisposable
         _menuBar = null;
         IsShow = false;
 
+        Application.KeyBindings.Remove (Key);
+
         if (_container is { })
         {
             _container.Closing -= Container_Closing;
@@ -250,6 +252,9 @@ public sealed class ContextMenu : IDisposable
 
         _menuBar._isContextMenuLoading = true;
         _menuBar.MenuAllClosed += MenuBar_MenuAllClosed;
+
+        Application.KeyBindings.Add (Key, _menuBar, Command.Cancel);
+
         _menuBar.BeginInit ();
         _menuBar.EndInit ();
         IsShow = true;

+ 1 - 0
UnitTests/Application/KeyboardTests.cs

@@ -189,6 +189,7 @@ public class KeyboardTests
         keyWasHandled = false;
         Application.RaiseKeyDownEvent (Key.H);
         Assert.False (keyWasHandled);
+        Assert.True (view.HotKeyCommand);
 
         keyWasHandled = false;
         Assert.False (view.HasFocus);