Jelajahi Sumber

WIP: Builds. No worky.

Tig 7 bulan lalu
induk
melakukan
e6054f7275

+ 5 - 0
Terminal.Gui/Input/Keyboard/KeyBinding.cs

@@ -43,6 +43,11 @@ public record struct KeyBinding
     /// <summary>The scope of the <see cref="Commands"/>.</summary>
     public KeyBindingScope Scope { get; set; }
 
+    /// <summary>
+    ///     The Key that is bound to the <see cref="Commands"/>.
+    /// </summary>
+    public Key Key { get; set; }
+
     /// <summary>The view the key binding is bound to.</summary>
     public View? BoundView { get; set; }
 

+ 19 - 0
Terminal.Gui/View/View.Command.cs

@@ -330,4 +330,23 @@ public partial class View // Command APIs
 
         return null;
     }
+
+    /// <summary>
+    /// Invokes the specified command.
+    /// </summary>
+    /// <param name="command">The command to invoke.</param>
+    /// <returns>
+    ///     <see langword="null"/> if no command was found; input proessing should continue.
+    ///     <see langword="false"/> if the command was invoked and was not handled (or cancelled); input proessing should continue.
+    ///     <see langword="true"/> if the command was invoked the command was handled (or cancelled); input proessing should stop.
+    /// </returns>
+    public bool? InvokeCommand (Command command)
+    {
+        if (CommandImplementations.TryGetValue (command, out CommandImplementation? implementation))
+        {
+            return implementation (null);
+        }
+
+        return null;
+    }
 }

+ 1 - 1
Terminal.Gui/View/View.Mouse.cs

@@ -360,7 +360,7 @@ public partial class View // Mouse APIs
 
         // Always invoke Select command on MouseClick
         // By default, this will raise Selecting/OnSelecting - Subclasses can override this via AddCommand (Command.Select ...).
-        args.Handled = InvokeCommand (Command.Select, ctx: new (Command.Select, key: null, data: args)) == true;
+        args.Handled = InvokeCommand<KeyBinding> (Command.Select, new ([Command.Select], KeyBindingScope.Focused, null, args)) == true;
 
         return args.Handled;
     }

+ 7 - 3
Terminal.Gui/Views/Button.cs

@@ -70,8 +70,12 @@ public class Button : View, IDesignable
         HighlightStyle = DefaultHighlightStyle;
     }
 
-    private bool? HandleHotKeyCommand (CommandContext ctx)
+    private bool? HandleHotKeyCommand (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         bool cachedIsDefault = IsDefault; // Supports "Swap Default" in Buttons scenario where IsDefault changes
 
         if (RaiseSelecting (ctx) is true)
@@ -93,7 +97,7 @@ public class Button : View, IDesignable
         // If Accept was not handled...
         if (cachedIsDefault && SuperView is { })
         {
-            return SuperView.InvokeCommand (Command.Accept);
+            return SuperView.InvokeCommand<KeyBinding> (Command.Accept, ctx.Binding);
         }
 
         return false;
@@ -133,7 +137,7 @@ public class Button : View, IDesignable
         }
 
         // TODO: With https://github.com/gui-cs/Terminal.Gui/issues/3778 we won't have to pass data:
-        e.Handled = InvokeCommand (Command.HotKey, new (Command.HotKey, null, data: this)) == true;
+        e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new KeyBinding([Command.HotKey], KeyBindingScope.HotKey, this, null)) == true;
     }
 
     private void Button_TitleChanged (object sender, EventArgs<string> e)

+ 6 - 1
Terminal.Gui/Views/CheckBox.cs

@@ -34,8 +34,13 @@ public class CheckBox : View
         HighlightStyle = DefaultHighlightStyle;
     }
 
