Prepping to combine keybinding classes

This commit is contained in:
Tig
2024-12-06 15:25:23 -07:00
parent 0586c303a7
commit 7360683152
7 changed files with 73 additions and 72 deletions

View File

@@ -92,7 +92,7 @@ public static partial class Application // Initialization (Init/Shutdown)
}
}
AddApplicationKeyBindings ();
AddKeyBindings ();
// Start the process of configuration management.
// Note that we end up calling LoadConfigurationFromAllSources

View File

@@ -45,7 +45,7 @@ public static partial class Application // Keyboard handling
// Invoke any Application-scoped KeyBindings.
// The first view that handles the key will stop the loop.
foreach (KeyValuePair<Key, ApplicationKeyBinding> binding in KeyBindings.Bindings.Where (b => b.Key == key.KeyCode))
foreach (KeyValuePair<Key, ApplicationKeyBinding> binding in KeyBindings.GetBindings (key))
{
if (binding.Value.Target is { })
{
@@ -155,12 +155,12 @@ public static partial class Application // Keyboard handling
#region Application-scoped KeyBindings
static Application () { AddApplicationKeyBindings (); }
static Application () { AddKeyBindings (); }
/// <summary>Gets the Application-scoped key bindings.</summary>
public static ApplicationKeyBindings KeyBindings { get; internal set; } = new ();
internal static void AddApplicationKeyBindings ()
internal static void AddKeyBindings ()
{
CommandImplementations = new ();
@@ -231,29 +231,30 @@ public static partial class Application // Keyboard handling
return false;
});
KeyBindings.Clear ();
// Resources/config.json overrides
QuitKey = Key.Esc;
NextTabKey = Key.Tab;
PrevTabKey = Key.Tab.WithShift;
NextTabGroupKey = Key.F6;
PrevTabGroupKey = Key.F6.WithShift;
QuitKey = Key.Esc;
ArrangeKey = Key.F5.WithCtrl;
// Need to clear after setting the above to ensure actually clear
// because set_QuitKey etc.. may call Add
KeyBindings.Clear ();
KeyBindings.Add (QuitKey, Command.Quit);
KeyBindings.Add (NextTabKey, Command.NextTabStop);
KeyBindings.Add (PrevTabKey, Command.PreviousTabStop);
KeyBindings.Add (NextTabGroupKey, Command.NextTabGroup);
KeyBindings.Add (PrevTabGroupKey, Command.PreviousTabGroup);
KeyBindings.Add (ArrangeKey, Command.Edit);
KeyBindings.Add (Key.CursorRight, Command.NextTabStop);
KeyBindings.Add (Key.CursorDown, Command.NextTabStop);
KeyBindings.Add (Key.CursorLeft, Command.PreviousTabStop);
KeyBindings.Add (Key.CursorUp, Command.PreviousTabStop);
KeyBindings.Add (NextTabKey, Command.NextTabStop);
KeyBindings.Add (PrevTabKey, Command.PreviousTabStop);
KeyBindings.Add (NextTabGroupKey, Command.NextTabGroup);
KeyBindings.Add (PrevTabGroupKey, Command.PreviousTabGroup);
KeyBindings.Add (ArrangeKey, Command.Edit);
// TODO: Refresh Key should be configurable
KeyBindings.Add (Key.F5, Command.Refresh);
@@ -265,46 +266,32 @@ public static partial class Application // Keyboard handling
}
}
/// <summary>
/// Gets the list of <see cref="ApplicationKeyBinding"/>s.
/// </summary>
/// <remarks>
/// This is an internal method used by the <see cref="View"/> class to add Application key bindings.
/// </remarks>
/// <returns>The list of Views that have Application-scoped key bindings.</returns>
internal static List<ApplicationKeyBinding> GetViewKeyBindings ()
{
// Get the list of views that do not have Application-scoped key bindings
return KeyBindings.Bindings
.Where (kv => kv.Value.Target is {})
.Select (kv => kv.Value)
.Distinct ()
.ToList ();
}
private static void ReplaceKey (Key oldKey, Key newKey)
{
if (KeyBindings.Bindings.Count == 0)
{
return;
}
KeyBindings.ReplaceKey (oldKey, newKey);
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);
}
}
//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);
// }
//}
}

View File

@@ -214,7 +214,8 @@ public static partial class Application
ClearScreenNextIteration = false;
AddApplicationKeyBindings ();
KeyBindings.Clear ();
AddKeyBindings ();
// Reset synchronization context to allow the user to run async/await,
// as the main loop has been ended, the synchronization context from

