mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
API docs
This commit is contained in:
@@ -255,9 +255,7 @@ public partial class View // Keyboard APIs
|
||||
/// <para>
|
||||
/// If a more focused subview does not handle the key press, this method raises <see cref="OnKeyDown"/>/
|
||||
/// <see cref="KeyDown"/> to allow the
|
||||
/// view to pre-process the key press. If <see cref="OnKeyDown"/>/<see cref="KeyDown"/> is not handled
|
||||
/// <see cref="InvokingKeyBindings"/>/<see cref="OnInvokingKeyBindings"/> will be raised to invoke any key
|
||||
/// bindings.
|
||||
/// view to pre-process the key press. If <see cref="OnKeyDown"/>/<see cref="KeyDown"/> is not handled any commands bound to the key will be invoked.
|
||||
/// Then, only if no key bindings are
|
||||
/// handled, <see cref="OnKeyDownNotHandled"/>/<see cref="KeyDownNotHandled"/> will be raised allowing the view to
|
||||
/// process the key press.
|
||||
@@ -292,8 +290,8 @@ public partial class View // Keyboard APIs
|
||||
|
||||
// During (this is what can be cancelled)
|
||||
|
||||
// TODO: NewKeyDownEvent returns bool. It should be bool? so state of RaiseInvokingKeyBindingsAndInvokeCommands can be reflected up stack
|
||||
if (RaiseInvokingKeyBindingsAndInvokeCommands (key) is true || key.Handled)
|
||||
// TODO: NewKeyDownEvent returns bool. It should be bool? so state of InvokeCommands can be reflected up stack
|
||||
if (InvokeCommandsBoundToKey (key) is true || key.Handled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -336,7 +334,7 @@ public partial class View // Keyboard APIs
|
||||
|
||||
/// <summary>
|
||||
/// Called when the user presses a key, allowing subscribers to pre-process the key down event. Called
|
||||
/// before <see cref="InvokingKeyBindings"/> and <see cref="KeyDownNotHandled"/> are raised. Set
|
||||
/// before key bindings are invoked and <see cref="KeyDownNotHandled"/> is raised. Set
|
||||
/// <see cref="Key.Handled"/>
|
||||
/// to true to
|
||||
/// stop the key from being processed further.
|
||||
@@ -357,7 +355,7 @@ public partial class View // Keyboard APIs
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the user presses a key, allowing subscribers to pre-process the key down event. Called
|
||||
/// before <see cref="InvokingKeyBindings"/> and <see cref="KeyDownNotHandled"/> are raised. Set
|
||||
/// before key bindings are invoked and <see cref="KeyDownNotHandled"/> is raised. Set
|
||||
/// <see cref="Key.Handled"/>
|
||||
/// to true to
|
||||
/// stop the key from being processed further.
|
||||
@@ -508,8 +506,7 @@ public partial class View // Keyboard APIs
|
||||
private Dictionary<Command, CommandImplementation> CommandImplementations { get; } = new ();
|
||||
|
||||
/// <summary>
|
||||
/// INTERNAL API: Raises the <see cref="InvokingKeyBindings"/> event and invokes the commands bound to
|
||||
/// <paramref name="key"/>.
|
||||
/// INTERNAL API: Invokes any commands bound to <paramref name="key"/> on this view, adornments, and subviews.
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns>
|
||||
@@ -517,28 +514,13 @@ public partial class View // Keyboard APIs
|
||||
/// continue.
|
||||
/// <see langword="false"/> if a command was invoked and was not handled (or cancelled); input processing should
|
||||
/// continue.
|
||||
/// <see langword="true"/> if <see cref="InvokingKeyBindings"/> was handled or a command was invoked and handled (or
|
||||
/// <see langword="true"/> if at least one command was invoked and handled (or
|
||||
/// cancelled); input processing should stop.
|
||||
/// </returns>
|
||||
internal bool? RaiseInvokingKeyBindingsAndInvokeCommands (Key key)
|
||||
internal bool? InvokeCommandsBoundToKey (Key key)
|
||||
{
|
||||
KeyBindingScope scope = KeyBindingScope.Focused | KeyBindingScope.HotKey;
|
||||
|
||||
// During
|
||||
if (OnInvokingKeyBindings (key, scope))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
InvokingKeyBindings?.Invoke (this, key);
|
||||
|
||||
if (key.Handled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// After
|
||||
|
||||
// * 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`),
|
||||
@@ -547,29 +529,29 @@ public partial class View // Keyboard APIs
|
||||
// `InvokeKeyBindings` returns `true`. Continue passing the event (return `false` from `OnInvokeKeyBindings`).
|
||||
bool? handled = InvokeCommands (key, scope);
|
||||
|
||||
if (handled is { } && (bool)handled)
|
||||
if (handled is true)
|
||||
{
|
||||
// Stop processing if any key binding handled the key.
|
||||
// DO NOT stop processing if there are no matching key bindings or none of the key bindings handled the key
|
||||
return handled;
|
||||
}
|
||||
|
||||
if (Margin is { } && ProcessAdornmentKeyBindings (Margin, key, scope, ref handled))
|
||||
if (Margin is { } && InvokeCommandsBoundToKeyOnAdornment (Margin, key, scope, ref handled))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Padding is { } && ProcessAdornmentKeyBindings (Padding, key, scope, ref handled))
|
||||
if (Padding is { } && InvokeCommandsBoundToKeyOnAdornment (Padding, key, scope, ref handled))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Border is { } && ProcessAdornmentKeyBindings (Border, key, scope, ref handled))
|
||||
if (Border is { } && InvokeCommandsBoundToKeyOnAdornment (Border, key, scope, ref handled))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ProcessSubViewKeyBindings (key, scope, ref handled))
|
||||
if (InvokeCommandsBoundToKeyOnSubviews (key, scope, ref handled))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -577,32 +559,9 @@ public partial class View // Keyboard APIs
|
||||
return handled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a key is pressed that may be mapped to a key binding. Set <see cref="Key.Handled"/> to true to
|
||||
/// stop the key from being processed by other views.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
|
||||
/// </remarks>
|
||||
/// <param name="key">Contains the details about the key that produced the event.</param>
|
||||
/// <param name="scope">The scope.</param>
|
||||
/// <returns>
|
||||
/// <see langword="false"/> if the event was raised and was not handled (or cancelled); input processing should
|
||||
/// continue.
|
||||
/// <see langword="true"/> if the event was raised and handled (or cancelled); input processing should stop.
|
||||
/// </returns>
|
||||
protected virtual bool OnInvokingKeyBindings (Key key, KeyBindingScope scope) { return false; }
|
||||
|
||||
// TODO: This does not carry KeyBindingScope, but OnInvokingKeyBindings does
|
||||
/// <summary>
|
||||
/// Raised when a key is pressed that may be mapped to a key binding. Set <see cref="Key.Handled"/> to true to
|
||||
/// stop the key from being processed by other views.
|
||||
/// </summary>
|
||||
public event EventHandler<Key>? InvokingKeyBindings;
|
||||
|
||||
private bool ProcessAdornmentKeyBindings (Adornment adornment, Key key, KeyBindingScope scope, ref bool? handled)
|
||||
private static bool InvokeCommandsBoundToKeyOnAdornment (Adornment adornment, Key key, KeyBindingScope scope, ref bool? handled)
|
||||
{
|
||||
bool? adornmentHandled = adornment.RaiseInvokingKeyBindingsAndInvokeCommands (key);
|
||||
bool? adornmentHandled = adornment.InvokeCommandsBoundToKey (key);
|
||||
|
||||
if (adornmentHandled is true)
|
||||
{
|
||||
@@ -616,7 +575,7 @@ public partial class View // Keyboard APIs
|
||||
|
||||
foreach (View subview in adornment.Subviews)
|
||||
{
|
||||
bool? subViewHandled = subview.RaiseInvokingKeyBindingsAndInvokeCommands (key);
|
||||
bool? subViewHandled = subview.InvokeCommandsBoundToKey (key);
|
||||
|
||||
if (subViewHandled is { })
|
||||
{
|
||||
@@ -632,7 +591,7 @@ public partial class View // Keyboard APIs
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ProcessSubViewKeyBindings (Key key, KeyBindingScope scope, ref bool? handled, bool invoke = true)
|
||||
private bool InvokeCommandsBoundToKeyOnSubviews (Key key, KeyBindingScope scope, ref bool? handled, bool invoke = true)
|
||||
{
|
||||
// Now, process any key bindings in the subviews that are tagged to KeyBindingScope.HotKey.
|
||||
foreach (View subview in Subviews)
|
||||
@@ -654,7 +613,7 @@ public partial class View // Keyboard APIs
|
||||
return true;
|
||||
}
|
||||
|
||||
bool? subViewHandled = subview.RaiseInvokingKeyBindingsAndInvokeCommands (key);
|
||||
bool? subViewHandled = subview.InvokeCommandsBoundToKey (key);
|
||||
|
||||
if (subViewHandled is { })
|
||||
{
|
||||
@@ -667,7 +626,7 @@ public partial class View // Keyboard APIs
|
||||
}
|
||||
}
|
||||
|
||||
bool recurse = subview.ProcessSubViewKeyBindings (key, scope, ref handled, invoke);
|
||||
bool recurse = subview.InvokeCommandsBoundToKeyOnSubviews (key, scope, ref handled, invoke);
|
||||
|
||||
if (recurse || (handled is { } && (bool)handled))
|
||||
{
|
||||
|
||||
@@ -309,7 +309,7 @@ internal sealed class Menu : View
|
||||
protected override bool OnKeyDownNotHandled (Key keyEvent)
|
||||
{
|
||||
// We didn't handle the key, pass it on to host
|
||||
return _host.RaiseInvokingKeyBindingsAndInvokeCommands (keyEvent) == true;
|
||||
return _host.InvokeCommandsBoundToKey (keyEvent) == true;
|
||||
}
|
||||
|
||||
private void Current_TerminalResized (object? sender, SizeChangedEventArgs e)
|
||||
|
||||
@@ -10,109 +10,136 @@ public class Keys : Scenario
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
ObservableCollection<string> keyPressedList = [];
|
||||
ObservableCollection<string> invokingKeyBindingsList = new ();
|
||||
ObservableCollection<string> keyDownList = [];
|
||||
ObservableCollection<string> keyDownNotHandledList = new ();
|
||||
|
||||
var win = new Window { Title = GetQuitKeyAndName () };
|
||||
var editLabel = new Label { X = 0, Y = 0, Text = "Type text here:" };
|
||||
win.Add (editLabel);
|
||||
|
||||
var edit = new TextField { X = Pos.Right (editLabel) + 1, Y = Pos.Top (editLabel), Width = Dim.Fill (2) };
|
||||
var label = new Label
|
||||
{
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Text = "_Type text here:"
|
||||
};
|
||||
win.Add (label);
|
||||
|
||||
var edit = new TextField
|
||||
{
|
||||
X = Pos.Right (label) + 1,
|
||||
Y = Pos.Top (label),
|
||||
Width = Dim.Fill (2),
|
||||
Height = 1,
|
||||
};
|
||||
win.Add (edit);
|
||||
|
||||
edit.KeyDown += (s, a) => { keyPressedList.Add (a.ToString ()); };
|
||||
|
||||
edit.InvokingKeyBindings += (s, a) =>
|
||||
{
|
||||
if (edit.KeyBindings.TryGet (a, out KeyBinding binding))
|
||||
{
|
||||
invokingKeyBindingsList.Add ($"{a}: {string.Join (",", binding.Commands)}");
|
||||
}
|
||||
};
|
||||
|
||||
// Last KeyPress: ______
|
||||
var keyPressedLabel = new Label
|
||||
label = new Label
|
||||
{
|
||||
X = Pos.Left (editLabel), Y = Pos.Top (editLabel) + 1, Text = "Last TextView.KeyPressed:"
|
||||
X = 0,
|
||||
Y = Pos.Bottom (label),
|
||||
Text = "Last _Application.KeyDown:"
|
||||
};
|
||||
win.Add (keyPressedLabel);
|
||||
var labelTextViewKeypress = new Label { X = Pos.Right (keyPressedLabel) + 1, Y = Pos.Top (keyPressedLabel) };
|
||||
win.Add (labelTextViewKeypress);
|
||||
|
||||
edit.KeyDown += (s, e) => labelTextViewKeypress.Text = e.ToString ();
|
||||
|
||||
keyPressedLabel = new Label
|
||||
win.Add (label);
|
||||
var labelAppKeypress = new Label
|
||||
{
|
||||
X = Pos.Left (keyPressedLabel), Y = Pos.Bottom (keyPressedLabel), Text = "Last Application.KeyDown:"
|
||||
X = Pos.Right (label) + 1,
|
||||
Y = Pos.Top (label)
|
||||
};
|
||||
win.Add (keyPressedLabel);
|
||||
var labelAppKeypress = new Label { X = Pos.Right (keyPressedLabel) + 1, Y = Pos.Top (keyPressedLabel) };
|
||||
win.Add (labelAppKeypress);
|
||||
|
||||
Application.KeyDown += (s, e) => labelAppKeypress.Text = e.ToString ();
|
||||
|
||||
// Key stroke log:
|
||||
var keyLogLabel = new Label
|
||||
{
|
||||
X = Pos.Left (editLabel), Y = Pos.Top (editLabel) + 4, Text = "Application Key Events:"
|
||||
};
|
||||
win.Add (keyLogLabel);
|
||||
int maxKeyString = Key.CursorRight.WithAlt.WithCtrl.WithShift.ToString ().Length;
|
||||
var yOffset = 1;
|
||||
ObservableCollection<string> keyEventlist = new ();
|
||||
|
||||
var keyEventListView = new ListView
|
||||
label = new ()
|
||||
{
|
||||
X = 0,
|
||||
Y = Pos.Top (keyLogLabel) + yOffset,
|
||||
Width = "Key Down:".Length + maxKeyString,
|
||||
Y = Pos.Bottom (label),
|
||||
Text = "_Last TextField.KeyDown:"
|
||||
};
|
||||
win.Add (label);
|
||||
|
||||
var lastTextFieldKeyDownLabel = new Label
|
||||
{
|
||||
X = Pos.Right (label) + 1,
|
||||
Y = Pos.Top (label),
|
||||
Height = 1,
|
||||
};
|
||||
win.Add (lastTextFieldKeyDownLabel);
|
||||
|
||||
edit.KeyDown += (s, e) => lastTextFieldKeyDownLabel.Text = e.ToString ();
|
||||
|
||||
// Application key event log:
|
||||
label = new Label
|
||||
{
|
||||
X = 0,
|
||||
Y = Pos.Bottom (label) + 1,
|
||||
Text = "Application Key Events:"
|
||||
};
|
||||
win.Add (label);
|
||||
int maxKeyString = Key.CursorRight.WithAlt.WithCtrl.WithShift.ToString ().Length;
|
||||
|
||||
ObservableCollection<string> keyEventList = new ();
|
||||
|
||||
var appKeyEventListView = new ListView
|
||||
{
|
||||
X = 0,
|
||||
Y = Pos.Bottom (label),
|
||||
Width = "KeyDown:".Length + maxKeyString,
|
||||
Height = Dim.Fill (),
|
||||
Source = new ListWrapper<string> (keyEventlist)
|
||||
Source = new ListWrapper<string> (keyEventList)
|
||||
};
|
||||
keyEventListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
|
||||
win.Add (keyEventListView);
|
||||
appKeyEventListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
|
||||
win.Add (appKeyEventListView);
|
||||
|
||||
// OnKeyPressed
|
||||
var onKeyPressedLabel = new Label
|
||||
// View key events...
|
||||
edit.KeyDown += (s, a) => { keyDownList.Add (a.ToString ()); };
|
||||
|
||||
edit.KeyDownNotHandled += (s, a) =>
|
||||
{
|
||||
if (edit.KeyBindings.TryGet (a, out KeyBinding binding))
|
||||
{
|
||||
keyDownNotHandledList.Add ($"{a}: {string.Join (",", binding.Commands)}");
|
||||
}
|
||||
};
|
||||
|
||||
// KeyDown
|
||||
label = new Label
|
||||
{
|
||||
X = Pos.Right (keyEventListView) + 1, Y = Pos.Top (editLabel) + 4, Text = "TextView KeyDown:"
|
||||
X = Pos.Right (appKeyEventListView) + 1,
|
||||
Y = Pos.Top (label),
|
||||
Text = "TextView Key Down:"
|
||||
};
|
||||
win.Add (onKeyPressedLabel);
|
||||
win.Add (label);
|
||||
|
||||
yOffset = 1;
|
||||
|
||||
var onKeyPressedListView = new ListView
|
||||
var onKeyDownListView = new ListView
|
||||
{
|
||||
X = Pos.Left (onKeyPressedLabel),
|
||||
Y = Pos.Top (onKeyPressedLabel) + yOffset,
|
||||
X = Pos.Left (label),
|
||||
Y = Pos.Bottom (label),
|
||||
Width = maxKeyString,
|
||||
Height = Dim.Fill (),
|
||||
Source = new ListWrapper<string> (keyPressedList)
|
||||
Source = new ListWrapper<string> (keyDownList)
|
||||
};
|
||||
onKeyPressedListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
|
||||
win.Add (onKeyPressedListView);
|
||||
onKeyDownListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
|
||||
win.Add (onKeyDownListView);
|
||||
|
||||
// OnInvokeKeyBindings
|
||||
var onInvokingKeyBindingsLabel = new Label
|
||||
// KeyDownNotHandled
|
||||
label = new Label
|
||||
{
|
||||
X = Pos.Right (onKeyPressedListView) + 1,
|
||||
Y = Pos.Top (editLabel) + 4,
|
||||
Text = "TextView InvokingKeyBindings:"
|
||||
X = Pos.Right (onKeyDownListView) + 1,
|
||||
Y = Pos.Top (label),
|
||||
Text = "TextView KeyDownNotHandled:"
|
||||
};
|
||||
win.Add (onInvokingKeyBindingsLabel);
|
||||
win.Add (label);
|
||||
|
||||
var onInvokingKeyBindingsListView = new ListView
|
||||
var onKeyDownNotHandledListView = new ListView
|
||||
{
|
||||
X = Pos.Left (onInvokingKeyBindingsLabel),
|
||||
Y = Pos.Top (onInvokingKeyBindingsLabel) + yOffset,
|
||||
Width = Dim.Fill (1),
|
||||
X = Pos.Left (label),
|
||||
Y = Pos.Bottom (label),
|
||||
Width = maxKeyString,
|
||||
Height = Dim.Fill (),
|
||||
Source = new ListWrapper<string> (invokingKeyBindingsList)
|
||||
Source = new ListWrapper<string> (keyDownNotHandledList)
|
||||
};
|
||||
onInvokingKeyBindingsListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
|
||||
win.Add (onInvokingKeyBindingsListView);
|
||||
onKeyDownNotHandledListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
|
||||
win.Add (onKeyDownNotHandledListView);
|
||||
|
||||
//Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
|
||||
Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
|
||||
Application.KeyUp += (s, a) => KeyDownPressUp (a, "Up");
|
||||
|
||||
@@ -120,10 +147,9 @@ public class Keys : Scenario
|
||||
{
|
||||
// BUGBUG: KeyEvent.ToString is badly broken
|
||||
var msg = $"Key{updown,-7}: {args}";
|
||||
keyEventlist.Add (msg);
|
||||
keyEventListView.MoveDown ();
|
||||
onKeyPressedListView.MoveDown ();
|
||||
onInvokingKeyBindingsListView.MoveDown ();
|
||||
keyEventList.Add (msg);
|
||||
appKeyEventListView.MoveDown ();
|
||||
onKeyDownNotHandledListView.MoveDown ();
|
||||
}
|
||||
|
||||
Application.Run (win);
|
||||
|
||||
@@ -148,7 +148,7 @@ public class VkeyPacketSimulator : Scenario
|
||||
}
|
||||
};
|
||||
|
||||
tvInput.InvokingKeyBindings += (s, e) =>
|
||||
tvInput.KeyDownNotHandled += (s, e) =>
|
||||
{
|
||||
Key ev = e;
|
||||
|
||||
|
||||
@@ -163,39 +163,39 @@ public class KeyboardTests
|
||||
public void KeyBinding_OnKeyDown ()
|
||||
{
|
||||
var view = new ScopedKeyBindingView ();
|
||||
var invoked = false;
|
||||
view.InvokingKeyBindings += (s, e) => invoked = true;
|
||||
var keyWasHandled = false;
|
||||
view.KeyDownNotHandled += (s, e) => keyWasHandled = true;
|
||||
|
||||
var top = new Toplevel ();
|
||||
top.Add (view);
|
||||
Application.Begin (top);
|
||||
|
||||
Application.RaiseKeyDownEvent (Key.A);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.True (view.ApplicationCommand);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
view.ApplicationCommand = false;
|
||||
Application.KeyBindings.Remove (KeyCode.A);
|
||||
Application.RaiseKeyDownEvent (Key.A); // old
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.ApplicationCommand);
|
||||
Application.KeyBindings.Add (Key.A.WithCtrl, view, Command.Save);
|
||||
Application.RaiseKeyDownEvent (Key.A); // old
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.ApplicationCommand);
|
||||
Application.RaiseKeyDownEvent (Key.A.WithCtrl); // new
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.True (view.ApplicationCommand);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
Application.RaiseKeyDownEvent (Key.H);
|
||||
Assert.True (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
Assert.False (view.HasFocus);
|
||||
Application.RaiseKeyDownEvent (Key.F);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
|
||||
Assert.True (view.ApplicationCommand);
|
||||
Assert.True (view.HotKeyCommand);
|
||||
@@ -208,23 +208,23 @@ public class KeyboardTests
|
||||
public void KeyBinding_OnKeyDown_Negative ()
|
||||
{
|
||||
var view = new ScopedKeyBindingView ();
|
||||
var invoked = false;
|
||||
view.InvokingKeyBindings += (s, e) => invoked = true;
|
||||
var keyWasHandled = false;
|
||||
view.KeyDownNotHandled += (s, e) => keyWasHandled = true;
|
||||
|
||||
var top = new Toplevel ();
|
||||
top.Add (view);
|
||||
Application.Begin (top);
|
||||
|
||||
Application.RaiseKeyDownEvent (Key.A.WithCtrl);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.ApplicationCommand);
|
||||
Assert.False (view.HotKeyCommand);
|
||||
Assert.False (view.FocusedCommand);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
Assert.False (view.HasFocus);
|
||||
Application.RaiseKeyDownEvent (Key.Z);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.ApplicationCommand);
|
||||
Assert.False (view.HotKeyCommand);
|
||||
Assert.False (view.FocusedCommand);
|
||||
|
||||
@@ -95,7 +95,7 @@ public class HotKeyTests
|
||||
{
|
||||
var view = new View ();
|
||||
view.KeyBindings.Add (Key.A, Command.HotKey); // implies KeyBindingScope.Focused - so this should not be invoked
|
||||
view.InvokingKeyBindings += (s, e) => { Assert.Fail (); };
|
||||
view.KeyDownNotHandled += (s, e) => { Assert.Fail (); };
|
||||
|
||||
var superView = new View ();
|
||||
superView.Add (view);
|
||||
@@ -109,8 +109,11 @@ public class HotKeyTests
|
||||
{
|
||||
var view = new View ();
|
||||
view.KeyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.HotKey);
|
||||
bool invoked = false;
|
||||
view.InvokingKeyBindings += (s, e) => { invoked = true; };
|
||||
bool hotKeyInvoked = false;
|
||||
view.HandlingHotKey += (s, e) => { hotKeyInvoked = true; };
|
||||
|
||||
bool notHandled = false;
|
||||
view.KeyDownNotHandled += (s, e) => { notHandled = true; };
|
||||
|
||||
var superView = new View ();
|
||||
superView.Add (view);
|
||||
@@ -118,7 +121,8 @@ public class HotKeyTests
|
||||
var ke = Key.A;
|
||||
superView.NewKeyDownEvent (ke);
|
||||
|
||||
Assert.True (invoked);
|
||||
Assert.False (notHandled);
|
||||
Assert.True (hotKeyInvoked);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ namespace Terminal.Gui.ViewTests;
|
||||
public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
{
|
||||
/// <summary>
|
||||
/// This tests that when a new key down event is sent to the view will fire the 3 key-down related
|
||||
/// events: KeyDown, InvokingKeyBindings, and ProcessKeyDown. Note that KeyUp is independent.
|
||||
/// This tests that when a new key down event is sent to the view will fire the key-down related
|
||||
/// events: KeyDown and KeyDownNotHandled. Note that KeyUp is independent.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[MemberData (nameof (AllViewTypes))]
|
||||
@@ -33,27 +33,18 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
keyDown = true;
|
||||
};
|
||||
|
||||
var invokingKeyBindings = false;
|
||||
|
||||
view.InvokingKeyBindings += (s, a) =>
|
||||
{
|
||||
a.Handled = false; // don't handle it so the other events are called
|
||||
invokingKeyBindings = true;
|
||||
};
|
||||
|
||||
var keyDownProcessed = false;
|
||||
var keyDownNotHandled = false;
|
||||
|
||||
view.KeyDownNotHandled += (s, a) =>
|
||||
{
|
||||
a.Handled = true;
|
||||
keyDownProcessed = true;
|
||||
keyDownNotHandled = true;
|
||||
};
|
||||
|
||||
// Key.Empty is invalid, but it's used here to test that the event is fired
|
||||
Assert.True (view.NewKeyDownEvent (Key.Empty)); // this will be true because the ProcessKeyDown event handled it
|
||||
Assert.True (keyDown);
|
||||
Assert.True (invokingKeyBindings);
|
||||
Assert.True (keyDownProcessed);
|
||||
Assert.True (keyDownNotHandled);
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
@@ -96,7 +87,7 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
public void NewKeyDownUpEvents_Events_Are_Raised_With_Only_Key_Modifiers (bool shift, bool alt, bool control)
|
||||
{
|
||||
var keyDown = false;
|
||||
var keyPressed = false;
|
||||
var keyDownNotHandled = false;
|
||||
var keyUp = false;
|
||||
|
||||
var view = new OnNewKeyTestView ();
|
||||
@@ -112,7 +103,7 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
Assert.True (view.OnKeyDownCalled);
|
||||
keyDown = true;
|
||||
};
|
||||
view.KeyDownNotHandled += (s, e) => { keyPressed = true; };
|
||||
view.KeyDownNotHandled += (s, e) => { keyDownNotHandled = true; };
|
||||
|
||||
view.KeyUp += (s, e) =>
|
||||
{
|
||||
@@ -125,11 +116,6 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
keyUp = true;
|
||||
};
|
||||
|
||||
//view.ProcessKeyDownEvent (new (Key.Null | (shift ? Key.ShiftMask : 0) | (alt ? Key.AltMask : 0) | (control ? Key.CtrlMask : 0)));
|
||||
//Assert.True (keyDown);
|
||||
//Assert.True (view.OnKeyDownWasCalled);
|
||||
//Assert.True (view.OnProcessKeyDownWasCalled);
|
||||
|
||||
view.NewKeyDownEvent (
|
||||
new (
|
||||
KeyCode.Null
|
||||
@@ -138,7 +124,7 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
| (control ? KeyCode.CtrlMask : 0)
|
||||
)
|
||||
);
|
||||
Assert.True (keyPressed);
|
||||
Assert.True (keyDownNotHandled);
|
||||
Assert.True (view.OnKeyDownCalled);
|
||||
Assert.True (view.OnProcessKeyDownCalled);
|
||||
|
||||
@@ -154,107 +140,11 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
Assert.True (view.OnKeyUpCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NewKeyDownEvent_InvokingKeyBindings_Handled_Cancels ()
|
||||
{
|
||||
var view = new View ();
|
||||
var keyPressInvoked = false;
|
||||
var invokingKeyBindingsInvoked = false;
|
||||
var processKeyPressInvoked = false;
|
||||
var setHandledTo = false;
|
||||
|
||||
view.KeyDown += (s, e) =>
|
||||
{
|
||||
keyPressInvoked = true;
|
||||
Assert.False (e.Handled);
|
||||
Assert.Equal (KeyCode.N, e.KeyCode);
|
||||
};
|
||||
|
||||
view.InvokingKeyBindings += (s, e) =>
|
||||
{
|
||||
invokingKeyBindingsInvoked = true;
|
||||
e.Handled = setHandledTo;
|
||||
Assert.Equal (setHandledTo, e.Handled);
|
||||
Assert.Equal (KeyCode.N, e.KeyCode);
|
||||
};
|
||||
|
||||
view.KeyDownNotHandled += (s, e) =>
|
||||
{
|
||||
processKeyPressInvoked = true;
|
||||
processKeyPressInvoked = true;
|
||||
Assert.False (e.Handled);
|
||||
Assert.Equal (KeyCode.N, e.KeyCode);
|
||||
};
|
||||
|
||||
view.NewKeyDownEvent (Key.N);
|
||||
Assert.True (keyPressInvoked);
|
||||
Assert.True (invokingKeyBindingsInvoked);
|
||||
Assert.True (processKeyPressInvoked);
|
||||
|
||||
keyPressInvoked = false;
|
||||
invokingKeyBindingsInvoked = false;
|
||||
processKeyPressInvoked = false;
|
||||
setHandledTo = true;
|
||||
view.NewKeyDownEvent (Key.N);
|
||||
Assert.True (keyPressInvoked);
|
||||
Assert.True (invokingKeyBindingsInvoked);
|
||||
Assert.False (processKeyPressInvoked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NewKeyDownEvent_InvokingKeyBindings_Handled_True_Stops_Processing ()
|
||||
{
|
||||
var keyDown = false;
|
||||
var invokingKeyBindings = false;
|
||||
var keyPressed = false;
|
||||
|
||||
var view = new OnNewKeyTestView ();
|
||||
Assert.True (view.CanFocus);
|
||||
view.CancelVirtualMethods = false;
|
||||
|
||||
view.KeyDown += (s, e) =>
|
||||
{
|
||||
Assert.Equal (KeyCode.A, e.KeyCode);
|
||||
Assert.False (keyDown);
|
||||
Assert.True (view.OnKeyDownCalled);
|
||||
e.Handled = false;
|
||||
keyDown = true;
|
||||
};
|
||||
|
||||
view.InvokingKeyBindings += (s, e) =>
|
||||
{
|
||||
Assert.Equal (KeyCode.A, e.KeyCode);
|
||||
Assert.False (keyPressed);
|
||||
Assert.True (view.OnInvokingKeyBindingsCalled);
|
||||
e.Handled = true;
|
||||
invokingKeyBindings = true;
|
||||
};
|
||||
|
||||
view.KeyDownNotHandled += (s, e) =>
|
||||
{
|
||||
Assert.Equal (KeyCode.A, e.KeyCode);
|
||||
Assert.False (keyPressed);
|
||||
Assert.False (view.OnProcessKeyDownCalled);
|
||||
e.Handled = true;
|
||||
keyPressed = true;
|
||||
};
|
||||
|
||||
view.NewKeyDownEvent (Key.A);
|
||||
Assert.True (keyDown);
|
||||
Assert.True (invokingKeyBindings);
|
||||
Assert.False (keyPressed);
|
||||
|
||||
Assert.True (view.OnKeyDownCalled);
|
||||
Assert.True (view.OnInvokingKeyBindingsCalled);
|
||||
Assert.False (view.OnProcessKeyDownCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NewKeyDownEvent_Handled_True_Stops_Processing ()
|
||||
{
|
||||
var keyDown = false;
|
||||
var invokingKeyBindings = false;
|
||||
var keyPressed = false;
|
||||
var keyDownNotHandled = false;
|
||||
|
||||
var view = new OnNewKeyTestView ();
|
||||
Assert.True (view.CanFocus);
|
||||
@@ -269,31 +159,21 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
keyDown = true;
|
||||
};
|
||||
|
||||
view.InvokingKeyBindings += (s, e) =>
|
||||
{
|
||||
Assert.Equal (KeyCode.A, e.KeyCode);
|
||||
Assert.False (keyPressed);
|
||||
Assert.False (view.OnInvokingKeyBindingsCalled);
|
||||
e.Handled = true;
|
||||
invokingKeyBindings = true;
|
||||
};
|
||||
|
||||
view.KeyDownNotHandled += (s, e) =>
|
||||
{
|
||||
Assert.Equal (KeyCode.A, e.KeyCode);
|
||||
Assert.False (keyPressed);
|
||||
Assert.False (keyDownNotHandled);
|
||||
Assert.False (view.OnProcessKeyDownCalled);
|
||||
e.Handled = true;
|
||||
keyPressed = true;
|
||||
keyDownNotHandled = true;
|
||||
};
|
||||
|
||||
view.NewKeyDownEvent (Key.A);
|
||||
Assert.True (keyDown);
|
||||
Assert.False (invokingKeyBindings);
|
||||
Assert.False (keyPressed);
|
||||
Assert.False (keyDownNotHandled);
|
||||
|
||||
Assert.True (view.OnKeyDownCalled);
|
||||
Assert.False (view.OnInvokingKeyBindingsCalled);
|
||||
Assert.False (view.OnProcessKeyDownCalled);
|
||||
}
|
||||
|
||||
@@ -301,8 +181,7 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
public void NewKeyDownEvent_KeyDown_Handled_Stops_Processing ()
|
||||
{
|
||||
var view = new View ();
|
||||
var invokingKeyBindingsInvoked = false;
|
||||
var processKeyPressInvoked = false;
|
||||
var keyDownNotHandled = false;
|
||||
var setHandledTo = false;
|
||||
|
||||
view.KeyDown += (s, e) =>
|
||||
@@ -312,38 +191,27 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
Assert.Equal (KeyCode.N, e.KeyCode);
|
||||
};
|
||||
|
||||
view.InvokingKeyBindings += (s, e) =>
|
||||
{
|
||||
invokingKeyBindingsInvoked = true;
|
||||
Assert.False (e.Handled);
|
||||
Assert.Equal (KeyCode.N, e.KeyCode);
|
||||
};
|
||||
|
||||
view.KeyDownNotHandled += (s, e) =>
|
||||
{
|
||||
processKeyPressInvoked = true;
|
||||
keyDownNotHandled = true;
|
||||
Assert.False (e.Handled);
|
||||
Assert.Equal (KeyCode.N, e.KeyCode);
|
||||
};
|
||||
|
||||
view.NewKeyDownEvent (Key.N);
|
||||
Assert.True (invokingKeyBindingsInvoked);
|
||||
Assert.True (processKeyPressInvoked);
|
||||
Assert.True (keyDownNotHandled);
|
||||
|
||||
invokingKeyBindingsInvoked = false;
|
||||
processKeyPressInvoked = false;
|
||||
keyDownNotHandled = false;
|
||||
setHandledTo = true;
|
||||
view.NewKeyDownEvent (Key.N);
|
||||
Assert.False (invokingKeyBindingsInvoked);
|
||||
Assert.False (processKeyPressInvoked);
|
||||
Assert.False (keyDownNotHandled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NewKeyDownEvent_ProcessKeyDown_Handled_Stops_Processing ()
|
||||
{
|
||||
var keyDown = false;
|
||||
var invokingKeyBindings = false;
|
||||
var processKeyDown = false;
|
||||
var keyDownNotHandled = false;
|
||||
|
||||
var view = new OnNewKeyTestView ();
|
||||
Assert.True (view.CanFocus);
|
||||
@@ -358,31 +226,20 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
keyDown = true;
|
||||
};
|
||||
|
||||
view.InvokingKeyBindings += (s, e) =>
|
||||
{
|
||||
Assert.Equal (KeyCode.A, e.KeyCode);
|
||||
Assert.False (processKeyDown);
|
||||
Assert.True (view.OnInvokingKeyBindingsCalled);
|
||||
e.Handled = false;
|
||||
invokingKeyBindings = true;
|
||||
};
|
||||
|
||||
view.KeyDownNotHandled += (s, e) =>
|
||||
{
|
||||
Assert.Equal (KeyCode.A, e.KeyCode);
|
||||
Assert.False (processKeyDown);
|
||||
Assert.False (keyDownNotHandled);
|
||||
Assert.True (view.OnProcessKeyDownCalled);
|
||||
e.Handled = true;
|
||||
processKeyDown = true;
|
||||
keyDownNotHandled = true;
|
||||
};
|
||||
|
||||
view.NewKeyDownEvent (Key.A);
|
||||
Assert.True (keyDown);
|
||||
Assert.True (invokingKeyBindings);
|
||||
Assert.True (processKeyDown);
|
||||
Assert.True (keyDownNotHandled);
|
||||
|
||||
Assert.True (view.OnKeyDownCalled);
|
||||
Assert.True (view.OnInvokingKeyBindingsCalled);
|
||||
Assert.True (view.OnProcessKeyDownCalled);
|
||||
}
|
||||
|
||||
@@ -409,7 +266,6 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
|
||||
Assert.True (view.OnKeyUpCalled);
|
||||
Assert.False (view.OnKeyDownCalled);
|
||||
Assert.False (view.OnInvokingKeyBindingsCalled);
|
||||
Assert.False (view.OnProcessKeyDownCalled);
|
||||
}
|
||||
|
||||
@@ -417,12 +273,12 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
[InlineData (null, null)]
|
||||
[InlineData (true, true)]
|
||||
[InlineData (false, false)]
|
||||
public void RaiseInvokingKeyBindingsAndInvokeCommands_Returns_Nullable_Properly (bool? toReturn, bool? expected)
|
||||
public void InvokeCommandsBoundToKey_Returns_Nullable_Properly (bool? toReturn, bool? expected)
|
||||
{
|
||||
var view = new KeyBindingsTestView ();
|
||||
view.CommandReturns = toReturn;
|
||||
|
||||
bool? result = view.RaiseInvokingKeyBindingsAndInvokeCommands (Key.A);
|
||||
bool? result = view.InvokeCommandsBoundToKey (Key.A);
|
||||
Assert.Equal (expected, result);
|
||||
}
|
||||
|
||||
@@ -444,20 +300,11 @@ public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
{
|
||||
public OnNewKeyTestView () { CanFocus = true; }
|
||||
public bool CancelVirtualMethods { set; private get; }
|
||||
public bool OnInvokingKeyBindingsCalled { get; set; }
|
||||
public bool OnKeyDownCalled { get; set; }
|
||||
public bool OnProcessKeyDownCalled { get; set; }
|
||||
public bool OnKeyUpCalled { get; set; }
|
||||
public override string Text { get; set; }
|
||||
|
||||
protected override bool OnInvokingKeyBindings (Key keyEvent, KeyBindingScope scope)
|
||||
{
|
||||
|
||||
OnInvokingKeyBindingsCalled = true;
|
||||
|
||||
return CancelVirtualMethods;
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown (Key keyEvent)
|
||||
{
|
||||
OnKeyDownCalled = true;
|
||||
|
||||
@@ -11,37 +11,38 @@ public class ViewKeyBindingTests (ITestOutputHelper output)
|
||||
public void Focus_KeyBinding ()
|
||||
{
|
||||
var view = new ScopedKeyBindingView ();
|
||||
var invoked = false;
|
||||
view.InvokingKeyBindings += (s, e) => invoked = true;
|
||||
var keyWasHandled = false;
|
||||
view.KeyDownNotHandled += (s, e) => keyWasHandled = true;
|
||||
|
||||
var top = new Toplevel ();
|
||||
top.Add (view);
|
||||
Application.Begin (top);
|
||||
|
||||
Application.RaiseKeyDownEvent (Key.A);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.True (view.ApplicationCommand);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
Application.RaiseKeyDownEvent (Key.H);
|
||||
Assert.True (invoked);
|
||||
Assert.True (view.HotKeyCommand);
|
||||
Assert.False (keyWasHandled);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
Assert.False (view.HasFocus);
|
||||
Application.RaiseKeyDownEvent (Key.F);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.FocusedCommand);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
view.CanFocus = true;
|
||||
view.SetFocus ();
|
||||
Assert.True (view.HasFocus);
|
||||
Application.RaiseKeyDownEvent (Key.F);
|
||||
Assert.True (invoked);
|
||||
Assert.True (view.FocusedCommand);
|
||||
Assert.False (keyWasHandled); // Command was invoked, but wasn't handled
|
||||
|
||||
Assert.True (view.ApplicationCommand);
|
||||
Assert.True (view.HotKeyCommand);
|
||||
Assert.True (view.FocusedCommand);
|
||||
top.Dispose ();
|
||||
}
|
||||
|
||||
@@ -50,23 +51,23 @@ public class ViewKeyBindingTests (ITestOutputHelper output)
|
||||
public void Focus_KeyBinding_Negative ()
|
||||
{
|
||||
var view = new ScopedKeyBindingView ();
|
||||
var invoked = false;
|
||||
view.InvokingKeyBindings += (s, e) => invoked = true;
|
||||
var keyWasHandled = false;
|
||||
view.KeyDownNotHandled += (s, e) => keyWasHandled = true;
|
||||
|
||||
var top = new Toplevel ();
|
||||
top.Add (view);
|
||||
Application.Begin (top);
|
||||
|
||||
Application.RaiseKeyDownEvent (Key.Z);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.ApplicationCommand);
|
||||
Assert.False (view.HotKeyCommand);
|
||||
Assert.False (view.FocusedCommand);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
Assert.False (view.HasFocus);
|
||||
Application.RaiseKeyDownEvent (Key.F);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.ApplicationCommand);
|
||||
Assert.False (view.HotKeyCommand);
|
||||
Assert.False (view.FocusedCommand);
|
||||
@@ -78,28 +79,29 @@ public class ViewKeyBindingTests (ITestOutputHelper output)
|
||||
public void HotKey_KeyBinding ()
|
||||
{
|
||||
var view = new ScopedKeyBindingView ();
|
||||
var invoked = false;
|
||||
view.InvokingKeyBindings += (s, e) => invoked = true;
|
||||
var keyWasHandled = false;
|
||||
view.KeyDownNotHandled += (s, e) => keyWasHandled = true;
|
||||
|
||||
var top = new Toplevel ();
|
||||
top.Add (view);
|
||||
Application.Begin (top);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
Application.RaiseKeyDownEvent (Key.H);
|
||||
Assert.True (invoked);
|
||||
Assert.True (view.HotKeyCommand);
|
||||
Assert.False (keyWasHandled);
|
||||
|
||||
view.HotKey = KeyCode.Z;
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
view.HotKeyCommand = false;
|
||||
Application.RaiseKeyDownEvent (Key.H); // old hot key
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.HotKeyCommand);
|
||||
|
||||
Application.RaiseKeyDownEvent (Key.Z); // new hot key
|
||||
Assert.True (invoked);
|
||||
Assert.True (view.HotKeyCommand);
|
||||
Assert.False (keyWasHandled);
|
||||
|
||||
top.Dispose ();
|
||||
}
|
||||
|
||||
@@ -108,18 +110,18 @@ public class ViewKeyBindingTests (ITestOutputHelper output)
|
||||
public void HotKey_KeyBinding_Negative ()
|
||||
{
|
||||
var view = new ScopedKeyBindingView ();
|
||||
var invoked = false;
|
||||
view.InvokingKeyBindings += (s, e) => invoked = true;
|
||||
var keyWasHandled = false;
|
||||
view.KeyDownNotHandled += (s, e) => keyWasHandled = true;
|
||||
|
||||
var top = new Toplevel ();
|
||||
top.Add (view);
|
||||
Application.Begin (top);
|
||||
|
||||
Application.RaiseKeyDownEvent (Key.Z);
|
||||
Assert.False (invoked);
|
||||
Assert.False (keyWasHandled);
|
||||
Assert.False (view.HotKeyCommand);
|
||||
|
||||
invoked = false;
|
||||
keyWasHandled = false;
|
||||
Application.RaiseKeyDownEvent (Key.F);
|
||||
Assert.False (view.HotKeyCommand);
|
||||
top.Dispose ();
|
||||
@@ -59,22 +59,25 @@ The Command can be invoked even if the `View` that defines them is not focused o
|
||||
|
||||
### **Handling Keyboard Events**
|
||||
|
||||
Keyboard events are retrieved from [Console Drivers](drivers.md) and passed on
|
||||
to the [Application](~/api/Terminal.Gui.Application.yml) class by the [Main Loop](mainloop.md).
|
||||
Keyboard events are retrieved from [Console Drivers](drivers.md) each iteration of the [Application](~/api/Terminal.Gui.Application.yml) [Main Loop](mainloop.md). The console driver raises the @Terminal.Gui.ConsoleDriver.KeyDown and @Terminal.Gui.ConsoleDriver.KeyUp events which invoke @Terminal.Gui.Application.RaiseKeyDown(Terminal.Gui.Key) and @Terminal.Gui.Application.RaiseKeyUp(Terminal.Gui.Key) respectively.
|
||||
|
||||
[Application](~/api/Terminal.Gui.Application.yml) then determines the current [Toplevel](~/api/Terminal.Gui.Toplevel.yml) view
|
||||
(either the default created by calling @Terminal.Gui.Application.Init(Terminal.Gui.ConsoleDriver,System.String), or the one set by calling `Application.Run`). The mouse event, using [Viewport-relative coordinates](xref:Terminal.Gui.View.Viewport) is then passed to the @Terminal.Gui.View.NewKeyDownEvent(Terminal.Gui.Key) method of the current [Toplevel](~/api/Terminal.Gui.Toplevel.yml) view.
|
||||
NOTE: Not all drivers/platforms support sensing distinct KeyUp events. These drivers will simulate KeyUp events by raising @Terminal.Gui.ConsoleDriver.KeyUp after @Terminal.Gui.ConsoleDriver.KeyDown.
|
||||
|
||||
If the view is enabled, the @Terminal.Gui.View.NewKeyDownEvent(Terminal.Gui.Key) method will do the following:
|
||||
@Terminal.Gui.Application.RaiseKeyDown(Terminal.Gui.Key) raises @Terminal.Gui.Application.KeyDown and then calls @Terminal.Gui.View.NewKeyDownEvent(Terminal.Gui.Key) on all toplevel Views. If no View handles the key event, any Application-scoped key bindings will be invoked.
|
||||
|
||||
1) If the view has a subview that has focus, 'ProcessKeyDown' on the focused view will be called. If the focused view handles the key press, processing stops.
|
||||
2) If there is no focused sub-view, or the focused sub-view does not handle the key press, @Terminal.Gui.View.OnKeyDown(Terminal.Gui.Key) will be called. If the view handles the key press, processing stops.
|
||||
3) If the view does not handle the key press, @Terminal.Gui.TextField.OnInvokingKeyBindings(Terminal.Gui.Key,Terminal.Gui.KeyBindingScope) will be called. This method calls @Terminal.Gui.View.InvokeKeyBindings(Terminal.Gui.Key,Terminal.Gui.KeyBindingScope) to invoke any keys bound to commands. If the key is bound and any of it's command handlers return true, processing stops.
|
||||
4) If the key is not bound, or the bound command handlers do not return true, @Terminal.Gui.View.OnProcessKeyDown(Terminal.Gui.Key) is called. If the view handles the key press, processing stops.
|
||||
@Terminal.Gui.Application.RaiseKeyDown(Terminal.Gui.Key) raises @Terminal.Gui.Application.KeyDown and then calls @Terminal.Gui.View.NewKeyUpEvent(Terminal.Gui.Key) on all toplevel Views.
|
||||
|
||||
If a view is enabled, the @Terminal.Gui.View.NewKeyDownEvent(Terminal.Gui.Key) method will do the following:
|
||||
|
||||
1) If the view has a subview that has focus, 'NewKeyDown' on the focused view will be called. This is recursive. If the most-focused view handles the key press, processing stops.
|
||||
2) If there is no most-focused sub-view, or a most-focused sub-view does not handle the key press, @Terminal.Gui.View.OnKeyDown(Terminal.Gui.Key) will be called. If the view handles the key press, processing stops.
|
||||
3) If @Terminal.Gui.View.OnKeyDown(Terminal.Gui.Key) does not handle the event. @Terminal.Gui.View.KeyDown will be raised.
|
||||
4) If the view does not handle the key down event, any bindings for the key will be invoked (see @Terminal.Gui.View.KeyBindings). If the key is bound and any of it's command handlers return true, processing stops.
|
||||
5) If the key is not bound, or the bound command handlers do not return true, @Terminal.Gui.View.OnKeyDownNotHandled(Terminal.Gui.Key) is called.
|
||||
|
||||
## **Application Key Handling**
|
||||
|
||||
To define application key handling logic for an entire application in cases where the methods listed above are not suitable, use the `Application.OnKeyDown` event.
|
||||
To define application key handling logic for an entire application in cases where the methods listed above are not suitable, use the @Terminal.Gui.Application.KeyDown event.
|
||||
|
||||
## **Key Down/Up Events**
|
||||
|
||||
@@ -90,17 +93,14 @@ To define application key handling logic for an entire application in cases wher
|
||||
- `NewKeyDownEvent` is called on the most-focused SubView (if any) that has focus. If that call returns true, the method returns.
|
||||
- Calls `OnKeyDown`.
|
||||
- **During**
|
||||
- Assuming `OnKeyDown` call returns false (indicating the key wasn't handled)
|
||||
- `OnInvokingKeyBindings` is called to invoke any bound commands.
|
||||
- `OnInvokingKeyBindings` fires the `InvokingKeyBindings` event
|
||||
- Assuming `OnKeyDown` call returns false (indicating the key wasn't handled) any commands bound to the key will be invoked.
|
||||
- **After**
|
||||
- Assuming `OnInvokingKeyBindings` returns false (indicating the key wasn't handled)
|
||||
- `OnProcessKeyDown` is called to process the key.
|
||||
- `OnProcessKeyDown` fires the `ProcessKeyDown` event
|
||||
- Assuming no keybinding was found or all invoked commands were not handled:
|
||||
- `OnKeyDownNotHandled` is called to process the key.
|
||||
- `KeyDownNotHandled` is raised.
|
||||
|
||||
- Subclasses of `View` can (rarely) override `OnKeyDown` to see keys before they are processed by `OnInvokingKeyBindings` and `OnProcessKeyDown
|
||||
- Subclasses of `View` can (rarely) override `OnInvokingKeyBindings` to see keys before they are processed by `OnProcessKeyDown`
|
||||
- Subclasses of `View` can (often) override `OnProcessKeyDown` to do normal key processing.
|
||||
- Subclasses of `View` can (rarely) override `OnKeyDown` (or subscribe to `KeyDown`) to see keys before they are processed
|
||||
- Subclasses of `View` can (often) override `OnKeyDownNotHandled` to do key processing for keys that were not previously handled. `TextField` and `TextView` are examples.
|
||||
|
||||
## ConsoleDriver
|
||||
|
||||
|
||||
Reference in New Issue
Block a user