mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Prepping to combine keybinding classes 2
This commit is contained in:
@@ -54,7 +54,7 @@ public static partial class Application // Keyboard handling
|
||||
return false;
|
||||
}
|
||||
|
||||
bool? handled = binding.Value.Target?.InvokeCommands<ApplicationKeyBinding> (binding.Value.Commands, binding.Value);
|
||||
bool? handled = binding.Value.Target?.InvokeCommands (binding.Value.Commands, binding.Value);
|
||||
|
||||
if (handled != null && (bool)handled)
|
||||
{
|
||||
@@ -83,16 +83,16 @@ public static partial class Application // Keyboard handling
|
||||
|
||||
static bool? InvokeCommand (Command command, Key key, ApplicationKeyBinding appBinding)
|
||||
{
|
||||
if (!CommandImplementations!.ContainsKey (command))
|
||||
if (!_commandImplementations!.ContainsKey (command))
|
||||
{
|
||||
throw new NotSupportedException (
|
||||
@$"A KeyBinding was set up for the command {command} ({key}) but that command is not supported by Application."
|
||||
);
|
||||
}
|
||||
|
||||
if (CommandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
|
||||
if (_commandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
|
||||
{
|
||||
var context = new CommandContext<ApplicationKeyBinding> (command, appBinding); // Create the context here
|
||||
CommandContext<ApplicationKeyBinding> context = new (command, appBinding); // Create the context here
|
||||
|
||||
return implementation (context);
|
||||
}
|
||||
@@ -116,7 +116,8 @@ public static partial class Application // Keyboard handling
|
||||
public static event EventHandler<Key>? KeyDown;
|
||||
|
||||
/// <summary>
|
||||
/// Called when the user releases a key (by the <see cref="IConsoleDriver"/>). Raises the cancelable <see cref="KeyUp"/>
|
||||
/// Called when the user releases a key (by the <see cref="IConsoleDriver"/>). Raises the cancelable
|
||||
/// <see cref="KeyUp"/>
|
||||
/// event
|
||||
/// then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="RaiseKeyDownEvent"/>.
|
||||
/// </summary>
|
||||
@@ -162,7 +163,7 @@ public static partial class Application // Keyboard handling
|
||||
|
||||
internal static void AddKeyBindings ()
|
||||
{
|
||||
CommandImplementations = new ();
|
||||
_commandImplementations.Clear ();
|
||||
|
||||
// Things this view knows how to do
|
||||
AddCommand (
|
||||
@@ -231,7 +232,6 @@ public static partial class Application // Keyboard handling
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Resources/config.json overrides
|
||||
QuitKey = Key.Esc;
|
||||
NextTabKey = Key.Tab;
|
||||
@@ -266,35 +266,6 @@ public static partial class Application // Keyboard handling
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReplaceKey (Key oldKey, Key newKey)
|
||||
{
|
||||
KeyBindings.ReplaceKey (oldKey, newKey);
|
||||
|
||||
//return;
|
||||
//if (KeyBindings.Bindings.Count == 0)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
//if (newKey == Key.Empty)
|
||||
//{
|
||||
// KeyBindings.Remove (oldKey);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// if (KeyBindings.TryGet (oldKey, out ApplicationKeyBinding binding))
|
||||
// {
|
||||
// KeyBindings.Remove (oldKey);
|
||||
// KeyBindings.Add (newKey, binding);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// KeyBindings.Add (newKey, binding);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
#endregion Application-scoped KeyBindings
|
||||
|
||||
/// <summary>
|
||||
@@ -313,11 +284,10 @@ public static partial class Application // Keyboard handling
|
||||
/// </remarks>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="f">The function.</param>
|
||||
private static void AddCommand (Command command, Func<bool?> f) { CommandImplementations! [command] = ctx => f (); }
|
||||
private static void AddCommand (Command command, Func<bool?> f) { _commandImplementations! [command] = ctx => f (); }
|
||||
|
||||
/// <summary>
|
||||
/// Commands for Application.
|
||||
/// </summary>
|
||||
private static Dictionary<Command, View.CommandImplementation>? CommandImplementations { get; set; }
|
||||
|
||||
private static readonly Dictionary<Command, View.CommandImplementation> _commandImplementations = new ();
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public static partial class Application // Navigation stuff
|
||||
{
|
||||
if (_nextTabGroupKey != value)
|
||||
{
|
||||
ReplaceKey (_nextTabGroupKey, value);
|
||||
KeyBindings.ReplaceKey (_nextTabGroupKey, value);
|
||||
_nextTabGroupKey = value;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public static partial class Application // Navigation stuff
|
||||
{
|
||||
if (_nextTabKey != value)
|
||||
{
|
||||
ReplaceKey (_nextTabKey, value);
|
||||
KeyBindings.ReplaceKey (_nextTabKey, value);
|
||||
_nextTabKey = value;
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public static partial class Application // Navigation stuff
|
||||
{
|
||||
if (_prevTabGroupKey != value)
|
||||
{
|
||||
ReplaceKey (_prevTabGroupKey, value);
|
||||
KeyBindings.ReplaceKey (_prevTabGroupKey, value);
|
||||
_prevTabGroupKey = value;
|
||||
}
|
||||
}
|
||||
@@ -78,10 +78,10 @@ public static partial class Application // Navigation stuff
|
||||
{
|
||||
get => _prevTabKey;
|
||||
set
|
||||
{
|
||||
{
|
||||
if (_prevTabKey != value)
|
||||
{
|
||||
ReplaceKey (_prevTabKey, value);
|
||||
KeyBindings.ReplaceKey (_prevTabKey, value);
|
||||
_prevTabKey = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public static partial class Application // Run (Begin, Run, End, Stop)
|
||||
{
|
||||
if (_quitKey != value)
|
||||
{
|
||||
ReplaceKey (_quitKey, value);
|
||||
KeyBindings.ReplaceKey (_quitKey, value);
|
||||
_quitKey = value;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public static partial class Application // Run (Begin, Run, End, Stop)
|
||||
{
|
||||
if (_arrangeKey != value)
|
||||
{
|
||||
ReplaceKey (_arrangeKey, value);
|
||||
KeyBindings.ReplaceKey (_arrangeKey, value);
|
||||
_arrangeKey = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,10 @@ public record struct KeyBinding
|
||||
{
|
||||
/// <summary>Initializes a new instance.</summary>
|
||||
/// <param name="commands">The commands this key binding will invoke.</param>
|
||||
/// <param name="scope">The scope of the <see cref="Commands"/>.</param>
|
||||
/// <param name="context">Arbitrary context that can be associated with this key binding.</param>
|
||||
public KeyBinding (Command [] commands, KeyBindingScope scope, object? context = null)
|
||||
public KeyBinding (Command [] commands, object? context = null)
|
||||
{
|
||||
Commands = commands;
|
||||
Scope = scope;
|
||||
Data = context;
|
||||
}
|
||||
|
||||
@@ -29,10 +27,9 @@ public record struct KeyBinding
|
||||
/// <param name="scope">The scope of the <see cref="Commands"/>.</param>
|
||||
/// <param name="boundView">The view the key binding is bound to.</param>
|
||||
/// <param name="data">Arbitrary data that can be associated with this key binding.</param>
|
||||
public KeyBinding (Command [] commands, KeyBindingScope scope, View? boundView, object? data = null)
|
||||
public KeyBinding (Command [] commands, View? boundView, object? data = null)
|
||||
{
|
||||
Commands = commands;
|
||||
Scope = scope;
|
||||
BoundView = boundView;
|
||||
Data = data;
|
||||
}
|
||||
@@ -40,9 +37,6 @@ public record struct KeyBinding
|
||||
/// <summary>The commands this key binding will invoke.</summary>
|
||||
public Command [] Commands { get; set; }
|
||||
|
||||
/// <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>
|
||||
|
||||
@@ -22,22 +22,5 @@ public enum KeyBindingScope
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <seealso cref="View.KeyBindings"/>
|
||||
Focused = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The key binding is scoped to the View's Superview hierarchy and the bound <see cref="Command"/>s will be invoked
|
||||
/// even when the View does not have
|
||||
/// focus, as
|
||||
/// long as some View up the SuperView hierachy does have focus. This is typically used for <see cref="View.HotKey"/>s.
|
||||
/// <para>
|
||||
/// The View must be visible.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// HotKey-scoped key bindings are only invoked if the key down event was not handled by the focused view or
|
||||
/// any of its subviews.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <seealso cref="View.KeyBindings"/>
|
||||
/// <seealso cref="View.HotKey"/>
|
||||
HotKey = 2
|
||||
Focused = 1
|
||||
}
|
||||
|
||||
@@ -9,12 +9,6 @@ namespace Terminal.Gui;
|
||||
/// <seealso cref="Command"/>
|
||||
public class KeyBindings
|
||||
{
|
||||
///// <summary>
|
||||
///// Initializes a new instance. This constructor is used when the <see cref="KeyBindings"/> are not bound to a
|
||||
///// <see cref="View"/>. This is used for Application.KeyBindings and unit tests.
|
||||
///// </summary>
|
||||
//public KeyBindings () { }
|
||||
|
||||
/// <summary>Initializes a new instance bound to <paramref name="boundView"/>.</summary>
|
||||
public KeyBindings (View? boundView) { BoundView = boundView; }
|
||||
|
||||
@@ -43,43 +37,6 @@ public class KeyBindings
|
||||
Bindings.Add (new (key), binding);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Adds a new key combination that will trigger the commands in <paramref name="commands"/>.</para>
|
||||
/// <para>
|
||||
/// If the key is already bound to a different array of <see cref="Command"/>s it will be rebound
|
||||
/// <paramref name="commands"/>.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Commands are only ever applied to the current <see cref="View"/> (i.e. this feature cannot be used to switch
|
||||
/// focus to another view and perform multiple commands there).
|
||||
/// </remarks>
|
||||
/// <param name="key">The key to check.</param>
|
||||
/// <param name="scope">The scope for the command.</param>
|
||||
/// <param name="commands">
|
||||
/// The command to invoked on the <see cref="View"/> when <paramref name="key"/> is pressed. When
|
||||
/// multiple commands are provided,they will be applied in sequence. The bound <paramref name="key"/> strike will be
|
||||
/// consumed if any took effect.
|
||||
/// </param>
|
||||
public void Add (Key key, KeyBindingScope scope, params Command [] commands)
|
||||
{
|
||||
if (key == Key.Empty || !key.IsValid)
|
||||
{
|
||||
throw new ArgumentException (@"Invalid Key", nameof (commands));
|
||||
}
|
||||
|
||||
if (commands.Length == 0)
|
||||
{
|
||||
throw new ArgumentException (@"At least one command must be specified", nameof (commands));
|
||||
}
|
||||
|
||||
if (TryGet (key, out KeyBinding binding))
|
||||
{
|
||||
throw new InvalidOperationException (@$"A key binding for {key} exists ({binding}).");
|
||||
}
|
||||
|
||||
Add (key, new KeyBinding (commands, scope, BoundView));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
@@ -88,7 +45,7 @@ public class KeyBindings
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This is a helper function for <see cref="Add(Key,KeyBinding,View?)"/>. If used for a View (
|
||||
/// <see cref="Target"/> is set), the scope will be set to <see cref="KeyBindingScope.Focused"/>.
|
||||
/// <see cref="BoundView"/> is set), the scope will be set to <see cref="KeyBindingScope.Focused"/>.
|
||||
/// Otherwise, it will be set to <see cref="KeyBindingScope.Application"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
@@ -108,7 +65,7 @@ public class KeyBindings
|
||||
/// </param>
|
||||
public void Add (Key key, params Command [] commands)
|
||||
{
|
||||
Add (key, KeyBindingScope.Focused, commands);
|
||||
Add (key, new KeyBinding(commands));
|
||||
}
|
||||
|
||||
// TODO: Add a dictionary comparer that ignores Scope
|
||||
@@ -166,20 +123,6 @@ public class KeyBindings
|
||||
throw new InvalidOperationException ($"Key {key} is not bound.");
|
||||
}
|
||||
|
||||
/// <summary>Gets the <see cref="KeyBinding"/> for the specified <see cref="Key"/>.</summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="scope"></param>
|
||||
/// <returns></returns>
|
||||
public KeyBinding Get (Key key, KeyBindingScope scope)
|
||||
{
|
||||
if (TryGet (key, scope, out KeyBinding binding))
|
||||
{
|
||||
return binding;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException ($"Key {key}/{scope} is not bound.");
|
||||
}
|
||||
|
||||
/// <summary>Gets the array of <see cref="Command"/>s bound to <paramref name="key"/> if it exists.</summary>
|
||||
/// <param name="key">The key to check.</param>
|
||||
/// <returns>
|
||||
@@ -238,7 +181,7 @@ public class KeyBindings
|
||||
if (TryGet (key, out KeyBinding binding))
|
||||
{
|
||||
Remove (key);
|
||||
Add (key, binding.Scope, newCommands);
|
||||
Add (key, newCommands);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -277,12 +220,7 @@ public class KeyBindings
|
||||
/// <returns><see langword="true"/> if the Key is bound; otherwise <see langword="false"/>.</returns>
|
||||
public bool TryGet (Key key, out KeyBinding binding)
|
||||
{
|
||||
//if (BoundView is null)
|
||||
//{
|
||||
// throw new InvalidOperationException ("KeyBindings must be bound to a View to use this method.");
|
||||
//}
|
||||
|
||||
binding = new (Array.Empty<Command> (), KeyBindingScope.Disabled, null);
|
||||
binding = new ([], null);
|
||||
|
||||
if (key.IsValid)
|
||||
{
|
||||
@@ -291,42 +229,4 @@ public class KeyBindings
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Gets the commands bound with the specified Key that are scoped to a particular scope.</summary>
|
||||
/// <remarks></remarks>
|
||||
/// <param name="key">The key to check.</param>
|
||||
/// <param name="scope">the scope to filter on</param>
|
||||
/// <param name="binding">
|
||||
/// When this method returns, contains the commands bound with the specified Key, if the Key is
|
||||
/// found; otherwise, null. This parameter is passed uninitialized.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if the Key is bound; otherwise <see langword="false"/>.</returns>
|
||||
public bool TryGet (Key key, KeyBindingScope scope, out KeyBinding binding)
|
||||
{
|
||||
if (!key.IsValid)
|
||||
{
|
||||
//if (BoundView is null)
|
||||
//{
|
||||
// throw new InvalidOperationException ("KeyBindings must be bound to a View to use this method.");
|
||||
//}
|
||||
|
||||
binding = new (Array.Empty<Command> (), KeyBindingScope.Disabled, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Bindings.TryGetValue (key, out binding))
|
||||
{
|
||||
if (scope.HasFlag (binding.Scope))
|
||||
{
|
||||
binding.Key = key;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
binding = new (Array.Empty<Command> (), KeyBindingScope.Disabled, null);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,15 +1390,15 @@ public class Border : Adornment
|
||||
return true; // Always eat
|
||||
});
|
||||
|
||||
KeyBindings.Add (Key.Esc, KeyBindingScope.HotKey, Command.Quit);
|
||||
KeyBindings.Add (Application.ArrangeKey, KeyBindingScope.HotKey, Command.Quit);
|
||||
KeyBindings.Add (Key.CursorUp, KeyBindingScope.HotKey, Command.Up);
|
||||
KeyBindings.Add (Key.CursorDown, KeyBindingScope.HotKey, Command.Down);
|
||||
KeyBindings.Add (Key.CursorLeft, KeyBindingScope.HotKey, Command.Left);
|
||||
KeyBindings.Add (Key.CursorRight, KeyBindingScope.HotKey, Command.Right);
|
||||
HotKeyBindings.Add (Key.Esc, Command.Quit);
|
||||
HotKeyBindings.Add (Application.ArrangeKey, Command.Quit);
|
||||
HotKeyBindings.Add (Key.CursorUp, Command.Up);
|
||||
HotKeyBindings.Add (Key.CursorDown, Command.Down);
|
||||
HotKeyBindings.Add (Key.CursorLeft, Command.Left);
|
||||
HotKeyBindings.Add (Key.CursorRight, Command.Right);
|
||||
|
||||
KeyBindings.Add (Key.Tab, KeyBindingScope.HotKey, Command.Tab);
|
||||
KeyBindings.Add (Key.Tab.WithShift, KeyBindingScope.HotKey, Command.BackTab);
|
||||
HotKeyBindings.Add (Key.Tab, Command.Tab);
|
||||
HotKeyBindings.Add (Key.Tab.WithShift, Command.BackTab);
|
||||
}
|
||||
|
||||
private void ApplicationOnMouseEvent (object? sender, MouseEventArgs e)
|
||||
@@ -1472,7 +1472,7 @@ public class Border : Adornment
|
||||
_bottomSizeButton = null;
|
||||
}
|
||||
|
||||
KeyBindings.Clear ();
|
||||
HotKeyBindings.Clear ();
|
||||
|
||||
if (CanFocus)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Terminal.Gui;
|
||||
|
||||
public partial class View // Command APIs
|
||||
{
|
||||
private Dictionary<Command, CommandImplementation> CommandImplementations { get; } = new ();
|
||||
private readonly Dictionary<Command, CommandImplementation> _commandImplementations = new ();
|
||||
|
||||
#region Default Implementation
|
||||
|
||||
@@ -95,7 +95,7 @@ public partial class View // Command APIs
|
||||
|
||||
if (isDefaultView != this && isDefaultView is Button { IsDefault: true } button)
|
||||
{
|
||||
bool? handled = isDefaultView.InvokeCommand<KeyBinding> (Command.Accept, new ([Command.Accept], 0, null, this));
|
||||
bool? handled = isDefaultView.InvokeCommand<KeyBinding> (Command.Accept, new ([Command.Accept], null, this));
|
||||
if (handled == true)
|
||||
{
|
||||
return true;
|
||||
@@ -104,7 +104,7 @@ public partial class View // Command APIs
|
||||
|
||||
if (SuperView is { })
|
||||
{
|
||||
return SuperView?.InvokeCommand<KeyBinding> (Command.Accept, new ([Command.Accept], 0, null, this)) is true;
|
||||
return SuperView?.InvokeCommand<KeyBinding> (Command.Accept, new ([Command.Accept], null, this)) is true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ public partial class View // Command APIs
|
||||
/// </remarks>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="impl">The delegate.</param>
|
||||
protected void AddCommand (Command command, CommandImplementation impl) { CommandImplementations [command] = impl; }
|
||||
protected void AddCommand (Command command, CommandImplementation impl) { _commandImplementations [command] = impl; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
@@ -270,11 +270,11 @@ public partial class View // Command APIs
|
||||
/// </remarks>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="impl">The delegate.</param>
|
||||
protected void AddCommand (Command command, Func<bool?> impl) { CommandImplementations [command] = ctx => impl (); }
|
||||
protected void AddCommand (Command command, Func<bool?> impl) { _commandImplementations [command] = ctx => impl (); }
|
||||
|
||||
/// <summary>Returns all commands that are supported by this <see cref="View"/>.</summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Command> GetSupportedCommands () { return CommandImplementations.Keys; }
|
||||
public IEnumerable<Command> GetSupportedCommands () { return _commandImplementations.Keys; }
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified commands.
|
||||
@@ -292,7 +292,7 @@ public partial class View // Command APIs
|
||||
|
||||
foreach (Command command in commands)
|
||||
{
|
||||
if (!CommandImplementations.ContainsKey (command))
|
||||
if (!_commandImplementations.ContainsKey (command))
|
||||
{
|
||||
throw new NotSupportedException (
|
||||
@$"A Binding was set up for the command {command} ({binding}) but that command is not supported by this View ({GetType ().Name})"
|
||||
@@ -327,7 +327,7 @@ public partial class View // Command APIs
|
||||
/// </returns>
|
||||
public bool? InvokeCommand<TBindingType> (Command command, TBindingType binding)
|
||||
{
|
||||
if (CommandImplementations.TryGetValue (command, out CommandImplementation? implementation))
|
||||
if (_commandImplementations.TryGetValue (command, out CommandImplementation? implementation))
|
||||
{
|
||||
return implementation (new CommandContext<TBindingType> ()
|
||||
{
|
||||
@@ -350,7 +350,7 @@ public partial class View // Command APIs
|
||||
/// </returns>
|
||||
public bool? InvokeCommand (Command command)
|
||||
{
|
||||
if (CommandImplementations.TryGetValue (command, out CommandImplementation? implementation))
|
||||
if (_commandImplementations.TryGetValue (command, out CommandImplementation? implementation))
|
||||
{
|
||||
return implementation (null);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ public partial class View // Keyboard APIs
|
||||
KeyBindings.Add (Key.Space, Command.Select);
|
||||
KeyBindings.Add (Key.Enter, Command.Accept);
|
||||
|
||||
HotKeyBindings = new (this);
|
||||
|
||||
// Note, setting HotKey will bind HotKey to Command.HotKey
|
||||
HotKeySpecifier = (Rune)'_';
|
||||
TitleTextFormatter.HotKeyChanged += TitleTextFormatter_HotKeyChanged;
|
||||
@@ -153,50 +155,54 @@ public partial class View // Keyboard APIs
|
||||
}
|
||||
|
||||
// Remove base version
|
||||
if (KeyBindings.TryGet (prevHotKey, out _))
|
||||
if (HotKeyBindings.TryGet (prevHotKey, out _))
|
||||
{
|
||||
KeyBindings.Remove (prevHotKey);
|
||||
HotKeyBindings.Remove (prevHotKey);
|
||||
}
|
||||
|
||||
// Remove the Alt version
|
||||
if (KeyBindings.TryGet (prevHotKey.WithAlt, out _))
|
||||
if (HotKeyBindings.TryGet (prevHotKey.WithAlt, out _))
|
||||
{
|
||||
KeyBindings.Remove (prevHotKey.WithAlt);
|
||||
HotKeyBindings.Remove (prevHotKey.WithAlt);
|
||||
}
|
||||
|
||||
if (_hotKey.IsKeyCodeAtoZ)
|
||||
{
|
||||
// Remove the shift version
|
||||
if (KeyBindings.TryGet (prevHotKey.WithShift, out _))
|
||||
if (HotKeyBindings.TryGet (prevHotKey.WithShift, out _))
|
||||
{
|
||||
KeyBindings.Remove (prevHotKey.WithShift);
|
||||
HotKeyBindings.Remove (prevHotKey.WithShift);
|
||||
}
|
||||
|
||||
// Remove alt | shift version
|
||||
if (KeyBindings.TryGet (prevHotKey.WithShift.WithAlt, out _))
|
||||
if (HotKeyBindings.TryGet (prevHotKey.WithShift.WithAlt, out _))
|
||||
{
|
||||
KeyBindings.Remove (prevHotKey.WithShift.WithAlt);
|
||||
HotKeyBindings.Remove (prevHotKey.WithShift.WithAlt);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new
|
||||
if (newKey != Key.Empty)
|
||||
{
|
||||
KeyBinding keyBinding = new ([Command.HotKey], KeyBindingScope.HotKey, context);
|
||||
KeyBinding keyBinding = new ()
|
||||
{
|
||||
Commands = [Command.HotKey],
|
||||
Data = context
|
||||
};
|
||||
|
||||
// Add the base and Alt key
|
||||
KeyBindings.Remove (newKey);
|
||||
KeyBindings.Add (newKey, keyBinding);
|
||||
KeyBindings.Remove (newKey.WithAlt);
|
||||
KeyBindings.Add (newKey.WithAlt, keyBinding);
|
||||
HotKeyBindings.Remove (newKey);
|
||||
HotKeyBindings.Add (newKey, keyBinding);
|
||||
HotKeyBindings.Remove (newKey.WithAlt);
|
||||
HotKeyBindings.Add (newKey.WithAlt, keyBinding);
|
||||
|
||||
// If the Key is A..Z, add ShiftMask and AltMask | ShiftMask
|
||||
if (newKey.IsKeyCodeAtoZ)
|
||||
{
|
||||
KeyBindings.Remove (newKey.WithShift);
|
||||
KeyBindings.Add (newKey.WithShift, keyBinding);
|
||||
KeyBindings.Remove (newKey.WithShift.WithAlt);
|
||||
KeyBindings.Add (newKey.WithShift.WithAlt, keyBinding);
|
||||
HotKeyBindings.Remove (newKey.WithShift);
|
||||
HotKeyBindings.Add (newKey.WithShift, keyBinding);
|
||||
HotKeyBindings.Remove (newKey.WithShift.WithAlt);
|
||||
HotKeyBindings.Add (newKey.WithShift.WithAlt, keyBinding);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,7 +538,7 @@ public partial class View // Keyboard APIs
|
||||
// `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, KeyBindingScope.Focused);
|
||||
bool? handled = InvokeCommandsBoundToFocusedKey (key);
|
||||
|
||||
if (handled is true)
|
||||
{
|
||||
@@ -541,17 +547,17 @@ public partial class View // Keyboard APIs
|
||||
return handled;
|
||||
}
|
||||
|
||||
if (Margin is { } && InvokeCommandsBoundToKeyOnAdornment (Margin, key, KeyBindingScope.Focused, ref handled))
|
||||
if (Margin is { } && InvokeCommandsBoundToKeyOnAdornment (Margin, key, ref handled))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Padding is { } && InvokeCommandsBoundToKeyOnAdornment (Padding, key, KeyBindingScope.Focused, ref handled))
|
||||
if (Padding is { } && InvokeCommandsBoundToKeyOnAdornment (Padding, key, ref handled))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Border is { } && InvokeCommandsBoundToKeyOnAdornment (Border, key, KeyBindingScope.Focused, ref handled))
|
||||
if (Border is { } && InvokeCommandsBoundToKeyOnAdornment (Border, key, ref handled))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -559,7 +565,7 @@ public partial class View // Keyboard APIs
|
||||
return handled;
|
||||
}
|
||||
|
||||
private static bool InvokeCommandsBoundToKeyOnAdornment (Adornment adornment, Key key, KeyBindingScope scope, ref bool? handled)
|
||||
private static bool InvokeCommandsBoundToKeyOnAdornment (Adornment adornment, Key key, ref bool? handled)
|
||||
{
|
||||
bool? adornmentHandled = adornment.InvokeCommandsBoundToKey (key);
|
||||
|
||||
@@ -593,7 +599,7 @@ public partial class View // Keyboard APIs
|
||||
|
||||
internal bool InvokeCommandsBoundToHotKeyOnSubviews (Key key, ref bool? handled, bool invoke = true)
|
||||
{
|
||||
bool? weHandled = InvokeCommandsBoundToKey (key, KeyBindingScope.HotKey);
|
||||
bool? weHandled = InvokeCommandsBoundToHotKey (key);
|
||||
if (weHandled is true)
|
||||
{
|
||||
return true;
|
||||
@@ -634,7 +640,7 @@ public partial class View // Keyboard APIs
|
||||
|
||||
foreach (View subview in Subviews)
|
||||
{
|
||||
if (subview.KeyBindings.TryGet (key, KeyBindingScope.HotKey, out _))
|
||||
if (subview.HotKeyBindings.TryGet (key, out _))
|
||||
{
|
||||
boundView = subview;
|
||||
|
||||
@@ -650,6 +656,46 @@ public partial class View // Keyboard APIs
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the Commands bound to <paramref name="key"/>.
|
||||
/// <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
|
||||
/// </summary>
|
||||
/// <param name="key">The key event passed.</param>
|
||||
/// <returns>
|
||||
/// <see langword="null"/> if no command was invoked; input processing should continue.
|
||||
/// <see langword="false"/> if at least one command was invoked and was not handled (or cancelled); input processing
|
||||
/// should continue.
|
||||
/// <see langword="true"/> if at least one command was invoked and handled (or cancelled); input processing should
|
||||
/// stop.
|
||||
/// </returns>
|
||||
protected bool? InvokeCommandsBoundToFocusedKey (Key key)
|
||||
{
|
||||
if (!KeyBindings.TryGet (key, out KeyBinding binding))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
//if (Application.KeyBindings.TryGet (key, out KeyBinding b))
|
||||
//{
|
||||
// Debug.WriteLine (
|
||||
// $"WARNING: InvokeKeyBindings ({key}) - An Application scope binding exists for this key. The registered view will not invoke Command.");
|
||||
//}
|
||||
|
||||
// TODO: This is a "prototype" debug check. It may be too annoying vs. useful.
|
||||
// Scour the bindings up our View hierarchy
|
||||
// to ensure that the key is not already bound to a different set of commands.
|
||||
if (SuperView?.IsHotKeyBound (key, out View? previouslyBoundView) ?? false)
|
||||
{
|
||||
Debug.WriteLine ($"WARNING: InvokeKeyBindings ({key}) - A subview or peer has bound this Key and will not see it: {previouslyBoundView}.");
|
||||
}
|
||||
|
||||
#endif
|
||||
return InvokeCommands<KeyBinding> (binding.Commands, binding);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the Commands bound to <paramref name="key"/>.
|
||||
/// <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
|
||||
@@ -663,9 +709,9 @@ public partial class View // Keyboard APIs
|
||||
/// <see langword="true"/> if at least one command was invoked and handled (or cancelled); input processing should
|
||||
/// stop.
|
||||
/// </returns>
|
||||
protected bool? InvokeCommandsBoundToKey (Key key, KeyBindingScope scope)
|
||||
protected bool? InvokeCommandsBoundToHotKey (Key key)
|
||||
{
|
||||
if (!KeyBindings.TryGet (key, scope, out KeyBinding binding))
|
||||
if (!HotKeyBindings.TryGet (key, out KeyBinding binding))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,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<KeyBinding> (Command.HotKey, new KeyBinding ([Command.HotKey], KeyBindingScope.HotKey, this, null)) == true;
|
||||
e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new KeyBinding ([Command.HotKey], this, data: null)) == true;
|
||||
}
|
||||
|
||||
private void Button_TitleChanged (object sender, EventArgs<string> e)
|
||||
|
||||
@@ -25,7 +25,7 @@ public class FrameView : View
|
||||
private void FrameView_MouseClick (object sender, MouseEventArgs e)
|
||||
{
|
||||
// base sets focus on HotKey
|
||||
e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new ([Command.HotKey], KeyBindingScope.Focused, null, this)) == true;
|
||||
e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new ([Command.HotKey], this, this)) == true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public class Label : View, IDesignable
|
||||
{
|
||||
if (!CanFocus)
|
||||
{
|
||||
e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new ([Command.HotKey], KeyBindingScope.HotKey, this, this)) == true;
|
||||
e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new ([Command.HotKey], this, data: this)) == true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,8 +171,8 @@ public class ListView : View, IDesignable
|
||||
KeyBindings.Add (Key.Space.WithShift, [Command.Select, Command.Down]);
|
||||
|
||||
// Use the form of Add that lets us pass context to the handler
|
||||
KeyBindings.Add (Key.A.WithCtrl, new KeyBinding ([Command.SelectAll], KeyBindingScope.Focused, true));
|
||||
KeyBindings.Add (Key.U.WithCtrl, new KeyBinding ([Command.SelectAll], KeyBindingScope.Focused, false));
|
||||
KeyBindings.Add (Key.A.WithCtrl, new KeyBinding ([Command.SelectAll], true));
|
||||
KeyBindings.Add (Key.U.WithCtrl, new KeyBinding ([Command.SelectAll], false));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -130,7 +130,7 @@ internal sealed class Menu : View
|
||||
|
||||
if (menuItem.ShortcutKey != Key.Empty)
|
||||
{
|
||||
KeyBinding keyBinding = new ([Command.Select], KeyBindingScope.HotKey, menuItem);
|
||||
KeyBinding keyBinding = new ([Command.Select], this, data: menuItem);
|
||||
|
||||
// Remove an existent ShortcutKey
|
||||
menuItem._menuBar.KeyBindings.Remove (menuItem.ShortcutKey!);
|
||||
@@ -251,7 +251,7 @@ internal sealed class Menu : View
|
||||
{
|
||||
// We didn't handle the key, pass it on to host
|
||||
bool? handled = null;
|
||||
return _host.InvokeCommandsBoundToHotKeyOnSubviews (keyEvent, ref handled, true ) == true;
|
||||
return _host.InvokeCommandsBoundToHotKeyOnSubviews (keyEvent, ref handled, true) == true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseEvent (MouseEventArgs me)
|
||||
@@ -480,14 +480,14 @@ internal sealed class Menu : View
|
||||
|
||||
foreach (MenuItem menuItem in menuItems)
|
||||
{
|
||||
KeyBinding keyBinding = new ([Command.Toggle], KeyBindingScope.HotKey, menuItem);
|
||||
KeyBinding keyBinding = new ([Command.Toggle], this, data: menuItem);
|
||||
|
||||
if (menuItem.HotKey != Key.Empty)
|
||||
{
|
||||
KeyBindings.Remove (menuItem.HotKey!);
|
||||
KeyBindings.Add (menuItem.HotKey!, keyBinding);
|
||||
KeyBindings.Remove (menuItem.HotKey!.WithAlt);
|
||||
KeyBindings.Add (menuItem.HotKey.WithAlt, keyBinding);
|
||||
HotKeyBindings.Remove (menuItem.HotKey!);
|
||||
HotKeyBindings.Add (menuItem.HotKey!, keyBinding);
|
||||
HotKeyBindings.Remove (menuItem.HotKey!.WithAlt);
|
||||
HotKeyBindings.Add (menuItem.HotKey.WithAlt, keyBinding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,8 +162,8 @@ public class MenuBar : View, IDesignable
|
||||
KeyBindings.Add (Key.Esc, Command.Cancel);
|
||||
KeyBindings.Add (Key.CursorDown, Command.Accept);
|
||||
|
||||
KeyBinding keyBinding = new ([Command.Toggle], KeyBindingScope.HotKey, -1); // -1 indicates Key was used
|
||||
KeyBindings.Add (Key, keyBinding);
|
||||
KeyBinding keyBinding = new ([Command.Toggle], this, data: -1); // -1 indicates Key was used
|
||||
HotKeyBindings.Add (Key, keyBinding);
|
||||
|
||||
// TODO: Why do we have two keybindings for opening the menu? Ctrl-Space and Key?
|
||||
KeyBindings.Add (Key.Space.WithCtrl, keyBinding);
|
||||
@@ -204,21 +204,21 @@ public class MenuBar : View, IDesignable
|
||||
|
||||
if (menuBarItem.HotKey != Key.Empty)
|
||||
{
|
||||
KeyBindings.Remove (menuBarItem.HotKey!);
|
||||
KeyBinding keyBinding = new ([Command.Toggle], KeyBindingScope.Focused, menuBarItem);
|
||||
KeyBindings.Add (menuBarItem.HotKey!, keyBinding);
|
||||
KeyBindings.Remove (menuBarItem.HotKey!.WithAlt);
|
||||
keyBinding = new ([Command.Toggle], KeyBindingScope.HotKey, menuBarItem);
|
||||
KeyBindings.Add (menuBarItem.HotKey.WithAlt, keyBinding);
|
||||
HotKeyBindings.Remove (menuBarItem.HotKey!);
|
||||
KeyBinding keyBinding = new ([Command.Toggle], this, menuBarItem);
|
||||
HotKeyBindings.Add (menuBarItem.HotKey!, keyBinding);
|
||||
HotKeyBindings.Remove (menuBarItem.HotKey!.WithAlt);
|
||||
keyBinding = new ([Command.Toggle], this, data: menuBarItem);
|
||||
HotKeyBindings.Add (menuBarItem.HotKey.WithAlt, keyBinding);
|
||||
}
|
||||
|
||||
if (menuBarItem.ShortcutKey != Key.Empty)
|
||||
{
|
||||
// Technically this will never run because MenuBarItems don't have shortcuts
|
||||
// unless the IsTopLevel is true
|
||||
KeyBindings.Remove (menuBarItem.ShortcutKey!);
|
||||
KeyBinding keyBinding = new ([Command.Select], KeyBindingScope.HotKey, menuBarItem);
|
||||
KeyBindings.Add (menuBarItem.ShortcutKey!, keyBinding);
|
||||
HotKeyBindings.Remove (menuBarItem.ShortcutKey!);
|
||||
KeyBinding keyBinding = new ([Command.Select], this, data: menuBarItem);
|
||||
HotKeyBindings.Add (menuBarItem.ShortcutKey!, keyBinding);
|
||||
}
|
||||
|
||||
menuBarItem.AddShortcutKeyBindings (this);
|
||||
@@ -1310,9 +1310,9 @@ public class MenuBar : View, IDesignable
|
||||
return;
|
||||
}
|
||||
|
||||
KeyBindings.Remove (_key);
|
||||
KeyBinding keyBinding = new ([Command.Toggle], KeyBindingScope.HotKey, -1); // -1 indicates Key was used
|
||||
KeyBindings.Add (value, keyBinding);
|
||||
HotKeyBindings.Remove (_key);
|
||||
KeyBinding keyBinding = new ([Command.Toggle], this, data: -1); // -1 indicates Key was used
|
||||
HotKeyBindings.Add (value, keyBinding);
|
||||
_key = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ public class MenuBarItem : MenuItem
|
||||
if (_menuBar.Menus [index].HotKey != Key.Empty)
|
||||
{
|
||||
// Remove an existent HotKey
|
||||
_menuBar.KeyBindings.Remove (HotKey!.WithAlt);
|
||||
_menuBar.HotKeyBindings.Remove (HotKey!.WithAlt);
|
||||
}
|
||||
|
||||
_menuBar.Menus [index] = null!;
|
||||
|
||||
@@ -149,11 +149,11 @@ public class MenuItem
|
||||
if (AllowNullChecked)
|
||||
{
|
||||
Checked = previousChecked switch
|
||||
{
|
||||
null => true,
|
||||
true => false,
|
||||
false => null
|
||||
};
|
||||
{
|
||||
null => true,
|
||||
true => false,
|
||||
false => null
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -242,9 +242,9 @@ public class MenuItem
|
||||
}
|
||||
else if (nextIsHot)
|
||||
{
|
||||
HotKey = char.ToLower (x);
|
||||
HotKey = char.ToLower (x);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ public class MenuItem
|
||||
|
||||
if (ShortcutKey != Key.Empty)
|
||||
{
|
||||
KeyBinding keyBinding = new ([Command.Select], KeyBindingScope.HotKey, this);
|
||||
KeyBinding keyBinding = new ([Command.Select], null, data: this);
|
||||
// Remove an existent ShortcutKey
|
||||
_menuBar.KeyBindings.Remove (ShortcutKey!);
|
||||
_menuBar.KeyBindings.Add (ShortcutKey!, keyBinding);
|
||||
@@ -314,7 +314,7 @@ public class MenuItem
|
||||
|
||||
if (index > -1)
|
||||
{
|
||||
_menuBar.KeyBindings.Remove (oldKey.WithAlt);
|
||||
_menuBar.HotKeyBindings.Remove (oldKey.WithAlt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,9 +324,9 @@ public class MenuItem
|
||||
|
||||
if (index > -1)
|
||||
{
|
||||
_menuBar.KeyBindings.Remove (HotKey!.WithAlt);
|
||||
KeyBinding keyBinding = new ([Command.Toggle], KeyBindingScope.HotKey, this);
|
||||
_menuBar.KeyBindings.Add (HotKey.WithAlt, keyBinding);
|
||||
_menuBar.HotKeyBindings.Remove (HotKey!.WithAlt);
|
||||
KeyBinding keyBinding = new ([Command.Toggle], null, data: this);
|
||||
_menuBar.HotKeyBindings.Add (HotKey.WithAlt, keyBinding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ public class RadioGroup : View, IDesignable, IOrientation
|
||||
if (c > -1)
|
||||
{
|
||||
// Just like the user pressing the items' hotkey
|
||||
e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new KeyBinding ([Command.HotKey], KeyBindingScope.HotKey, boundView: this, data: c)) == true;
|
||||
e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new KeyBinding ([Command.HotKey], boundView: this, data: c)) == true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ public class ScrollSlider : View, IOrientation, IDesignable
|
||||
OnScrolled (distance);
|
||||
Scrolled?.Invoke (this, new (in distance));
|
||||
|
||||
RaiseSelecting (new CommandContext<KeyBinding> (Command.Select, new KeyBinding ([Command.Select], KeyBindingScope.Focused, null, distance)));
|
||||
RaiseSelecting (new CommandContext<KeyBinding> (Command.Select, new KeyBinding ([Command.Select], null, distance)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -69,7 +69,7 @@ public class Shortcut : View, IOrientation, IDesignable
|
||||
/// <param name="helpText">The help text to display.</param>
|
||||
public Shortcut (View targetView, Command command, string commandText, string? helpText = null)
|
||||
: this (
|
||||
targetView?.KeyBindings.GetKeyFromCommands (command)!,
|
||||
targetView?.HotKeyBindings.GetKeyFromCommands (command)!,
|
||||
commandText,
|
||||
null,
|
||||
helpText)
|
||||
@@ -499,7 +499,7 @@ public class Shortcut : View, IOrientation, IDesignable
|
||||
e.Context is CommandContext<MouseBinding>)
|
||||
{
|
||||
// Forward command to ourselves
|
||||
InvokeCommand<KeyBinding> (Command.Select, new ([Command.Select], KeyBindingScope.Focused, null, this));
|
||||
InvokeCommand<KeyBinding> (Command.Select, new ([Command.Select], null, this));
|
||||
}
|
||||
|
||||
// BUGBUG: This prevents NumericUpDown on statusbar in HexEditor from working
|
||||
@@ -618,7 +618,7 @@ public class Shortcut : View, IOrientation, IDesignable
|
||||
private bool _bindKeyToApplication = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether <see cref="Key"/> is bound to <see cref="Command"/> via <see cref="View.KeyBindings"/> (as a HotKey) or <see cref="Application.KeyBindings"/>.
|
||||
/// Gets or sets whether <see cref="Key"/> is bound to <see cref="Command"/> via <see cref="View.HotKeyBindings"/> or <see cref="Application.KeyBindings"/>.
|
||||
/// </summary>
|
||||
public bool BindKeyToApplication
|
||||
{
|
||||
@@ -636,7 +636,7 @@ public class Shortcut : View, IOrientation, IDesignable
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyBindings.Remove (Key);
|
||||
HotKeyBindings.Remove (Key);
|
||||
}
|
||||
|
||||
_bindKeyToApplication = value;
|
||||
@@ -716,11 +716,11 @@ public class Shortcut : View, IOrientation, IDesignable
|
||||
{
|
||||
if (oldKey != Key.Empty)
|
||||
{
|
||||
KeyBindings.Remove (oldKey);
|
||||
HotKeyBindings.Remove (oldKey);
|
||||
}
|
||||
|
||||
KeyBindings.Remove (Key);
|
||||
KeyBindings.Add (Key, KeyBindingScope.HotKey, Command.HotKey);
|
||||
HotKeyBindings.Remove (Key);
|
||||
HotKeyBindings.Add (Key, Command.HotKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,7 +699,7 @@ public class Editor : Scenario
|
||||
Height = 11;
|
||||
Arrangement = ViewArrangement.Movable;
|
||||
|
||||
KeyBindings.Add (Key.Esc, KeyBindingScope.Focused, Command.Cancel);
|
||||
KeyBindings.Add (Key.Esc, Command.Cancel);
|
||||
AddCommand (Command.Cancel, () =>
|
||||
{
|
||||
Visible = false;
|
||||
|
||||
@@ -104,7 +104,7 @@ public sealed class KeyBindings : Scenario
|
||||
|
||||
foreach (var subview in appWindow.Subviews)
|
||||
{
|
||||
foreach (var binding in subview.KeyBindings.Bindings.Where (b => b.Value.Scope == KeyBindingScope.HotKey))
|
||||
foreach (var binding in subview.HotKeyBindings.Bindings)
|
||||
{
|
||||
hotkeyBindings.Add ($"{binding.Key} -> {subview.GetType ().Name} - {binding.Value.Commands [0]}");
|
||||
}
|
||||
@@ -149,7 +149,7 @@ public sealed class KeyBindings : Scenario
|
||||
_focusedBindingsListView.Title = $"_Focused ({focused?.GetType ().Name}) Bindings";
|
||||
|
||||
_focusedBindings.Clear();
|
||||
foreach (var binding in focused?.KeyBindings!.Bindings.Where (b => b.Value.Scope == KeyBindingScope.Focused)!)
|
||||
foreach (var binding in focused?.KeyBindings!.Bindings)
|
||||
{
|
||||
_focusedBindings.Add ($"{binding.Key} -> {binding.Value.Commands [0]}");
|
||||
}
|
||||
@@ -180,7 +180,7 @@ public class KeyBindingsDemo : View
|
||||
return true;
|
||||
});
|
||||
|
||||
KeyBindings.Add (Key.F2, KeyBindingScope.Focused, Command.Save);
|
||||
KeyBindings.Add (Key.F2, Command.Save);
|
||||
KeyBindings.Add (Key.F3, Command.New); // same as specifying KeyBindingScope.Focused
|
||||
Application.KeyBindings.Add (Key.F4, this, Command.New);
|
||||
|
||||
@@ -190,7 +190,7 @@ public class KeyBindingsDemo : View
|
||||
{
|
||||
return false;
|
||||
}
|
||||
MessageBox.Query ($"{keyCommandContext.Binding.Scope}", $"Key: {keyCommandContext.Binding.Key}\nCommand: {ctx.Command}", buttons: "Ok");
|
||||
MessageBox.Query ($"{keyCommandContext.Binding}", $"Key: {keyCommandContext.Binding.Key}\nCommand: {ctx.Command}", buttons: "Ok");
|
||||
Application.RequestStop ();
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ public class KeyBindingsTests ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new View ());
|
||||
List<Command> commands = new ();
|
||||
Assert.Throws<ArgumentException> (() => keyBindings.Add (Key.Empty, KeyBindingScope.HotKey, Command.Accept));
|
||||
Assert.Throws<ArgumentException> (() => keyBindings.Add (Key.Empty, Command.Accept));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -34,7 +34,7 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void Add_No_Commands_Throws ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
List<Command> commands = new ();
|
||||
Assert.Throws<ArgumentException> (() => keyBindings.Add (Key.A, commands.ToArray ()));
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void Add_Single_Adds ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
Command [] resultCommands = keyBindings.GetCommands (Key.A);
|
||||
Assert.Contains (Command.HotKey, resultCommands);
|
||||
@@ -58,29 +58,29 @@ public class KeyBindingsTests ()
|
||||
public void Add_With_Throws_If_Exists ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new View ());
|
||||
keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.HotKey);
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.Accept));
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, Command.Accept));
|
||||
|
||||
Command [] resultCommands = keyBindings.GetCommands (Key.A);
|
||||
Assert.Contains (Command.HotKey, resultCommands);
|
||||
|
||||
keyBindings = new (new View ());
|
||||
keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.HotKey);
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.Accept));
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, Command.Accept));
|
||||
|
||||
resultCommands = keyBindings.GetCommands (Key.A);
|
||||
Assert.Contains (Command.HotKey, resultCommands);
|
||||
|
||||
keyBindings = new (new View ());
|
||||
keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.HotKey);
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.Accept));
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, Command.Accept));
|
||||
|
||||
resultCommands = keyBindings.GetCommands (Key.A);
|
||||
Assert.Contains (Command.HotKey, resultCommands);
|
||||
|
||||
keyBindings = new (new View ());
|
||||
keyBindings.Add (Key.A, new KeyBinding (new [] { Command.HotKey }, KeyBindingScope.HotKey));
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, new KeyBinding (new [] { Command.Accept }, KeyBindingScope.HotKey)));
|
||||
keyBindings.Add (Key.A, new KeyBinding (new [] { Command.HotKey }));
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, new KeyBinding (new [] { Command.Accept })));
|
||||
|
||||
resultCommands = keyBindings.GetCommands (Key.A);
|
||||
Assert.Contains (Command.HotKey, resultCommands);
|
||||
@@ -102,7 +102,7 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void Defaults ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Assert.Empty (keyBindings.Bindings);
|
||||
Assert.Null (keyBindings.GetKeyFromCommands (Command.Accept));
|
||||
Assert.NotNull (keyBindings.BoundView);
|
||||
@@ -111,7 +111,7 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void Get_Binding_Not_Found_Throws ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Get (Key.A));
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.Get (Key.B));
|
||||
}
|
||||
@@ -128,7 +128,7 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void GetCommands_WithCommands_ReturnsCommands ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
Command [] resultCommands = keyBindings.GetCommands (Key.A);
|
||||
Assert.Contains (Command.HotKey, resultCommands);
|
||||
@@ -139,8 +139,8 @@ public class KeyBindingsTests ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Command [] commands = { Command.Right, Command.Left };
|
||||
keyBindings.Add (Key.A,commands);
|
||||
keyBindings.Add (Key.B,commands);
|
||||
keyBindings.Add (Key.A, commands);
|
||||
keyBindings.Add (Key.B, commands);
|
||||
Command [] resultCommands = keyBindings.GetCommands (Key.A);
|
||||
Assert.Contains (Command.Right, resultCommands);
|
||||
Assert.Contains (Command.Left, resultCommands);
|
||||
@@ -152,7 +152,7 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void GetCommands_WithMultipleCommands_ReturnsCommands ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Command [] commands = { Command.Right, Command.Left };
|
||||
keyBindings.Add (Key.A, commands);
|
||||
Command [] resultCommands = keyBindings.GetCommands (Key.A);
|
||||
@@ -163,12 +163,12 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void GetKeyFromCommands_MultipleCommands ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Command [] commands1 = { Command.Right, Command.Left };
|
||||
keyBindings.Add (Key.A, commands1);
|
||||
|
||||
Command [] commands2 = { Command.Up, Command.Down };
|
||||
keyBindings.Add (Key.B,commands2);
|
||||
keyBindings.Add (Key.B, commands2);
|
||||
|
||||
Key key = keyBindings.GetKeyFromCommands (commands1);
|
||||
Assert.Equal (Key.A, key);
|
||||
@@ -180,7 +180,7 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void GetKeyFromCommands_OneCommand ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, Command.Right);
|
||||
|
||||
Key key = keyBindings.GetKeyFromCommands (Command.Right);
|
||||
@@ -191,14 +191,14 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void GetKeyFromCommands_Unknown_Returns_Key_Empty ()
|
||||
{
|
||||
var keyBindings = new KeyBindings(new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Assert.Null (keyBindings.GetKeyFromCommands (Command.Accept));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetKeyFromCommands_WithCommands_ReturnsKey ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
Key resultKey = keyBindings.GetKeyFromCommands (Command.HotKey);
|
||||
Assert.Equal (Key.A, resultKey);
|
||||
@@ -208,10 +208,10 @@ public class KeyBindingsTests ()
|
||||
public void ReplaceKey_Replaces ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.HotKey);
|
||||
keyBindings.Add (Key.B, KeyBindingScope.Focused, Command.HotKey);
|
||||
keyBindings.Add (Key.C, KeyBindingScope.Focused, Command.HotKey);
|
||||
keyBindings.Add (Key.D, KeyBindingScope.Focused, Command.HotKey);
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
keyBindings.Add (Key.B, Command.HotKey);
|
||||
keyBindings.Add (Key.C, Command.HotKey);
|
||||
keyBindings.Add (Key.D, Command.HotKey);
|
||||
|
||||
keyBindings.ReplaceKey (Key.A, Key.E);
|
||||
Assert.Empty (keyBindings.GetCommands (Key.A));
|
||||
@@ -234,8 +234,8 @@ public class KeyBindingsTests ()
|
||||
public void ReplaceKey_Replaces_Leaves_Old_Binding ()
|
||||
{
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.Accept);
|
||||
keyBindings.Add (Key.B, KeyBindingScope.Focused, Command.HotKey);
|
||||
keyBindings.Add (Key.A, Command.Accept);
|
||||
keyBindings.Add (Key.B, Command.HotKey);
|
||||
|
||||
keyBindings.ReplaceKey (keyBindings.GetKeyFromCommands (Command.Accept), Key.C);
|
||||
Assert.Empty (keyBindings.GetCommands (Key.A));
|
||||
@@ -245,34 +245,33 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void ReplaceKey_Throws_If_DoesNotContain_Old ()
|
||||
{
|
||||
var keyBindings = new KeyBindings(new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.B));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceKey_Throws_If_New_Is_Empty ()
|
||||
{
|
||||
var keyBindings = new KeyBindings(new());
|
||||
keyBindings.Add (Key.A,Command.HotKey);
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.Empty));
|
||||
}
|
||||
|
||||
// Add with scope does the right things
|
||||
[Theory]
|
||||
[InlineData (KeyBindingScope.Focused)]
|
||||
[InlineData (KeyBindingScope.HotKey)]
|
||||
public void Scope_Add_Adds (KeyBindingScope scope)
|
||||
{
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Command [] commands = { Command.Right, Command.Left };
|
||||
|
||||
var key = new Key (Key.A);
|
||||
keyBindings.Add (Key.A, scope, commands);
|
||||
keyBindings.Add (Key.A, commands);
|
||||
KeyBinding binding = keyBindings.Get (key);
|
||||
Assert.Contains (Command.Right, binding.Commands);
|
||||
Assert.Contains (Command.Left, binding.Commands);
|
||||
|
||||
binding = keyBindings.Get (key, scope);
|
||||
binding = keyBindings.Get (key);
|
||||
Assert.Contains (Command.Right, binding.Commands);
|
||||
Assert.Contains (Command.Left, binding.Commands);
|
||||
|
||||
@@ -283,43 +282,41 @@ public class KeyBindingsTests ()
|
||||
|
||||
[Theory]
|
||||
[InlineData (KeyBindingScope.Focused)]
|
||||
[InlineData (KeyBindingScope.HotKey)]
|
||||
public void Scope_Get_Filters (KeyBindingScope scope)
|
||||
{
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Command [] commands = { Command.Right, Command.Left };
|
||||
|
||||
var key = new Key (Key.A);
|
||||
keyBindings.Add (key, scope, commands);
|
||||
keyBindings.Add (key, commands);
|
||||
KeyBinding binding = keyBindings.Get (key);
|
||||
Assert.Contains (Command.Right, binding.Commands);
|
||||
Assert.Contains (Command.Left, binding.Commands);
|
||||
|
||||
binding = keyBindings.Get (key, scope);
|
||||
binding = keyBindings.Get (key);
|
||||
Assert.Contains (Command.Right, binding.Commands);
|
||||
Assert.Contains (Command.Left, binding.Commands);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (KeyBindingScope.Focused)]
|
||||
[InlineData (KeyBindingScope.HotKey)]
|
||||
public void Scope_TryGet_Filters (KeyBindingScope scope)
|
||||
{
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
Command [] commands = { Command.Right, Command.Left };
|
||||
|
||||
var key = new Key (Key.A);
|
||||
keyBindings.Add (key, scope, commands);
|
||||
keyBindings.Add (key, commands);
|
||||
bool success = keyBindings.TryGet (key, out KeyBinding binding);
|
||||
Assert.Contains (Command.Right, binding.Commands);
|
||||
Assert.Contains (Command.Left, binding.Commands);
|
||||
|
||||
success = keyBindings.TryGet (key, scope, out binding);
|
||||
success = keyBindings.TryGet (key, out binding);
|
||||
Assert.Contains (Command.Right, binding.Commands);
|
||||
Assert.Contains (Command.Left, binding.Commands);
|
||||
|
||||
// negative test
|
||||
success = keyBindings.TryGet (key, 0, out binding);
|
||||
success = keyBindings.TryGet (key, out binding);
|
||||
Assert.False (success);
|
||||
|
||||
Command [] resultCommands = keyBindings.GetCommands (key);
|
||||
@@ -331,8 +328,8 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void TryGet_Succeeds ()
|
||||
{
|
||||
var keyBindings = new KeyBindings(new());
|
||||
keyBindings.Add (Key.Q.WithCtrl,Command.HotKey);
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.Q.WithCtrl, Command.HotKey);
|
||||
var key = new Key (Key.Q.WithCtrl);
|
||||
bool result = keyBindings.TryGet (key, out KeyBinding _);
|
||||
Assert.True (result); ;
|
||||
@@ -344,7 +341,7 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void TryGet_Unknown_ReturnsFalse ()
|
||||
{
|
||||
var keyBindings = new KeyBindings(new());
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
bool result = keyBindings.TryGet (Key.A, out KeyBinding _);
|
||||
Assert.False (result);
|
||||
}
|
||||
@@ -352,8 +349,8 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void TryGet_WithCommands_ReturnsTrue ()
|
||||
{
|
||||
var keyBindings = new KeyBindings(new());
|
||||
keyBindings.Add (Key.A,Command.HotKey);
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, Command.HotKey);
|
||||
bool result = keyBindings.TryGet (Key.A, out KeyBinding bindings);
|
||||
Assert.True (result);
|
||||
Assert.Contains (Command.HotKey, bindings.Commands);
|
||||
@@ -362,8 +359,8 @@ public class KeyBindingsTests ()
|
||||
[Fact]
|
||||
public void ReplaceCommands_Replaces ()
|
||||
{
|
||||
var keyBindings = new KeyBindings(new());
|
||||
keyBindings.Add (Key.A,Command.Accept);
|
||||
var keyBindings = new KeyBindings (new ());
|
||||
keyBindings.Add (Key.A, Command.Accept);
|
||||
|
||||
keyBindings.ReplaceCommands (Key.A, Command.Refresh);
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ public class HotKeyTests
|
||||
public void NewKeyDownEvent_Honors_HotKey_KeyBindings_SuperView ()
|
||||
{
|
||||
var view = new View ();
|
||||
view.KeyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.HotKey);
|
||||
view.HotKeyBindings.Add (Key.A, Command.HotKey);
|
||||
bool hotKeyInvoked = false;
|
||||
view.HandlingHotKey += (s, e) => { hotKeyInvoked = true; };
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ public class ViewKeyBindingTests (ITestOutputHelper output)
|
||||
|
||||
Application.KeyBindings.Add (Key.A, this, Command.Save);
|
||||
HotKey = KeyCode.H;
|
||||
KeyBindings.Add (Key.F, KeyBindingScope.Focused, Command.Left);
|
||||
KeyBindings.Add (Key.F, Command.Left);
|
||||
}
|
||||
|
||||
public bool ApplicationCommand { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user