View File

@@ -82,9 +82,7 @@ public class ApplicationKeyBindings
Add (key, binding);
}
// TODO: This should not be public!
/// <summary>The collection of <see cref="ApplicationKeyBinding"/> objects.</summary>
public Dictionary<Key, ApplicationKeyBinding> Bindings { get; } = new (new KeyEqualityComparer ());
private Dictionary<Key, ApplicationKeyBinding> Bindings { get; } = new (new KeyEqualityComparer ());
/// <summary>
/// Gets the keys that are bound.
@@ -95,6 +93,16 @@ public class ApplicationKeyBindings
return Bindings.Keys;
}
/// <summary>
/// Gets the bindings bound to <paramref name="key"/>.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public IEnumerable<KeyValuePair<Key, ApplicationKeyBinding>> GetBindings (Key key)
{
return Bindings.Where (b => b.Key == key.KeyCode);
}
/// <summary>Removes all <see cref="ApplicationKeyBinding"/> objects from the collection.</summary>
public void Clear () { Bindings.Clear (); }
@@ -193,25 +201,33 @@ public class ApplicationKeyBindings
throw new InvalidOperationException ($"Key {key} is not bound.");
}
/// <summary>Replaces a key combination already bound to a set of <see cref="Command"/>s.</summary>
/// <remarks></remarks>
/// <summary>Replaces a key combination bound to a set of <see cref="Command"/>s.</summary>
/// <remarks>If <paramref name="oldKey"/> is not bound, this method has the same effect as <see cref="Add(Terminal.Gui.Key,Terminal.Gui.ApplicationKeyBinding)"/>.</remarks>
/// <param name="oldKey">The key to be replaced.</param>
/// <param name="newKey">The new key to be used. If <see cref="Key.Empty"/> no action will be taken.</param>
/// <param name="newKey">The new key to be used. If <see cref="Key.Empty"/> this method has the same effect as <see cref="Remove"/>.</param>
public void ReplaceKey (Key oldKey, Key newKey)
{
if (!TryGet (oldKey, out ApplicationKeyBinding _))
{
throw new InvalidOperationException ($"Key {oldKey} is not bound.");
}
if (!newKey.IsValid)
{
throw new InvalidOperationException ($"Key {newKey} is is not valid.");
}
ApplicationKeyBinding binding = Bindings [oldKey];
Remove (oldKey);
Add (newKey, binding);
if (newKey == Key.Empty)
{
Remove (oldKey);
return;
}
if (TryGet (oldKey, out ApplicationKeyBinding binding))
{
Remove (oldKey);
Add (newKey, binding);
}
else
{
Add (newKey, binding);
}
}
/// <summary>Gets the commands bound with the specified Key.</summary>

View File

@@ -109,7 +109,7 @@ public sealed class ContextMenu : IDisposable
_menuBar?.Dispose ();
_menuBar = null;
IsShow = false;
`
if (_container is { })
{
_container.Closing -= Container_Closing;

View File

@@ -317,9 +317,6 @@ public class ApplicationTests
Assert.Empty (Application.TopLevels);
Assert.Empty (Application._cachedViewsUnderMouse);
// Keyboard
Assert.Empty (Application.GetViewKeyBindings ());
// Mouse
Assert.Null (Application._lastMousePosition);
@@ -555,7 +552,7 @@ public class ApplicationTests
Assert.Equal (Key.Q.WithCtrl, Application.QuitKey);
Assert.Contains (Key.Q.WithCtrl, Application.KeyBindings.Bindings);
Assert.NotEmpty (Application.KeyBindings.GetBindings (Key.Q.WithCtrl));
Application.Shutdown ();
Locations = ConfigLocations.Default;

View File

@@ -317,11 +317,11 @@ public class ShortcutTests
shortcut.BindKeyToApplication = true;
Assert.DoesNotContain (Key.A, shortcut.KeyBindings.Bindings.Keys);
Assert.Contains (Key.A, Application.KeyBindings.Bindings.Keys);
Assert.NotEmpty (Application.KeyBindings.GetBindings(Key.A));
shortcut.BindKeyToApplication = false;
Assert.Contains (Key.A, shortcut.KeyBindings.Bindings.Keys);
Assert.DoesNotContain (Key.A, Application.KeyBindings.Bindings.Keys);
Assert.Empty (Application.KeyBindings.GetBindings (Key.A));
}
[Theory]