-    private bool? AdvanceAndSelect (CommandContext ctx)
+    private bool? AdvanceAndSelect (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
+        
         bool? cancelled = AdvanceCheckState ();
 
         if (cancelled is true)

+ 20 - 4
Terminal.Gui/Views/ColorPicker.16.cs

@@ -67,8 +67,12 @@ public class ColorPicker16 : View
 
     /// <summary>Moves the selected item index to the next row.</summary>
     /// <returns></returns>
-    private bool MoveDown (CommandContext ctx)
+    private bool MoveDown (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         if (RaiseSelecting (ctx) == true)
         {
             return true;
@@ -83,8 +87,12 @@ public class ColorPicker16 : View
 
     /// <summary>Moves the selected item index to the previous column.</summary>
     /// <returns></returns>
-    private bool MoveLeft (CommandContext ctx)
+    private bool MoveLeft (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         if (RaiseSelecting (ctx) == true)
         {
             return true;
@@ -100,8 +108,12 @@ public class ColorPicker16 : View
 
     /// <summary>Moves the selected item index to the next column.</summary>
     /// <returns></returns>
-    private bool MoveRight (CommandContext ctx)
+    private bool MoveRight (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         if (RaiseSelecting (ctx) == true)
         {
             return true;
@@ -116,8 +128,12 @@ public class ColorPicker16 : View
 
     /// <summary>Moves the selected item index to the previous row.</summary>
     /// <returns></returns>
-    private bool MoveUp (CommandContext ctx)
+    private bool MoveUp (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         if (RaiseSelecting (ctx) == true)
         {
             return true;

+ 5 - 1
Terminal.Gui/Views/ComboBox.cs

@@ -395,8 +395,12 @@ public class ComboBox : View, IDesignable
         }
     }
 
-    private bool ActivateSelected (CommandContext ctx)
+    private bool ActivateSelected (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         if (HasItems ())
         {
             if (SelectText ())

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

@@ -25,7 +25,7 @@ public class FrameView : View
     private void FrameView_MouseClick (object sender, MouseEventArgs e)
     {
         // base sets focus on HotKey
-        e.Handled = InvokeCommand (Command.HotKey, ctx: new (Command.HotKey, key: null, data: this)) == true;
+        e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new ([Command.HotKey], KeyBindingScope.Focused, null, this)) == true;
     }
 
 

+ 7 - 3
Terminal.Gui/Views/Label.cs

@@ -36,7 +36,7 @@ public class Label : View, IDesignable
     {
         if (!CanFocus)
         {
-            e.Handled = InvokeCommand (Command.HotKey, ctx: new (Command.HotKey, key: null, data: this)) == true;
+            e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new ([Command.HotKey], KeyBindingScope.HotKey, this, this)) == true;
         }
     }
 
@@ -60,8 +60,12 @@ public class Label : View, IDesignable
         set => TextFormatter.HotKeySpecifier = base.HotKeySpecifier = value;
     }
 
-    private bool? InvokeHotKeyOnNext (CommandContext context)
+    private bool? InvokeHotKeyOnNext (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         if (RaiseHandlingHotKey () == true)
         {
             return true;
@@ -78,7 +82,7 @@ public class Label : View, IDesignable
 
         if (me != -1 && me < SuperView?.Subviews.Count - 1)
         {
-            return SuperView?.Subviews [me + 1].InvokeCommand (Command.HotKey, context.Key, context.KeyBinding) == true;
+            return SuperView?.Subviews [me + 1].InvokeCommand<KeyBinding> (Command.HotKey, ctx.Binding) == true;
         }
 
         return false;

+ 5 - 1
Terminal.Gui/Views/ListView.cs

@@ -141,7 +141,11 @@ public class ListView : View, IDesignable
                                         return !SetFocus ();
                                     });
 
-        AddCommand (Command.SelectAll, (ctx) => MarkAll ((bool)ctx.KeyBinding?.Context!));
+        AddCommand (Command.SelectAll, (ctx) =>
+                                       {
+                                           // BUGBUG: This probably isn't right
+                                           return MarkAll ((bool)ctx!.Data);
+                                       });
 
         // Default keybindings for all ListViews
         KeyBindings.Add (Key.CursorUp, Command.Up);

+ 3 - 3
Terminal.Gui/Views/Menu/Menu.cs

@@ -198,9 +198,9 @@ internal sealed class Menu : View
                         return true;
                     }
                    );
-        AddCommand (Command.Select, ctx => _host?.SelectItem ((ctx.KeyBinding?.Context as MenuItem)!));
-        AddCommand (Command.Toggle, ctx => ExpandCollapse ((ctx.KeyBinding?.Context as MenuItem)!));
-        AddCommand (Command.HotKey, ctx => _host?.SelectItem ((ctx.KeyBinding?.Context as MenuItem)!));
+        AddCommand (Command.Select, ctx => _host?.SelectItem ((ctx.Data as MenuItem)!));
+        AddCommand (Command.Toggle, ctx => ExpandCollapse ((ctx.Data as MenuItem)!));
+        AddCommand (Command.HotKey, ctx => _host?.SelectItem ((ctx.Data as MenuItem)!));
 
         // Default key bindings for this view
         KeyBindings.Add (Key.CursorUp, Command.Up);

+ 2 - 2
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -133,7 +133,7 @@ public class MenuBar : View, IDesignable
                                                   {
                                                       CloseOtherOpenedMenuBar ();
 
-                                                      return Select (Menus.IndexOf (ctx.KeyBinding?.Context));
+                                                      return Select (Menus.IndexOf (ctx.Data));
                                                   });
         AddCommand (Command.Select, ctx =>
                                     {
@@ -142,7 +142,7 @@ public class MenuBar : View, IDesignable
                                             // HACK: Work around the fact that View.MouseClick always invokes Select
                                             return false;
                                         }
-                                        var res = Run ((ctx.KeyBinding?.Context as MenuItem)?.Action!);
+                                        var res = Run ((ctx.Data as MenuItem)?.Action!);
                                         CloseAllMenus ();
 
                                         return res;

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

@@ -365,7 +365,7 @@ public static class MessageBox
                                        {
                                            Clicked = (int)button.Data!;
                                        } 
-                                       else if (e.Context.KeyBinding?.BoundView is Button btn)
+                                       else if (e.Context is CommandContext<KeyBinding> { Binding.BoundView: Button btn })
                                        {
                                            Clicked = (int)btn.Data!;
                                        }

+ 10 - 4
Terminal.Gui/Views/RadioGroup.cs

@@ -59,14 +59,20 @@ public class RadioGroup : View, IDesignable, IOrientation
         AddCommand (Command.HotKey,
                     ctx =>
                             {
-                                var item = ctx.KeyBinding?.Context as int?;
+                                if (ctx is not CommandContext<KeyBinding> keyCommandContext)
+                                {
+                                    return false;
+                                }
+
+                                var item = keyCommandContext.Data as int?;
+
 
                                 if (HasFocus)
                                 {
-                                    if (ctx is { KeyBinding: { } } && (ctx.KeyBinding.Value.BoundView != this || HotKey == ctx.Key?.NoAlt.NoCtrl.NoShift))
+                                    if (keyCommandContext is { Binding : { } } && (keyCommandContext.Binding.BoundView != this || HotKey == keyCommandContext.Binding.Key?.NoAlt.NoCtrl.NoShift))
                                     {
                                         // It's this.HotKey OR Another View (Label?) forwarded the hotkey command to us - Act just like `Space` (Select)
-                                        return InvokeCommand (Command.Select, ctx.Key, ctx.KeyBinding);
+                                        return InvokeCommand (Command.Select);
                                     }
                                 }
 
@@ -242,7 +248,7 @@ public class RadioGroup : View, IDesignable, IOrientation
                 if (c > -1)
                 {
                     // Just like the user pressing the items' hotkey
-                    e.Handled = InvokeCommand (Command.HotKey, null, new KeyBinding ([Command.HotKey], KeyBindingScope.HotKey, boundView: this, context: c)) == true;
+                    e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new KeyBinding ([Command.HotKey], KeyBindingScope.HotKey, boundView: this, context: c)) == true;
                 }
             }
 

+ 1 - 1
Terminal.Gui/Views/ScrollBar/ScrollSlider.cs

@@ -241,7 +241,7 @@ public class ScrollSlider : View, IOrientation, IDesignable
         OnScrolled (distance);
         Scrolled?.Invoke (this, new (in distance));
 
-        RaiseSelecting (new (Command.Select, null, null, distance));
+        RaiseSelecting (new CommandContext<KeyBinding> (Command.Select, new KeyBinding ([Command.Select], KeyBindingScope.Focused, null, distance)));
     }
 
     /// <summary>

+ 7 - 3
Terminal.Gui/Views/Shortcut.cs

@@ -300,8 +300,12 @@ public class Shortcut : View, IOrientation, IDesignable
         AddCommand (Command.Select, DispatchCommand);
     }
 
-    private bool? DispatchCommand (CommandContext ctx)
+    private bool? DispatchCommand (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         if (ctx.Data != this)
         {
             // Invoke Select on the command view to cause it to change state if it wants to
@@ -342,7 +346,7 @@ public class Shortcut : View, IOrientation, IDesignable
 
         if (_targetView is { })
         {
-            _targetView.InvokeCommand (Command);
+            _targetView.InvokeCommand (Command, ctx);
         }
 
         return cancel;
@@ -496,7 +500,7 @@ public class Shortcut : View, IOrientation, IDesignable
                 if (e.Context.Data != this)
                 {
                     // Forward command to ourselves
-                    InvokeCommand (Command.Select, new (Command.Select, null, null, this));
+                    InvokeCommand<KeyBinding> (Command.Select, new ([Command.Select], KeyBindingScope.Focused, null, this));
                 }
 
                 // BUGBUG: This prevents NumericUpDown on statusbar in HexEditor from working

+ 5 - 1
Terminal.Gui/Views/Slider.cs

@@ -1785,8 +1785,12 @@ public class Slider<T> : View, IOrientation
         return SetFocusedOption ();
     }
 
-    internal bool Accept (CommandContext ctx)
+    internal bool Accept (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         SetFocusedOption ();
 
         return RaiseAccepting (ctx) == true;

+ 5 - 1
Terminal.Gui/Views/TextView.cs

@@ -6143,8 +6143,12 @@ public class TextView : View
         Paste ();
     }
 
-    private bool ProcessEnterKey (CommandContext ctx)
+    private bool ProcessEnterKey (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         ResetColumnTrack ();
 
         if (_isReadOnly)

+ 5 - 1
Terminal.Gui/Views/TreeView/TreeView.cs

@@ -462,8 +462,12 @@ public class TreeView<T> : View, ITreeView where T : class
     ///     <para>This method also ensures that the selected object is visible.</para>
     /// </summary>
     /// <returns><see langword="true"/> if <see cref="ObjectActivated"/> was fired.</returns>
-    public bool? ActivateSelectedObjectIfAny (CommandContext ctx)
+    public bool? ActivateSelectedObjectIfAny (ICommandContext commandContext)
     {
+        if (commandContext is not CommandContext<KeyBinding> ctx)
+        {
+            return false;
+        }
         // By default, Command.Accept calls OnAccept, so we need to call it here to ensure that the event is fired.
         if (RaiseAccepting (ctx) == true)
         {

+ 1 - 1
UICatalog/Scenarios/Editor.cs

@@ -265,7 +265,7 @@ public class Editor : Scenario
         _textView.VerticalScrollBar.AutoShow = false;
         _textView.UnwrappedCursorPosition += (s, e) =>
                                              {
-                                                 siCursorPosition.Title = $"Ln {e.Point.Y + 1}, Col {e.Point.X + 1}";
+                                                 siCursorPosition.Title = $"Ln {e.Y + 1}, Col {e.X + 1}";
                                              };
 
         _appWindow.Add (statusBar);

+ 20 - 4
UICatalog/Scenarios/KeyBindings.cs

@@ -165,17 +165,29 @@ public class KeyBindingsDemo : View
 
         AddCommand (Command.Save, ctx =>
                                  {
-                                     MessageBox.Query ($"{ctx.KeyBinding?.Scope}", $"Key: {ctx.Key}\nCommand: {ctx.Command}", buttons: "Ok");
+                                     if (ctx is not CommandContext<KeyBinding> keyCommandContext)
+                                     {
+                                         return false;
+                                     }
+                                     MessageBox.Query ($"{keyCommandContext.Binding.Scope}", $"Key: {keyCommandContext.Binding.Key}\nCommand: {ctx.Command}", buttons: "Ok");
                                      return true;
                                  });
         AddCommand (Command.New, ctx =>
                                 {
-                                    MessageBox.Query ($"{ctx.KeyBinding?.Scope}", $"Key: {ctx.Key}\nCommand: {ctx.Command}", buttons: "Ok");
+                                    if (ctx is not CommandContext<KeyBinding> keyCommandContext)
+                                    {
+                                        return false;
+                                    }
+                                    MessageBox.Query ($"{keyCommandContext.Binding.Scope}", $"Key: {keyCommandContext.Binding.Key}\nCommand: {ctx.Command}", buttons: "Ok");
                                     return true;
                                 });
         AddCommand (Command.HotKey, ctx =>
         {
-            MessageBox.Query ($"{ctx.KeyBinding?.Scope}", $"Key: {ctx.Key}\nCommand: {ctx.Command}", buttons: "Ok");
+            if (ctx is not CommandContext<KeyBinding> keyCommandContext)
+            {
+                return false;
+            }
+            MessageBox.Query ($"{keyCommandContext.Binding.Scope}", $"Key: {keyCommandContext.Binding.Key}\nCommand: {ctx.Command}", buttons: "Ok");
             SetFocus ();
             return true;
         });
@@ -186,7 +198,11 @@ public class KeyBindingsDemo : View
 
         AddCommand (Command.Quit, ctx =>
                                          {
-                                             MessageBox.Query ($"{ctx.KeyBinding?.Scope}", $"Key: {ctx.Key}\nCommand: {ctx.Command}", buttons: "Ok");
+                                             if (ctx is not CommandContext<KeyBinding> keyCommandContext)
+                                             {
+                                                 return false;
+                                             }
+                                             MessageBox.Query ($"{keyCommandContext.Binding.Scope}", $"Key: {keyCommandContext.Binding.Key}\nCommand: {ctx.Command}", buttons: "Ok");
                                              Application.RequestStop ();
                                              return true;
                                          });