Browse Source

Merge branch 'v2_develop' into v2_3256_prepare_for_Rect_removal

* v2_develop:
  Fixes #3039. Fix View.HotKey (#3249)
Brandon Thetford 1 year ago
parent
commit
3d807c3833
100 changed files with 1457 additions and 1665 deletions
  1. 1 1
      .github/workflows/dotnet-core.yml
  2. 1 1
      Example/Example.cs
  3. 15 15
      ReactiveExample/LoginView.cs
  4. 8 7
      ReactiveExample/LoginViewModel.cs
  5. 1 2
      Terminal.Gui/Application.cs
  6. 1 1
      Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
  7. 1 1
      Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
  8. 2 1
      Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
  9. 2 2
      Terminal.Gui/FileServices/DefaultFileOperations.cs
  10. 8 11
      Terminal.Gui/Input/Command.cs
  11. 57 17
      Terminal.Gui/Input/Key.cs
  12. 15 11
      Terminal.Gui/Input/KeyBinding.cs
  13. 3 3
      Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs
  14. 1 1
      Terminal.Gui/Text/Autocomplete/AutocompleteBase.cs
  15. 9 9
      Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs
  16. 26 0
      Terminal.Gui/Text/StringEventArgs.cs
  17. 5 3
      Terminal.Gui/Text/TextFormatter.cs
  18. 16 42
      Terminal.Gui/View/Adornment/Border.cs
  19. 27 0
      Terminal.Gui/View/StateEventArgs.cs
  20. 0 23
      Terminal.Gui/View/TitleEventArgs.cs
  21. 0 20
      Terminal.Gui/View/ToggleEventArgs.cs
  22. 98 63
      Terminal.Gui/View/View.cs
  23. 115 71
      Terminal.Gui/View/ViewKeyboard.cs
  24. 36 11
      Terminal.Gui/View/ViewText.cs
  25. 34 31
      Terminal.Gui/Views/Button.cs
  26. 81 106
      Terminal.Gui/Views/CheckBox.cs
  27. 4 4
      Terminal.Gui/Views/ColorPicker.cs
  28. 21 16
      Terminal.Gui/Views/ComboBox.cs
  29. 12 8
      Terminal.Gui/Views/DateField.cs
  30. 2 2
      Terminal.Gui/Views/DatePicker.cs
  31. 15 15
      Terminal.Gui/Views/FileDialog.cs
  32. 4 4
      Terminal.Gui/Views/GraphView/GraphView.cs
  33. 17 17
      Terminal.Gui/Views/HexView.cs
  34. 42 41
      Terminal.Gui/Views/Label.cs
  35. 22 16
      Terminal.Gui/Views/ListView.cs
  36. 10 10
      Terminal.Gui/Views/Menu/Menu.cs
  37. 16 59
      Terminal.Gui/Views/Menu/MenuBar.cs
  38. 1 1
      Terminal.Gui/Views/MessageBox.cs
  39. 11 13
      Terminal.Gui/Views/RadioGroup.cs
  40. 17 17
      Terminal.Gui/Views/ScrollView.cs
  41. 20 20
      Terminal.Gui/Views/Slider.cs
  42. 4 4
      Terminal.Gui/Views/StatusBar.cs
  43. 8 8
      Terminal.Gui/Views/TabView.cs
  44. 1 1
      Terminal.Gui/Views/TableView/CheckBoxTableSourceWrapper.cs
  45. 1 1
      Terminal.Gui/Views/TableView/TableSelection.cs
  46. 29 28
      Terminal.Gui/Views/TableView/TableView.cs
  47. 0 19
      Terminal.Gui/Views/TextChangedEventArgs.cs
  48. 0 22
      Terminal.Gui/Views/TextChangingEventArgs.cs
  49. 75 65
      Terminal.Gui/Views/TextField.cs
  50. 18 18
      Terminal.Gui/Views/TextValidateField.cs
  51. 80 90
      Terminal.Gui/Views/TextView.cs
  52. 9 7
      Terminal.Gui/Views/Tile.cs
  53. 4 4
      Terminal.Gui/Views/TileView.cs
  54. 12 9
      Terminal.Gui/Views/TimeField.cs
  55. 1 1
      Terminal.Gui/Views/ToplevelOverlapped.cs
  56. 36 33
      Terminal.Gui/Views/TreeView/TreeView.cs
  57. 8 10
      Terminal.Gui/Views/Wizard/Wizard.cs
  58. 3 3
      UICatalog/KeyBindingsDialog.cs
  59. 3 3
      UICatalog/Scenarios/ASCIICustomButton.cs
  60. 34 79
      UICatalog/Scenarios/Adornments.cs
  61. 1 1
      UICatalog/Scenarios/AllViewsTester.cs
  62. 2 2
      UICatalog/Scenarios/BackgroundWorkerCollection.cs
  63. 12 12
      UICatalog/Scenarios/Buttons.cs
  64. 15 4
      UICatalog/Scenarios/CharacterMap.cs
  65. 1 1
      UICatalog/Scenarios/ChineseUI.cs
  66. 1 1
      UICatalog/Scenarios/Clipping.cs
  67. 2 2
      UICatalog/Scenarios/ComboBoxIteration.cs
  68. 4 4
      UICatalog/Scenarios/ComputedLayout.cs
  69. 1 1
      UICatalog/Scenarios/ContextMenus.cs
  70. 3 3
      UICatalog/Scenarios/CsvEditor.cs
  71. 43 33
      UICatalog/Scenarios/Dialogs.cs
  72. 16 16
      UICatalog/Scenarios/DynamicMenuBar.cs
  73. 11 11
      UICatalog/Scenarios/DynamicStatusBar.cs
  74. 7 7
      UICatalog/Scenarios/Editor.cs
  75. 1 1
      UICatalog/Scenarios/FileDialogExamples.cs
  76. 138 0
      UICatalog/Scenarios/HotKeys.cs
  77. 1 1
      UICatalog/Scenarios/Images.cs
  78. 2 2
      UICatalog/Scenarios/InteractiveTree.cs
  79. 1 1
      UICatalog/Scenarios/InvertColors.cs
  80. 0 386
      UICatalog/Scenarios/LabelsAsButtons.cs
  81. 1 1
      UICatalog/Scenarios/LineDrawing.cs
  82. 3 3
      UICatalog/Scenarios/ListColumns.cs
  83. 7 6
      UICatalog/Scenarios/ListViewWithSelection.cs
  84. 2 2
      UICatalog/Scenarios/ListsAndCombos.cs
  85. 3 3
      UICatalog/Scenarios/Localization.cs
  86. 3 3
      UICatalog/Scenarios/MenuBarScenario.cs
  87. 1 1
      UICatalog/Scenarios/MessageBoxes.cs
  88. 2 2
      UICatalog/Scenarios/MultiColouredTable.cs
  89. 4 4
      UICatalog/Scenarios/Progress.cs
  90. 3 3
      UICatalog/Scenarios/ProgressBarStyles.cs
  91. 1 1
      UICatalog/Scenarios/RunTExample.cs
  92. 6 6
      UICatalog/Scenarios/RuneWidthGreaterThanOne.cs
  93. 3 3
      UICatalog/Scenarios/Scrolling.cs
  94. 1 1
      UICatalog/Scenarios/SendKeys.cs
  95. 1 1
      UICatalog/Scenarios/SingleBackgroundWorker.cs
  96. 5 5
      UICatalog/Scenarios/TableEditor.cs
  97. 35 19
      UICatalog/Scenarios/Text.cs
  98. 2 2
      UICatalog/Scenarios/TextAlignments.cs
  99. 8 8
      UICatalog/Scenarios/Threading.cs
  100. 1 1
      UICatalog/Scenarios/TimeAndDate.cs

+ 1 - 1
.github/workflows/dotnet-core.yml

@@ -17,7 +17,7 @@ jobs:
     - name: Setup dotnet
       uses: actions/setup-dotnet@v4
       with:
-        dotnet-version: 8.0
+        dotnet-version: 8.x
         dotnet-quality: 'ga'
 
     - name: Install dependencies

+ 1 - 1
Example/Example.cs

@@ -61,7 +61,7 @@ public class ExampleWindow : Window
         };
 
         // When login button is clicked display a message popup
-        btnLogin.Clicked += (s, e) =>
+        btnLogin.Accept += (s, e) =>
                             {
                                 if (UserNameText.Text == "admin" && passwordText.Text == "password")
                                 {

+ 15 - 15
ReactiveExample/LoginView.cs

@@ -12,11 +12,11 @@ public class LoginView : Window, IViewFor<LoginViewModel>
 
     public LoginView (LoginViewModel viewModel)
     {
-        Title = "Reactive Extensions Example";
+        Title = $"Reactive Extensions Example - {Application.QuitKey} to Exit";
         ViewModel = viewModel;
         Label usernameLengthLabel = UsernameLengthLabel (TitleLabel ());
         TextField usernameInput = UsernameInput (usernameLengthLabel);
-        Label passwordLengthLabel = PasswordLengthLabel (usernameInput);
+        Label passwordLengthLabel = PasswordLengthLabel (usernameLengthLabel);
         TextField passwordInput = PasswordInput (passwordLengthLabel);
         Label validationLabel = ValidationLabel (passwordInput);
         Button loginButton = LoginButton (validationLabel);
@@ -42,12 +42,12 @@ public class LoginView : Window, IViewFor<LoginViewModel>
     {
         var clearButton = new Button
         {
-            X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40, Text = "Clear"
+            X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Text = "_Clear"
         };
 
         clearButton
             .Events ()
-            .Clicked
+            .Accept
             .InvokeCommand (ViewModel, x => x.Clear)
             .DisposeWith (_disposable);
         Add (clearButton);
@@ -59,12 +59,12 @@ public class LoginView : Window, IViewFor<LoginViewModel>
     {
         var loginButton = new Button
         {
-            X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40, Text = "Login"
+            X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Text = "_Login"
         };
 
         loginButton
             .Events ()
-            .Clicked
+            .Accept
             .InvokeCommand (ViewModel, x => x.Login)
             .DisposeWith (_disposable);
         Add (loginButton);
@@ -79,7 +79,7 @@ public class LoginView : Window, IViewFor<LoginViewModel>
 
         var loginProgressLabel = new Label
         {
-            X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40, Text = idle
+            AutoSize = false,  X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40, Height = 1, Text = idle
         };
 
         ViewModel
@@ -97,7 +97,7 @@ public class LoginView : Window, IViewFor<LoginViewModel>
     {
         var passwordInput = new TextField
         {
-            X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40, Text = ViewModel.Password
+            X = Pos.Right (previous) + 1, Y = Pos.Top (previous), Width = 40, Text = ViewModel.Password
         };
 
         ViewModel
@@ -119,11 +119,11 @@ public class LoginView : Window, IViewFor<LoginViewModel>
 
     private Label PasswordLengthLabel (View previous)
     {
-        var passwordLengthLabel = new Label { X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40 };
+        var passwordLengthLabel = new Label { X = Pos.Left (previous), Y = Pos.Top (previous) + 1, };
 
         ViewModel
             .WhenAnyValue (x => x.PasswordLength)
-            .Select (length => $"Password ({length} characters)")
+            .Select (length => $"_Password ({length} characters):")
             .BindTo (passwordLengthLabel, x => x.Text)
             .DisposeWith (_disposable);
         Add (passwordLengthLabel);
@@ -143,7 +143,7 @@ public class LoginView : Window, IViewFor<LoginViewModel>
     {
         var usernameInput = new TextField
         {
-            X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40, Text = ViewModel.Username
+            X = Pos.Right (previous) + 1, Y = Pos.Top (previous), Width = 40, Text = ViewModel.Username
         };
 
         ViewModel
@@ -165,11 +165,11 @@ public class LoginView : Window, IViewFor<LoginViewModel>
 
     private Label UsernameLengthLabel (View previous)
     {
-        var usernameLengthLabel = new Label { X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40 };
+        var usernameLengthLabel = new Label { X = Pos.Left (previous), Y = Pos.Top (previous) + 1 };
 
         ViewModel
             .WhenAnyValue (x => x.UsernameLength)
-            .Select (length => $"Username ({length} characters)")
+            .Select (length => $"_Username ({length} characters):")
             .BindTo (usernameLengthLabel, x => x.Text)
             .DisposeWith (_disposable);
         Add (usernameLengthLabel);
@@ -179,12 +179,12 @@ public class LoginView : Window, IViewFor<LoginViewModel>
 
     private Label ValidationLabel (View previous)
     {
-        var error = "Please, enter user name and password.";
+        var error = "Please enter a valid user name and password.";
         var success = "The input is valid!";
 
         var validationLabel = new Label
         {
-            X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40, Text = error
+           X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Text = error
         };
 
         ViewModel

+ 8 - 7
ReactiveExample/LoginViewModel.cs

@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel;
 using System.Reactive;
 using System.Reactive.Linq;
 using System.Runtime.Serialization;
@@ -37,10 +38,10 @@ public class LoginViewModel : ReactiveObject
 
         _isValid = canLogin.ToProperty (this, x => x.IsValid);
 
-        Login = ReactiveCommand.CreateFromTask<EventArgs> (
-                                                           e => Task.Delay (TimeSpan.FromSeconds (1)),
-                                                           canLogin
-                                                          );
+        Login = ReactiveCommand.CreateFromTask<CancelEventArgs> (
+                                                                 e => Task.Delay (TimeSpan.FromSeconds (1)),
+                                                                 canLogin
+                                                                );
 
         _usernameLength = this
                           .WhenAnyValue (x => x.Username)
@@ -52,7 +53,7 @@ public class LoginViewModel : ReactiveObject
                           .Select (password => password.Length)
                           .ToProperty (this, x => x.PasswordLength);
 
-        Clear = ReactiveCommand.Create<EventArgs> (e => { });
+        Clear = ReactiveCommand.Create<CancelEventArgs> (e => { });
 
         Clear.Subscribe (
                          unit =>
@@ -64,13 +65,13 @@ public class LoginViewModel : ReactiveObject
     }
 
     [IgnoreDataMember]
-    public ReactiveCommand<EventArgs, Unit> Clear { get; }
+    public ReactiveCommand<CancelEventArgs, Unit> Clear { get; }
 
     [IgnoreDataMember]
     public bool IsValid => _isValid.Value;
 
     [IgnoreDataMember]
-    public ReactiveCommand<EventArgs, Unit> Login { get; }
+    public ReactiveCommand<CancelEventArgs, Unit> Login { get; }
 
     [Reactive]
     [DataMember]

+ 1 - 2
Terminal.Gui/Application.cs

@@ -1773,7 +1773,7 @@ public static partial class Application
         {
             foreach (View view in topLevel.Subviews.Where (
                                                            v => v.KeyBindings.TryGet (
-                                                                                      keyEvent.KeyCode,
+                                                                                      keyEvent,
                                                                                       KeyBindingScope.Application,
                                                                                       out KeyBinding _
                                                                                      )
@@ -1781,7 +1781,6 @@ public static partial class Application
             {
                 if (view.KeyBindings.TryGet (keyEvent.KeyCode, KeyBindingScope.Application, out KeyBinding _))
                 {
-                    keyEvent.Scope = KeyBindingScope.Application;
                     bool? handled = view.OnInvokingKeyBindings (keyEvent);
 
                     if (handled is { } && (bool)handled)

+ 1 - 1
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -567,7 +567,7 @@ internal class CursesDriver : ConsoleDriver
             }
             else
             {
-                key = new Key (KeyCode.Esc);
+                key = Key.Esc;
             }
 
             OnKeyDown (key);

+ 1 - 1
Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs

@@ -318,7 +318,7 @@ public class FakeDriver : ConsoleDriver
 
             if (keyInfo.KeyChar != (uint)key)
             {
-                return ConsoleKeyMapping.MapToKeyCodeModifiers (keyInfo.Modifiers, (KeyCode)keyInfo.KeyChar);
+                return ConsoleKeyMapping.MapToKeyCodeModifiers (keyInfo.Modifiers, (KeyCode)keyInfo.Key);
             }
 
             if (keyInfo.Modifiers.HasFlag (ConsoleModifiers.Control)

+ 2 - 1
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1606,7 +1606,8 @@ internal class WindowsDriver : ConsoleDriver
                 }
             }
 
-            return (KeyCode)keyInfo.KeyChar;
+            // Return the Key (not KeyChar!)
+            return (KeyCode)keyInfo.Key;
         }
 
         // Handle control keys whose VK codes match the related ASCII value (those below ASCII 33) like ESC

+ 2 - 2
Terminal.Gui/FileServices/DefaultFileOperations.cs

@@ -135,14 +135,14 @@ public class DefaultFileOperations : IFileOperations
         var confirm = false;
         var btnOk = new Button { IsDefault = true, Text = Strings.btnOk };
 
-        btnOk.Clicked += (s, e) =>
+        btnOk.Accept += (s, e) =>
                          {
                              confirm = true;
                              Application.RequestStop ();
                          };
         var btnCancel = new Button { Text = Strings.btnCancel };
 
-        btnCancel.Clicked += (s, e) =>
+        btnCancel.Accept += (s, e) =>
                              {
                                  confirm = false;
                                  Application.RequestStop ();

+ 8 - 11
Terminal.Gui/Input/Command.cs

@@ -6,8 +6,14 @@ namespace Terminal.Gui;
 /// <summary>Actions which can be performed by the application or bound to keys in a <see cref="View"/> control.</summary>
 public enum Command
 {
-    /// <summary>The default command. For <see cref="View"/> this focuses the view.</summary>
-    Default,
+    /// <summary>Invoked when the HotKey for the View has been pressed.</summary>
+    HotKey,
+
+    /// <summary>Accepts the current state (e.g. list selection, button press, toggle, etc).</summary>
+    Accept,
+
+    /// <summary>Selects an item (e.g. a list item or menu item) without necessarily accepting it.</summary>
+    Select,
 
     /// <summary>Moves down one item (cell, line, etc...).</summary>
     LineDown,
@@ -131,12 +137,6 @@ public enum Command
     /// <summary>Open the selected item.</summary>
     OpenSelectedItem,
 
-    /// <summary>Toggle the checked state.</summary>
-    ToggleChecked,
-
-    /// <summary>Accepts the current state (e.g. selection, button press etc).</summary>
-    Accept,
-
     /// <summary>Toggles the Expanded or collapsed state of a a list or item (with subitems).</summary>
     ToggleExpandCollapse,
 
@@ -263,9 +263,6 @@ public enum Command
     /// <summary>Creates a new document.</summary>
     New,
 
-    /// <summary>Moves selection to an item (e.g. highlighting a different menu item) without necessarily accepting it.</summary>
-    Select,
-
     /// <summary>Shows context about the item (e.g. a context menu).</summary>
     ShowContextMenu
 }

+ 57 - 17
Terminal.Gui/Input/Key.cs

@@ -78,6 +78,16 @@ public class Key : EventArgs, IEquatable<Key>
     /// <param name="k">The key</param>
     public Key (KeyCode k) { KeyCode = k; }
 
+    /// <summary>
+    /// Copy constructor.
+    /// </summary>
+    /// <param name="key">The Key to copy</param>
+    public Key (Key key)
+    {
+        KeyCode = key.KeyCode;
+        Handled = key.Handled;
+    }
+
     /// <summary>Constructs a new <see cref="Key"/> from a char.</summary>
     /// <remarks>
     ///     <para>
@@ -144,12 +154,18 @@ public class Key : EventArgs, IEquatable<Key>
     /// </remarks>
     public Rune AsRune => ToRune (KeyCode);
 
+    private bool _handled = false;
+
     /// <summary>
     ///     Indicates if the current Key event has already been processed and the driver should stop notifying any other
-    ///     event subscriber. Its important to set this value to true specially when updating any View's layout from inside the
+    ///     event subscriber. It's important to set this value to true specially when updating any View's layout from inside the
     ///     subscriber method.
     /// </summary>
-    public bool Handled { get; set; } = false;
+    public bool Handled
+    {
+        get => _handled;
+        set => _handled = value;
+    }
 
     /// <summary>Gets a value indicating whether the Alt key was pressed (real or synthesized)</summary>
     /// <value><see langword="true"/> if is alternate; otherwise, <see langword="false"/>.</value>
@@ -182,6 +198,8 @@ public class Key : EventArgs, IEquatable<Key>
     /// </summary>
     public bool IsValid => this != Empty && NoAlt.NoShift.NoCtrl != Empty;
 
+    private readonly KeyCode _keyCode;
+
     /// <summary>The encoded key value.</summary>
     /// <para>
     ///     IMPORTANT: Lowercase alpha keys are encoded (in <see cref="Gui.KeyCode"/>) as values between 65 and 90
@@ -190,7 +208,21 @@ public class Key : EventArgs, IEquatable<Key>
     ///     for uppercase characters, these enum values represent *lowercase*, un-shifted characters.
     /// </para>
     /// <remarks>This property is the backing data for the <see cref="Key"/>. It is a <see cref="KeyCode"/> enum value.</remarks>
-    public KeyCode KeyCode { get; init; }
+    public KeyCode KeyCode
+    {
+        get => _keyCode;
+        init
+        {
+#if DEBUG
+            if (GetIsKeyCodeAtoZ (value) && (value & KeyCode.Space) != 0)
+            {
+                throw new ArgumentException ($"Invalid KeyCode: {value} is invalid.", nameof (value));
+            }
+
+#endif
+            _keyCode = value;
+        }
+    }
 
     /// <summary>
     ///     Helper for removing a shift modifier from a <see cref="Key"/>.
@@ -199,7 +231,7 @@ public class Key : EventArgs, IEquatable<Key>
     /// var AltDelete = ControlAltDelete.NoCtrl;
     /// </code>
     /// </summary>
-    public Key NoAlt => new (KeyCode & ~KeyCode.AltMask);
+    public Key NoAlt => new (this) { KeyCode = KeyCode & ~KeyCode.AltMask };
 
     /// <summary>
     ///     Helper for removing a shift modifier from a <see cref="Key"/>.
@@ -208,7 +240,7 @@ public class Key : EventArgs, IEquatable<Key>
     /// var AltDelete = ControlAltDelete.NoCtrl;
     /// </code>
     /// </summary>
-    public Key NoCtrl => new (KeyCode & ~KeyCode.CtrlMask);
+    public Key NoCtrl => new (this) { KeyCode = KeyCode & ~KeyCode.CtrlMask };
 
     /// <summary>
     ///     Helper for removing a shift modifier from a <see cref="Key"/>.
@@ -217,10 +249,7 @@ public class Key : EventArgs, IEquatable<Key>
     /// var AltDelete = ControlAltDelete.NoCtrl;
     /// </code>
     /// </summary>
-    public Key NoShift => new (KeyCode & ~KeyCode.ShiftMask);
-
-    /// <summary>Enables passing the key binding scope with the event. Default is <see cref="KeyBindingScope.Focused"/>.</summary>
-    public KeyBindingScope Scope { get; set; } = KeyBindingScope.Focused;
+    public Key NoShift => new (this) { KeyCode = KeyCode & ~KeyCode.ShiftMask };
 
     /// <summary>
     ///     Helper for specifying a shifted <see cref="Key"/>.
@@ -228,7 +257,7 @@ public class Key : EventArgs, IEquatable<Key>
     /// var ControlAltDelete = new Key(Key.Delete).WithAlt.WithDel;
     /// </code>
     /// </summary>
-    public Key WithAlt => new (KeyCode | KeyCode.AltMask);
+    public Key WithAlt => new (this) { KeyCode = KeyCode | KeyCode.AltMask };
 
     /// <summary>
     ///     Helper for specifying a shifted <see cref="Key"/>.
@@ -236,7 +265,7 @@ public class Key : EventArgs, IEquatable<Key>
     /// var ControlAltDelete = new Key(Key.Delete).WithAlt.WithDel;
     /// </code>
     /// </summary>
-    public Key WithCtrl => new (KeyCode | KeyCode.CtrlMask);
+    public Key WithCtrl => new (this) { KeyCode = KeyCode | KeyCode.CtrlMask };
 
     /// <summary>
     ///     Helper for specifying a shifted <see cref="Key"/>.
@@ -244,7 +273,7 @@ public class Key : EventArgs, IEquatable<Key>
     /// var ControlAltDelete = new Key(Key.Delete).WithAlt.WithDel;
     /// </code>
     /// </summary>
-    public Key WithShift => new (KeyCode | KeyCode.ShiftMask);
+    public Key WithShift => new (this) { KeyCode = KeyCode | KeyCode.ShiftMask };
 
     /// <summary>
     ///     Tests if a KeyCode represents a key in the range of <see cref="KeyCode.A"/> to <see cref="KeyCode.Z"/>,
@@ -369,7 +398,10 @@ public class Key : EventArgs, IEquatable<Key>
     public static implicit operator string (Key key) { return key.ToString (); }
 
     /// <inheritdoc/>
-    public override bool Equals (object obj) { return obj is Key k && k.KeyCode == KeyCode; }
+    public override bool Equals (object obj)
+    {
+        return obj is Key k && k.KeyCode == KeyCode && k.Handled == Handled;
+    }
 
     bool IEquatable<Key>.Equals (Key other) { return Equals (other); }
 
@@ -544,7 +576,7 @@ public class Key : EventArgs, IEquatable<Key>
     {
         if (string.IsNullOrEmpty (text))
         {
-            key = new Key (KeyCode.Null);
+            key = Key.Empty;
 
             return true;
         }
@@ -565,15 +597,15 @@ public class Key : EventArgs, IEquatable<Key>
             switch (parts [0])
             {
                 case "Ctrl":
-                    key = new Key (KeyCode.CtrlMask);
+                    key = KeyCode.CtrlMask;
 
                     return true;
                 case "Alt":
-                    key = new Key (KeyCode.AltMask);
+                    key = KeyCode.AltMask;
 
                     return true;
                 case "Shift":
-                    key = new Key (KeyCode.ShiftMask);
+                    key = KeyCode.ShiftMask;
 
                     return true;
             }
@@ -627,6 +659,10 @@ public class Key : EventArgs, IEquatable<Key>
                 }
             }
 
+            if (GetIsKeyCodeAtoZ (keyCode) && (keyCode & KeyCode.Space) != 0)
+            {
+                keyCode = keyCode & ~KeyCode.Space;
+            }
             key = new Key (keyCode | modifiers);
 
             return true;
@@ -643,6 +679,10 @@ public class Key : EventArgs, IEquatable<Key>
                     return true;
                 }
 
+                if (GetIsKeyCodeAtoZ (parsedKeyCode) && (parsedKeyCode & KeyCode.Space) != 0)
+                {
+                    parsedKeyCode = parsedKeyCode & ~KeyCode.Space;
+                }
                 key = new Key (parsedKeyCode | modifiers);
 
                 return true;

+ 15 - 11
Terminal.Gui/Input/KeyBinding.cs

@@ -10,10 +10,11 @@ namespace Terminal.Gui;
 /// <remarks>
 ///     <para>Key bindings are scoped to the most-focused view (<see cref="Focused"/>) by default.</para>
 /// </remarks>
+[Flags]
 public enum KeyBindingScope
 {
     /// <summary>The key binding is scoped to just the view that has focus.</summary>
-    Focused = 0,
+    Focused = 1,
 
     /// <summary>
     ///     The key binding is scoped to the View's SuperView and will be triggered even when the View does not have focus, as
@@ -29,7 +30,7 @@ public enum KeyBindingScope
     ///         </para>
     ///     </remarks>
     /// </summary>
-    HotKey,
+    HotKey = 2,
 
     /// <summary>
     ///     The key binding will be triggered regardless of which view has focus. This is typically used for global
@@ -39,7 +40,7 @@ public enum KeyBindingScope
     ///     Application-scoped key bindings are only invoked if the key down event was not handled by the focused view or
     ///     any of its subviews, and if the key down event was not bound to a <see cref="View.HotKey"/>.
     /// </remarks>
-    Application
+    Application = 4
 }
 
 /// <summary>Provides a collection of <see cref="Command"/> objects that are scoped to <see cref="KeyBindingScope"/>.</summary>
@@ -64,6 +65,7 @@ public class KeyBinding
 /// <summary>A class that provides a collection of <see cref="KeyBinding"/> objects bound to a <see cref="Key"/>.</summary>
 public class KeyBindings
 {
+    // TODO: Add a dictionary comparer that ignores Scope
     /// <summary>The collection of <see cref="KeyBinding"/> objects.</summary>
     public Dictionary<Key, KeyBinding> Bindings { get; } = new ();
 
@@ -92,16 +94,16 @@ public class KeyBindings
     /// </param>
     public void Add (Key key, KeyBindingScope scope, params Command [] commands)
     {
-        if (commands.Length == 0)
-        {
-            throw new ArgumentException (@"At least one command must be specified", nameof (commands));
-        }
-
         if (key is null || !key.IsValid)
         {
             //throw new ArgumentException ("Invalid Key", nameof (commands));
             return;
         }
+        
+        if (commands.Length == 0)
+        {
+            throw new ArgumentException (@"At least one command must be specified", nameof (commands));
+        }
 
         if (TryGet (key, out KeyBinding _))
         {
@@ -149,8 +151,10 @@ public class KeyBindings
     /// <param name="command"></param>
     public void Clear (params Command [] command)
     {
-        foreach (KeyValuePair<Key, KeyBinding> kvp in Bindings.Where (kvp => kvp.Value.Commands.SequenceEqual (command))
-                                                              .ToArray ())
+        var kvps = Bindings
+                   .Where (kvp => kvp.Value.Commands.SequenceEqual (command))
+                   .ToArray ();
+        foreach (KeyValuePair<Key, KeyBinding> kvp in kvps)
         {
             Bindings.Remove (kvp.Key);
         }
@@ -243,7 +247,7 @@ public class KeyBindings
     {
         if (key.IsValid && Bindings.TryGetValue (key, out binding))
         {
-            if (binding.Scope == scope)
+            if (scope.HasFlag (binding.Scope))
             {
                 return true;
             }

+ 3 - 3
Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs

@@ -64,19 +64,19 @@ public class AppendAutocomplete : AutocompleteBase
     /// <inheritdoc/>
     public override bool ProcessKey (Key a)
     {
-        KeyCode key = a.KeyCode;
+        Key key = a.KeyCode;
 
         if (key == SelectionKey)
         {
             return AcceptSelectionIfAny ();
         }
 
-        if (key == KeyCode.CursorUp)
+        if (key == Key.CursorUp)
         {
             return CycleSuggestion (1);
         }
 
-        if (key == KeyCode.CursorDown)
+        if (key == Key.CursorDown)
         {
             return CycleSuggestion (-1);
         }

+ 1 - 1
Terminal.Gui/Text/Autocomplete/AutocompleteBase.cs

@@ -46,7 +46,7 @@ public abstract class AutocompleteBase : IAutocomplete
 
     // TODO: Update to use Key instead of KeyCode
     /// <inheritdoc/>
-    public virtual KeyCode Reopen { get; set; } = KeyCode.Space | KeyCode.CtrlMask | KeyCode.AltMask;
+    public virtual KeyCode Reopen { get; set; } = (KeyCode)Key.Space.WithCtrl.WithAlt;
 
     /// <inheritdoc/>
     public virtual AutocompleteContext Context { get; set; }

+ 9 - 9
Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs

@@ -169,11 +169,11 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
     ///     Handle key events before <see cref="HostControl"/> e.g. to make key events like up/down apply to the
     ///     autocomplete control instead of changing the cursor position in the underlying text view.
     /// </summary>
-    /// <param name="a">The key event.</param>
+    /// <param name="key">The key event.</param>
     /// <returns><c>true</c>if the key can be handled <c>false</c>otherwise.</returns>
-    public override bool ProcessKey (Key a)
+    public override bool ProcessKey (Key key)
     {
-        if (SuggestionGenerator.IsWordChar ((Rune)a))
+        if (SuggestionGenerator.IsWordChar ((Rune)key))
         {
             Visible = true;
             ManipulatePopup ();
@@ -182,7 +182,7 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
             return false;
         }
 
-        if (a.KeyCode == Reopen)
+        if (key == Reopen)
         {
             Context.Canceled = false;
 
@@ -201,14 +201,14 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
             return false;
         }
 
-        if (a.KeyCode == KeyCode.CursorDown)
+        if (key == Key.CursorDown)
         {
             MoveDown ();
 
             return true;
         }
 
-        if (a.KeyCode == KeyCode.CursorUp)
+        if (key == Key.CursorUp)
         {
             MoveUp ();
 
@@ -227,12 +227,12 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
             return false;
         }*/
 
-        if (a.KeyCode == SelectionKey)
+        if (key == SelectionKey)
         {
             return Select ();
         }
 
-        if (a.KeyCode == CloseKey)
+        if (key == CloseKey)
         {
             Close ();
             Context.Canceled = true;
@@ -249,7 +249,7 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
     {
         if (!Context.Canceled && Suggestions.Count > 0 && !Visible && HostControl?.HasFocus == true)
         {
-            ProcessKey (new Key ((KeyCode)Suggestions [0].Title [0]));
+            ProcessKey (new Key (Suggestions [0].Title [0]));
         }
         else if (!Visible || HostControl?.HasFocus == false || Suggestions.Count == 0)
         {

+ 26 - 0
Terminal.Gui/Text/StringEventArgs.cs

@@ -0,0 +1,26 @@
+using System.ComponentModel;
+
+namespace Terminal.Gui;
+
+/// <summary>Cancellable event args for string-based property change events.</summary>
+public class StringEventArgs : CancelEventArgs
+{
+    /// <summary>
+    /// Initializes a new instance of <see cref="StringEventArgs"/>
+    /// </summary>
+    public StringEventArgs () {}
+
+    /// <summary>Initializes a new instance of <see cref="StringEventArgs"/></summary>
+    /// <param name="oldString">The old string.</param>
+    /// <param name="newString">The new string.</param>
+    public StringEventArgs (string oldString, string newString)
+    {
+        OldValue = oldString;
+        NewValue = newString;
+    }
+    /// <summary>The new string.</summary>
+    public string NewValue { get; set; }
+
+    /// <summary>The old string.</summary>
+    public string OldValue { get; set; }
+}

+ 5 - 3
Terminal.Gui/Text/TextFormatter.cs

@@ -1,4 +1,4 @@
-namespace Terminal.Gui;
+namespace Terminal.Gui;
 
 /// <summary>Text alignment enumeration, controls how text is displayed.</summary>
 public enum TextAlignment
@@ -216,7 +216,7 @@ public class TextFormatter
     /// <summary>Gets or sets whether the <see cref="TextFormatter"/> needs to format the text.</summary>
     /// <remarks>
     ///     <para>If <see langword="false"/> when Draw is called, the Draw call will be faster.</para>
-    ///     <para>Used by <see cref="Draw(Rectangle, Attribute, Attribute, Rectangle, bool, ConsoleDriver)"/></para>
+    ///     <para>Used by <see cref="Draw"/></para>
     ///     <para>Set to <see langword="true"/> when any of the properties of <see cref="TextFormatter"/> are set.</para>
     ///     <para>Set to <see langword="false"/> when the text is formatted (if <see cref="GetLines"/> is accessed).</para>
     /// </remarks>
@@ -2003,7 +2003,7 @@ public class TextFormatter
         if (string.IsNullOrEmpty (text) || hotKeySpecifier == (Rune)0xFFFF)
         {
             hotPos = -1;
-            hotKey = KeyCode.Null;
+            hotKey = Key.Empty;
 
             return false;
         }
@@ -2072,6 +2072,8 @@ public class TextFormatter
 
                 hotKey = newHotKey;
 
+                //hotKey.Scope = KeyBindingScope.HotKey;
+
                 return true;
             }
         }

+ 16 - 42
Terminal.Gui/View/Adornment/Border.cs

@@ -1,4 +1,4 @@
-namespace Terminal.Gui;
+namespace Terminal.Gui;
 
 /// <summary>The Border for a <see cref="View"/>.</summary>
 /// <remarks>
@@ -192,26 +192,7 @@ public class Border : Adornment
 
         Driver.Clip = savedClip;
     }
-
-    /// <summary>Draws the title for a Window-style view.</summary>
-    /// <param name="region">Screen relative region where the title will be drawn.</param>
-    /// <param name="title">The title.</param>
-    public void DrawTitle (Rectangle region, string title)
-    {
-        int width = region.Width;
-
-        if (!string.IsNullOrEmpty (title))
-        {
-            Driver.Move (region.X + 2, region.Y);
-
-            //Driver.AddRune (' ');
-            string str = title.EnumerateRunes ().Sum (r => Math.Max (r.GetColumns (), 1)) >= width
-                             ? TextFormatter.Format (title, width, false, false) [0]
-                             : title;
-            Driver.AddStr (str);
-        }
-    }
-
+    
     /// <inheritdoc/>
     public override void OnDrawContent (Rectangle contentArea)
     {
@@ -259,10 +240,14 @@ public class Border : Adornment
         int titleY = borderBounds.Y;
         var titleBarsLength = 0; // the little vertical thingies
 
-        int maxTitleWidth = Math.Min (
-                                      Parent.Title.GetColumns (),
-                                      Math.Min (screenBounds.Width - 4, borderBounds.Width - 4)
-                                     );
+        int maxTitleWidth = Math.Max (0,
+                                      Math.Min (
+                                          Parent.TitleTextFormatter.FormatAndGetSize ().Width,
+                                          Math.Min (screenBounds.Width - 4, borderBounds.Width - 4)
+                                          )
+                                      );
+        Parent.TitleTextFormatter.Size = new Size (maxTitleWidth, 1);
+
         int sideLineLength = borderBounds.Height;
         bool canDrawBorder = borderBounds.Width > 0 && borderBounds.Height > 0;
 
@@ -300,10 +285,9 @@ public class Border : Adornment
 
         if (canDrawBorder && Thickness.Top > 0 && maxTitleWidth > 0 && !string.IsNullOrEmpty (Parent?.Title))
         {
-            Attribute prevAttr = Driver.GetAttribute ();
-            Driver.SetAttribute (Parent.HasFocus ? Parent.GetFocusColor () : Parent.GetNormalColor ());
-            DrawTitle (new Rectangle (borderBounds.X, titleY, maxTitleWidth, 1), Parent?.Title);
-            Driver.SetAttribute (prevAttr);
+            Parent.TitleTextFormatter.Draw (new Rect (borderBounds.X + 2, titleY, maxTitleWidth, 1),
+                                            Parent.HasFocus ? Parent.GetFocusColor () : Parent.GetNormalColor (),
+                                            Parent.HasFocus ? Parent.GetFocusColor () : Parent.GetHotNormalColor ());
         }
 
         if (canDrawBorder && LineStyle != LineStyle.None)
@@ -480,19 +464,9 @@ public class Border : Adornment
                 // Redraw title 
                 if (drawTop && maxTitleWidth > 0 && !string.IsNullOrEmpty (Parent?.Title))
                 {
-                    prevAttr = Driver.GetAttribute ();
-
-                    if (ColorScheme is { })
-                    {
-                        Driver.SetAttribute (HasFocus ? GetHotNormalColor () : GetNormalColor ());
-                    }
-                    else
-                    {
-                        Driver.SetAttribute (Parent.HasFocus ? Parent.GetHotNormalColor () : Parent.GetNormalColor ());
-                    }
-
-                    DrawTitle (new Rectangle (borderBounds.X, titleY, Parent.Title.GetColumns (), 1), Parent?.Title);
-                    Driver.SetAttribute (prevAttr);
+                    Parent.TitleTextFormatter.Draw (new Rect (borderBounds.X + 2, titleY, maxTitleWidth, 1),
+                                                    Parent.HasFocus ? Parent.GetFocusColor () : Parent.GetNormalColor (),
+                                                    Parent.HasFocus ? Parent.GetFocusColor () : Parent.GetNormalColor ());
                 }
 
                 //Left

+ 27 - 0
Terminal.Gui/View/StateEventArgs.cs

@@ -0,0 +1,27 @@
+#nullable enable
+using System.ComponentModel;
+
+namespace Terminal.Gui;
+
+/// <summary><see cref="EventArgs"/> for events that convey state changes to a <see cref="View"/> class.</summary>
+/// <remarks>
+/// Events that use this class can be cancellable. The <see cref="CancelEventArgs.Cancel"/> property should be set to
+/// <see langword="true"/> to prevent the state change from occurring.
+/// </remarks>
+public class StateEventArgs<T> : CancelEventArgs
+{
+    /// <summary>Creates a new instance of the <see cref="StateEventArgs{T}"/> class.</summary>
+    /// <param name="oldValue"></param>
+    /// <param name="newValue"></param>
+    public StateEventArgs (T oldValue, T newValue)
+    {
+        OldValue = oldValue;
+        NewValue = newValue;
+    }
+
+    /// <summary>The new state</summary>
+    public T NewValue { get; set; }
+
+    /// <summary>The previous state</summary>
+    public T OldValue { get; }
+}

+ 0 - 23
Terminal.Gui/View/TitleEventArgs.cs

@@ -1,23 +0,0 @@
-namespace Terminal.Gui;
-
-/// <summary>Event arguments for Title change events.</summary>
-public class TitleEventArgs : EventArgs
-{
-    /// <summary>Initializes a new instance of <see cref="TitleEventArgs"/></summary>
-    /// <param name="oldTitle">The <see cref="View.Title"/> that is/has been replaced.</param>
-    /// <param name="newTitle">The new <see cref="View.Title"/> to be replaced.</param>
-    public TitleEventArgs (string oldTitle, string newTitle)
-    {
-        OldTitle = oldTitle;
-        NewTitle = newTitle;
-    }
-
-    /// <summary>Flag which allows canceling the Title change.</summary>
-    public bool Cancel { get; set; }
-
-    /// <summary>The new Window Title.</summary>
-    public string NewTitle { get; set; }
-
-    /// <summary>The old Window Title.</summary>
-    public string OldTitle { get; set; }
-}

+ 0 - 20
Terminal.Gui/View/ToggleEventArgs.cs

@@ -1,20 +0,0 @@
-namespace Terminal.Gui;
-
-/// <summary><see cref="EventArgs"/> for the <see cref="CheckBox.Toggled"/> event</summary>
-public class ToggleEventArgs : EventArgs
-{
-    /// <summary>Creates a new instance of the <see cref="ToggleEventArgs"/> class.</summary>
-    /// <param name="oldValue"></param>
-    /// <param name="newValue"></param>
-    public ToggleEventArgs (bool? oldValue, bool? newValue)
-    {
-        OldValue = oldValue;
-        NewValue = newValue;
-    }
-
-    /// <summary>The new checked state</summary>
-    public bool? NewValue { get; }
-
-    /// <summary>The previous checked state</summary>
-    public bool? OldValue { get; }
-}

+ 98 - 63
Terminal.Gui/View/View.cs

@@ -114,7 +114,6 @@ namespace Terminal.Gui;
 public partial class View : Responder, ISupportInitializeNotification
 {
     private bool _oldEnabled;
-    private string _title = string.Empty;
 
     /// <summary>Gets or sets whether a view is cleared if the <see cref="Visible"/> property is <see langword="false"/>.</summary>
     public bool ClearOnVisibleFalse { get; set; } = true;
@@ -182,32 +181,6 @@ public partial class View : Responder, ISupportInitializeNotification
     /// <remarks>The id should be unique across all Views that share a SuperView.</remarks>
     public string Id { get; set; } = "";
 
-    /// <summary>
-    ///     The title to be displayed for this <see cref="View"/>. The title will be displayed if <see cref="Border"/>.
-    ///     <see cref="Thickness.Top"/> is greater than 0.
-    /// </summary>
-    /// <value>The title.</value>
-    public string Title
-    {
-        get => _title;
-        set
-        {
-            if (!OnTitleChanging (_title, value))
-            {
-                string old = _title;
-                _title = value;
-                SetNeedsDisplay ();
-#if DEBUG
-                if (_title is { } && string.IsNullOrEmpty (Id))
-                {
-                    Id = _title;
-                }
-#endif
-                OnTitleChanged (old, _title);
-            }
-        }
-    }
-
     /// <inheritdoc/>
     /// >
     public override bool Visible
@@ -244,42 +217,9 @@ public partial class View : Responder, ISupportInitializeNotification
     /// <inheritdoc/>
     public override void OnEnabledChanged () { EnabledChanged?.Invoke (this, EventArgs.Empty); }
 
-    /// <summary>Called when the <see cref="View.Title"/> has been changed. Invokes the <see cref="TitleChanged"/> event.</summary>
-    /// <param name="oldTitle">The <see cref="View.Title"/> that is/has been replaced.</param>
-    /// <param name="newTitle">The new <see cref="View.Title"/> to be replaced.</param>
-    public virtual void OnTitleChanged (string oldTitle, string newTitle)
-    {
-        var args = new TitleEventArgs (oldTitle, newTitle);
-        TitleChanged?.Invoke (this, args);
-    }
-
-    /// <summary>
-    ///     Called before the <see cref="View.Title"/> changes. Invokes the <see cref="TitleChanging"/> event, which can
-    ///     be cancelled.
-    /// </summary>
-    /// <param name="oldTitle">The <see cref="View.Title"/> that is/has been replaced.</param>
-    /// <param name="newTitle">The new <see cref="View.Title"/> to be replaced.</param>
-    /// <returns>`true` if an event handler canceled the Title change.</returns>
-    public virtual bool OnTitleChanging (string oldTitle, string newTitle)
-    {
-        var args = new TitleEventArgs (oldTitle, newTitle);
-        TitleChanging?.Invoke (this, args);
-
-        return args.Cancel;
-    }
-
     /// <inheritdoc/>
     public override void OnVisibleChanged () { VisibleChanged?.Invoke (this, EventArgs.Empty); }
 
-    /// <summary>Event fired after the <see cref="View.Title"/> has been changed.</summary>
-    public event EventHandler<TitleEventArgs> TitleChanged;
-
-    /// <summary>
-    ///     Event fired when the <see cref="View.Title"/> is changing. Set <see cref="TitleEventArgs.Cancel"/> to `true`
-    ///     to cancel the Title change.
-    /// </summary>
-    public event EventHandler<TitleEventArgs> TitleChanging;
-
     /// <summary>Pretty prints the View</summary>
     /// <returns></returns>
     public override string ToString () { return $"{GetType ().Name}({Id}){Frame}"; }
@@ -328,6 +268,101 @@ public partial class View : Responder, ISupportInitializeNotification
         return true;
     }
 
+    #region Title
+
+    private string _title = string.Empty;
+
+    /// <summary>Gets the <see cref="Gui.TextFormatter"/> used to format <see cref="Title"/>.</summary>
+    internal TextFormatter TitleTextFormatter { get; init; } = new ();
+
+    /// <summary>
+    ///     The title to be displayed for this <see cref="View"/>. The title will be displayed if <see cref="Border"/>.
+    ///     <see cref="Thickness.Top"/> is greater than 0. The title can be used to set the <see cref="HotKey"/>
+    ///     for the view by prefixing character with <see cref="HotKeySpecifier"/> (e.g. <c>"T_itle"</c>).
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Set the <see cref="HotKeySpecifier"/> to enable hotkey support. To disable Title-based hotkey support set
+    ///         <see cref="HotKeySpecifier"/> to <c>(Rune)0xffff</c>.
+    ///     </para>
+    ///     <para>
+    ///         Only the first HotKey specifier found in <see cref="Title"/> is supported.
+    ///     </para>
+    ///     <para>
+    ///         To cause the hotkey to be rendered with <see cref="Text"/>,
+    ///         set <c>View.</c><see cref="TextFormatter.HotKeySpecifier"/> to the desired character.
+    ///     </para>
+    /// </remarks>
+    /// <value>The title.</value>
+    public string Title
+    {
+        get => _title;
+        set
+        {
+            if (value == _title)
+            {
+                return;
+            }
+
+            if (!OnTitleChanging (_title, value))
+            {
+                string old = _title;
+                _title = value;
+                TitleTextFormatter.Text = _title;
+                TitleTextFormatter.Size = new Size (
+                                                    TextFormatter.GetWidestLineLength (TitleTextFormatter.Text)
+                                                    - (TitleTextFormatter.Text?.Contains ((char)HotKeySpecifier.Value) == true
+                                                           ? Math.Max (HotKeySpecifier.GetColumns (), 0)
+                                                           : 0),
+                                                    1);
+                SetHotKeyFromTitle ();
+                SetNeedsDisplay ();
+#if DEBUG
+                if (_title is { } && string.IsNullOrEmpty (Id))
+                {
+                    Id = _title;
+                }
+#endif // DEBUG
+                OnTitleChanged (old, _title);
+            }
+        }
+    }
+
+    /// <summary>Called when the <see cref="View.Title"/> has been changed. Invokes the <see cref="TitleChanged"/> event.</summary>
+    /// <param name="oldTitle">The <see cref="View.Title"/> that is/has been replaced.</param>
+    /// <param name="newTitle">The new <see cref="View.Title"/> to be replaced.</param>
+    public virtual void OnTitleChanged (string oldTitle, string newTitle)
+    {
+        StateEventArgs<string> args = new (oldTitle, newTitle);
+        TitleChanged?.Invoke (this, args);
+    }
+
+    /// <summary>
+    ///     Called before the <see cref="View.Title"/> changes. Invokes the <see cref="TitleChanging"/> event, which can
+    ///     be cancelled.
+    /// </summary>
+    /// <param name="oldTitle">The <see cref="View.Title"/> that is/has been replaced.</param>
+    /// <param name="newTitle">The new <see cref="View.Title"/> to be replaced.</param>
+    /// <returns>`true` if an event handler canceled the Title change.</returns>
+    public virtual bool OnTitleChanging (string oldTitle, string newTitle)
+    {
+        StateEventArgs<string> args = new (oldTitle, newTitle);
+        TitleChanging?.Invoke (this, args);
+
+        return args.Cancel;
+    }
+
+    /// <summary>Event fired after the <see cref="View.Title"/> has been changed.</summary>
+    public event EventHandler<StateEventArgs<string>> TitleChanged;
+
+    /// <summary>
+    ///     Event fired when the <see cref="View.Title"/> is changing. Set <see cref="CancelEventArgs.Cancel"/> to `true`
+    ///     to cancel the Title change.
+    /// </summary>
+    public event EventHandler<StateEventArgs<string>> TitleChanging;
+
+    #endregion
+
     #region Constructors and Initialization
 
     /// <summary>Initializes a new instance of <see cref="View"/>.</summary>
@@ -347,7 +382,9 @@ public partial class View : Responder, ISupportInitializeNotification
     /// </remarks>
     public View ()
     {
-        TextFormatter.HotKeyChanged += TextFormatter_HotKeyChanged;
+        HotKeySpecifier = (Rune)'_';
+        TitleTextFormatter.HotKeyChanged += TitleTextFormatter_HotKeyChanged;
+
         TextDirection = TextDirection.LeftRight_TopBottom;
         Text = string.Empty;
 
@@ -434,8 +471,6 @@ public partial class View : Responder, ISupportInitializeNotification
         // These calls were moved from BeginInit as they access Bounds which is indeterminate until EndInit is called.
         UpdateTextDirection (TextDirection);
         UpdateTextFormatterText ();
-        SetHotKey ();
-
         OnResizeNeeded ();
 
         if (_subviews is { })

+ 115 - 71
Terminal.Gui/View/ViewKeyboard.cs

@@ -1,40 +1,63 @@
-namespace Terminal.Gui;
+using System.ComponentModel;
+
+namespace Terminal.Gui;
 
 public partial class View
 {
     private void AddCommands ()
     {
-        // By default, the Default command is bound to the HotKey enabling focus
-        AddCommand (
-                    Command.Default,
-                    () =>
-                    {
-                        if (CanFocus)
-                        {
-                            SetFocus ();
-
-                            return true;
-                        }
-
-                        return false;
-                    }
-                   );
-
-        // By default the Accept command does nothing
-        AddCommand (Command.Accept, () => false);
+        // By default, the HotKey command sets the focus
+        AddCommand (Command.HotKey, OnHotKey);
+
+        // By default, the Accept command raises the Accept event
+        AddCommand (Command.Accept, OnAccept);
     }
 
     #region HotKey Support
 
+    /// <summary>
+    /// Called when the HotKey command (<see cref="Command.HotKey"/>) is invoked. Causes this view to be focused.
+    /// </summary>
+    /// <returns>If <see langword="true"/> the command was canceled.</returns>
+    private bool? OnHotKey ()
+    {
+        if (CanFocus)
+        {
+            SetFocus ();
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /// <summary>
+    /// Cancelable event fired when the <see cref="Command.Accept"/> command is invoked. Set <see cref="CancelEventArgs.Cancel"/>
+    /// to cancel the event.
+    /// </summary>
+    public event EventHandler<CancelEventArgs> Accept;
+
+    /// <summary>
+    /// Called when the <see cref="Command.Accept"/> command is invoked. Fires the <see cref="Accept"/>
+    /// event.
+    /// </summary>
+    /// <returns>If <see langword="true"/> the event was canceled.</returns>
+    public bool? OnAccept ()
+    {
+        var args = new CancelEventArgs ();
+        Accept?.Invoke (this, args);
+        return args.Cancel;
+    }
+
     /// <summary>Invoked when the <see cref="HotKey"/> is changed.</summary>
     public event EventHandler<KeyChangedEventArgs> HotKeyChanged;
 
     private Key _hotKey = new ();
-    private void TextFormatter_HotKeyChanged (object sender, KeyChangedEventArgs e) { HotKeyChanged?.Invoke (this, e); }
+    private void TitleTextFormatter_HotKeyChanged (object sender, KeyChangedEventArgs e) { HotKeyChanged?.Invoke (this, e); }
 
     /// <summary>
     ///     Gets or sets the hot key defined for this view. Pressing the hot key on the keyboard while this view has focus will
-    ///     invoke the <see cref="Command.Default"/> and <see cref="Command.Accept"/> commands. <see cref="Command.Default"/>
+    ///     invoke the <see cref="Command.HotKey"/> and <see cref="Command.Accept"/> commands. <see cref="Command.HotKey"/>
     ///     causes the view to be focused and <see cref="Command.Accept"/> does nothing. By default, the HotKey is
     ///     automatically set to the first character of <see cref="Text"/> that is prefixed with with
     ///     <see cref="HotKeySpecifier"/>.
@@ -55,18 +78,18 @@ public partial class View
     ///     </para>
     ///     <para>
     ///         By default, when the Hot Key is set, key bindings are added for both the base key (e.g.
-    ///         <see cref="KeyCode.D3"/>) and the Alt-shifted key (e.g. <see cref="KeyCode.D3"/> |
-    ///         <see cref="KeyCode.AltMask"/>). This behavior can be overriden by overriding
+    ///         <see cref="Key.D3"/>) and the Alt-shifted key (e.g. <see cref="Key.D3"/>.
+    ///         <see cref="Key.WithAlt"/>). This behavior can be overriden by overriding
     ///         <see cref="AddKeyBindingsForHotKey"/>.
     ///     </para>
     ///     <para>
-    ///         By default, when the HotKey is set to <see cref="Key.A"/> through <see cref="KeyCode.Z"/> key bindings will
+    ///         By default, when the HotKey is set to <see cref="Key.A"/> through <see cref="Key.Z"/> key bindings will
     ///         be added for both the un-shifted and shifted versions. This means if the HotKey is <see cref="Key.A"/>, key
     ///         bindings for <c>Key.A</c> and <c>Key.A.WithShift</c> will be added. This behavior can be overriden by
     ///         overriding <see cref="AddKeyBindingsForHotKey"/>.
     ///     </para>
     ///     <para>If the hot key is changed, the <see cref="HotKeyChanged"/> event is fired.</para>
-    ///     <para>Set to <see cref="KeyCode.Null"/> to disable the hot key.</para>
+    ///     <para>Set to <see cref="Key.Empty"/> to disable the hot key.</para>
     /// </remarks>
     public virtual Key HotKey
     {
@@ -84,7 +107,9 @@ public partial class View
             if (AddKeyBindingsForHotKey (_hotKey, value))
             {
                 // This will cause TextFormatter_HotKeyChanged to be called, firing HotKeyChanged
-                _hotKey = TextFormatter.HotKey = value;
+                // BUGBUG: _hotkey should be set BEFORE setting TextFormatter.HotKey
+                _hotKey = value;
+                TitleTextFormatter.HotKey = value;
             }
         }
     }
@@ -95,8 +120,8 @@ public partial class View
     /// </summary>
     /// <remarks>
     ///     <para>
-    ///         By default key bindings are added for both the base key (e.g. <see cref="Key.D3"/>) and the Alt-shifted key
-    ///         (e.g. <c>Key.D3.WithAlt</c> This behavior can be overriden by overriding <see cref="AddKeyBindingsForHotKey"/>.
+    ///         By default, key bindings are added for both the base key (e.g. <see cref="Key.D3"/>) and the Alt-shifted key
+    ///         (e.g. <c>Key.D3.WithAlt</c>) This behavior can be overriden by overriding <see cref="AddKeyBindingsForHotKey"/>.
     ///     </para>
     ///     <para>
     ///         By default, when <paramref name="hotKey"/> is <see cref="Key.A"/> through <see cref="Key.Z"/> key bindings
@@ -104,10 +129,6 @@ public partial class View
     ///         key bindings for <c>Key.A</c> and <c>Key.A.WithShift</c> will be added. This behavior can be overriden by
     ///         overriding <see cref="AddKeyBindingsForHotKey"/>.
     ///     </para>
-    ///     <para>
-    ///         For each of the bound keys <see cref="Command.Default"/> causes the view to be focused and
-    ///         <see cref="Command.Accept"/> does nothing.
-    ///     </para>
     /// </remarks>
     /// <param name="prevHotKey">The HotKey <paramref name="hotKey"/> is replacing. Key bindings for this key will be removed.</param>
     /// <param name="hotKey">The new HotKey. If <see cref="Key.Empty"/> <paramref name="prevHotKey"/> bindings will be removed.</param>
@@ -115,7 +136,7 @@ public partial class View
     /// <exception cref="ArgumentException"></exception>
     public virtual bool AddKeyBindingsForHotKey (Key prevHotKey, Key hotKey)
     {
-        if ((KeyCode)_hotKey == hotKey)
+        if (_hotKey == hotKey)
         {
             return false;
         }
@@ -158,7 +179,7 @@ public partial class View
             KeyBindings.Remove (prevHotKey.WithAlt);
         }
 
-        if (_hotKey.KeyCode is >= KeyCode.A and <= KeyCode.Z)
+        if (_hotKey.IsKeyCodeAtoZ)
         {
             // Remove the shift version
             if (KeyBindings.TryGet (prevHotKey.WithShift, out _))
@@ -174,17 +195,17 @@ public partial class View
         }
 
         // Add the new 
-        if (newKey != KeyCode.Null)
+        if (newKey != Key.Empty)
         {
             // Add the base and Alt key
-            KeyBindings.Add (newKey, KeyBindingScope.HotKey, Command.Default, Command.Accept);
-            KeyBindings.Add (newKey.WithAlt, KeyBindingScope.HotKey, Command.Default, Command.Accept);
+            KeyBindings.Add (newKey, KeyBindingScope.HotKey, Command.HotKey);
+            KeyBindings.Add (newKey.WithAlt, KeyBindingScope.HotKey, Command.HotKey);
 
             // If the Key is A..Z, add ShiftMask and AltMask | ShiftMask
             if (newKey.IsKeyCodeAtoZ)
             {
-                KeyBindings.Add (newKey.WithShift, KeyBindingScope.HotKey, Command.Default, Command.Accept);
-                KeyBindings.Add (newKey.WithShift.WithAlt, KeyBindingScope.HotKey, Command.Default, Command.Accept);
+                KeyBindings.Add (newKey.WithShift, KeyBindingScope.HotKey, Command.HotKey);
+                KeyBindings.Add (newKey.WithShift.WithAlt, KeyBindingScope.HotKey, Command.HotKey);
             }
         }
 
@@ -199,37 +220,32 @@ public partial class View
     {
         get
         {
-            if (TextFormatter is { })
-            {
-                return TextFormatter.HotKeySpecifier;
-            }
-
-            return new Rune ('\xFFFF');
+            return TitleTextFormatter.HotKeySpecifier;
         }
         set
         {
-            TextFormatter.HotKeySpecifier = value;
-            SetHotKey ();
+            TitleTextFormatter.HotKeySpecifier = value;
+            SetHotKeyFromTitle ();
         }
     }
 
-    private void SetHotKey ()
+    private void SetHotKeyFromTitle ()
     {
-        if (TextFormatter is null || HotKeySpecifier == new Rune ('\xFFFF'))
+        if (TitleTextFormatter == null || HotKeySpecifier == new Rune ('\xFFFF'))
         {
             return; // throw new InvalidOperationException ("Can't set HotKey unless a TextFormatter has been created");
         }
 
-        if (TextFormatter.FindHotKey (_text, HotKeySpecifier, out _, out Key hk))
+        if (TextFormatter.FindHotKey (_title, HotKeySpecifier, out _, out Key hk))
         {
-            if (_hotKey.KeyCode != hk)
+            if (_hotKey != hk)
             {
                 HotKey = hk;
             }
         }
         else
         {
-            HotKey = KeyCode.Null;
+            HotKey = Key.Empty;
         }
     }
 
@@ -623,16 +639,15 @@ public partial class View
     /// </returns>
     public virtual bool? OnInvokingKeyBindings (Key keyEvent)
     {
-        // fire event
-        // BUGBUG: KeyEventArgs doesn't include scope, so the event never sees it.
-        if (keyEvent.Scope == KeyBindingScope.Application || keyEvent.Scope == KeyBindingScope.HotKey)
+        // fire event only if there's an app or hotkey binding for the key
+        if (KeyBindings.TryGet (keyEvent, KeyBindingScope.Application | KeyBindingScope.HotKey, out KeyBinding _))
         {
             InvokingKeyBindings?.Invoke (this, keyEvent);
-
             if (keyEvent.Handled)
             {
                 return true;
             }
+
         }
 
         // * If no key binding was found, `InvokeKeyBindings` returns `null`.
@@ -653,16 +668,16 @@ public partial class View
         // Now, process any key bindings in the subviews that are tagged to KeyBindingScope.HotKey.
         foreach (View view in Subviews.Where (
                                               v => v.KeyBindings.TryGet (
-                                                                         keyEvent.KeyCode,
+                                                                         keyEvent,
                                                                          KeyBindingScope.HotKey,
                                                                          out KeyBinding _
                                                                         )
                                              ))
         {
             // TODO: I think this TryGet is not needed due to the one in the lambda above. Use `Get` instead?
-            if (view.KeyBindings.TryGet (keyEvent.KeyCode, KeyBindingScope.HotKey, out KeyBinding binding))
+            if (view.KeyBindings.TryGet (keyEvent, KeyBindingScope.HotKey, out KeyBinding binding))
             {
-                keyEvent.Scope = KeyBindingScope.HotKey;
+                //keyEvent.Scope = KeyBindingScope.HotKey;
                 handled = view.OnInvokingKeyBindings (keyEvent);
 
                 if (handled is { } && (bool)handled)
@@ -682,19 +697,18 @@ public partial class View
     public event EventHandler<Key> InvokingKeyBindings;
 
     /// <summary>
-    ///     Invokes any binding that is registered on this <see cref="View"/> and matches the <paramref name="keyEvent"/>
+    ///     Invokes any binding that is registered on this <see cref="View"/> and matches the <paramref name="key"/>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </summary>
-    /// <param name="keyEvent">The key event passed.</param>
+    /// <param name="key">The key event passed.</param>
     /// <returns>
-    ///     <see langword="null"/> if no command was bound the <paramref name="keyEvent"/>. <see langword="true"/> if
+    ///     <see langword="null"/> if no command was bound the <paramref name="key"/>. <see langword="true"/> if
     ///     commands were invoked and at least one handled the command. <see langword="false"/> if commands were invoked and at
     ///     none handled the command.
     /// </returns>
-    protected bool? InvokeKeyBindings (Key keyEvent)
+    protected bool? InvokeKeyBindings (Key key)
     {
         bool? toReturn = null;
-        KeyCode key = keyEvent.KeyCode;
 
         if (!KeyBindings.TryGet (key, out KeyBinding binding))
         {
@@ -706,13 +720,7 @@ public partial class View
             if (!CommandImplementations.ContainsKey (command))
             {
                 throw new NotSupportedException (
-                                                 @$"A KeyBinding was set up for the command {
-                                                     command
-                                                 } ({
-                                                     keyEvent.KeyCode
-                                                 }) but that command is not supported by this View ({
-                                                     GetType ().Name
-                                                 })"
+                                                 @$"A KeyBinding was set up for the command {command} ({key}) but that command is not supported by this View ({GetType ().Name})"
                                                 );
             }
 
@@ -732,6 +740,42 @@ public partial class View
         return toReturn;
     }
 
+    /// <summary>
+    ///     Invokes the specified commands.
+    /// </summary>
+    /// <param name="commands"></param>
+    /// <returns>
+    ///     <see langword="null"/> if no command was found.
+    ///     <see langword="true"/> if the command was invoked and it handled the command.
+    ///     <see langword="false"/> if the command was invoked and it did not handle the command.
+    /// </returns>
+    public bool? InvokeCommands (Command [] commands)
+    {
+        bool? toReturn = null;
+
+        foreach (Command command in commands)
+        {
+            if (!CommandImplementations.ContainsKey (command))
+            {
+                throw new NotSupportedException (@$"{command} is not supported by ({GetType ().Name}).");
+            }
+
+            // each command has its own return value
+            bool? thisReturn = InvokeCommand (command);
+
+            // if we haven't got anything yet, the current command result should be used
+            toReturn ??= thisReturn;
+
+            // if ever see a true then that's what we will return
+            if (thisReturn ?? false)
+            {
+                toReturn = true;
+            }
+        }
+
+        return toReturn;
+    }
+
     /// <summary>Invokes the specified command.</summary>
     /// <param name="command"></param>
     /// <returns>

+ 36 - 11
Terminal.Gui/View/ViewText.cs

@@ -33,31 +33,48 @@ public partial class View
     ///         The text will word-wrap to additional lines if it does not fit horizontally. If <see cref="Bounds"/>'s height
     ///         is 1, the text will be clipped.
     ///     </para>
-    ///     <para>
-    ///         Set the <see cref="HotKeySpecifier"/> to enable hotkey support. To disable hotkey support set
-    ///         <see cref="HotKeySpecifier"/> to <c>(Rune)0xffff</c>.
-    ///     </para>
     ///     <para>If <see cref="AutoSize"/> is <c>true</c>, the <see cref="Bounds"/> will be adjusted to fit the text.</para>
+    ///     <para>When the text changes, the <see cref="TextChanged"/> is fired.</para>
     /// </remarks>
     public virtual string Text
     {
         get => _text;
         set
         {
+            if (value == _text)
+            {
+                return;
+            }
+
+            string old = _text;
             _text = value;
-            SetHotKey ();
             UpdateTextFormatterText ();
             OnResizeNeeded ();
-
 #if DEBUG
             if (_text is { } && string.IsNullOrEmpty (Id))
             {
                 Id = _text;
             }
 #endif
+            OnTextChanged (old, Text);
         }
     }
 
+    /// <summary>
+    /// Called when the <see cref="Text"/> has changed. Fires the <see cref="TextChanged"/> event.
+    /// </summary>
+    /// <param name="oldValue"></param>
+    /// <param name="newValue"></param>
+    public void OnTextChanged (string oldValue, string newValue)
+    {
+        TextChanged?.Invoke (this, new StateEventArgs<string> (oldValue, newValue));
+    }
+
+    /// <summary>
+    ///     Text changed event, raised when the text has changed.
+    /// </summary>
+    public event EventHandler<StateEventArgs<string>> TextChanged;
+
     /// <summary>
     ///     Gets or sets how the View's <see cref="Text"/> is aligned horizontally when drawn. Changing this property will
     ///     redisplay the <see cref="View"/>.
@@ -156,7 +173,15 @@ public partial class View
     ///     Gets the width or height of the <see cref="TextFormatter.HotKeySpecifier"/> characters in the
     ///     <see cref="Text"/> property.
     /// </summary>
-    /// <remarks>Only the first HotKey specifier found in <see cref="Text"/> is supported.</remarks>
+    /// <remarks>
+    ///     <para>
+    ///         This is for <see cref="Text"/>, not <see cref="Title"/>. For <see cref="Text"/> to show the hotkey,
+    ///         set <c>View.</c><see cref="TextFormatter.HotKeySpecifier"/> to the desired character.
+    ///     </para>
+    ///     <para>
+    ///         Only the first HotKey specifier found in <see cref="Text"/> is supported.
+    ///     </para>
+    /// </remarks>
     /// <param name="isWidth">
     ///     If <see langword="true"/> (the default) the width required for the HotKey specifier is returned.
     ///     Otherwise the height is returned.
@@ -170,13 +195,13 @@ public partial class View
     {
         if (isWidth)
         {
-            return TextFormatter.IsHorizontalDirection (TextDirection) && TextFormatter.Text?.Contains ((char)HotKeySpecifier.Value) == true
-                       ? Math.Max (HotKeySpecifier.GetColumns (), 0)
+            return TextFormatter.IsHorizontalDirection (TextDirection) && TextFormatter.Text?.Contains ((char)TextFormatter.HotKeySpecifier.Value) == true
+                       ? Math.Max (TextFormatter.HotKeySpecifier.GetColumns (), 0)
                        : 0;
         }
 
-        return TextFormatter.IsVerticalDirection (TextDirection) && TextFormatter.Text?.Contains ((char)HotKeySpecifier.Value) == true
-                   ? Math.Max (HotKeySpecifier.GetColumns (), 0)
+        return TextFormatter.IsVerticalDirection (TextDirection) && TextFormatter.Text?.Contains ((char)TextFormatter.HotKeySpecifier.Value) == true
+                   ? Math.Max (TextFormatter.HotKeySpecifier.GetColumns (), 0)
                    : 0;
     }
 

+ 34 - 31
Terminal.Gui/Views/Button.cs

@@ -7,17 +7,17 @@
 
 namespace Terminal.Gui;
 
-/// <summary>Button is a <see cref="View"/> that provides an item that invokes raises the <see cref="Clicked"/> event.</summary>
+/// <summary>Button is a <see cref="View"/> that provides an item that invokes raises the <see cref="View.Accept"/> event.</summary>
 /// <remarks>
 ///     <para>
-///         Provides a button showing text that raises the <see cref="Clicked"/> event when clicked on with a mouse or
+///         Provides a button showing text that raises the <see cref="View.Accept"/> event when clicked on with a mouse or
 ///         when the user presses SPACE, ENTER, or the <see cref="View.HotKey"/>. The hot key is the first letter or digit
 ///         following the first underscore ('_') in the button text.
 ///     </para>
 ///     <para>Use <see cref="View.HotKeySpecifier"/> to change the hot key specifier from the default of ('_').</para>
 ///     <para>
 ///         When the button is configured as the default (<see cref="IsDefault"/>) and the user presses the ENTER key, if
-///         no other <see cref="View"/> processes the key, the <see cref="Button"/>'s <see cref="Clicked"/> event will will
+///         no other <see cref="View"/> processes the key, the <see cref="Button"/>'s <see cref="View.Accept"/> event will
 ///         be fired.
 ///     </para>
 /// </remarks>
@@ -36,8 +36,6 @@ public class Button : View
         TextAlignment = TextAlignment.Centered;
         VerticalTextAlignment = VerticalTextAlignment.Middle;
 
-        HotKeySpecifier = new Rune ('_');
-
         _leftBracket = Glyphs.LeftBracket;
         _rightBracket = Glyphs.RightBracket;
         _leftDefault = Glyphs.LeftDefaultIndicator;
@@ -50,18 +48,36 @@ public class Button : View
         AutoSize = true;
 
         // Override default behavior of View
-        // Command.Default sets focus
-        AddCommand (
-                    Command.Accept,
-                    () =>
-                    {
-                        OnClicked ();
-
-                        return true;
-                    }
-                   );
-        KeyBindings.Add (Key.Space, Command.Default, Command.Accept);
-        KeyBindings.Add (Key.Enter, Command.Default, Command.Accept);
+        AddCommand (Command.HotKey, () =>
+                                     {
+                                         SetFocus ();
+                                         return !OnAccept ();
+                                     });
+
+        KeyBindings.Add (Key.Space, Command.HotKey);
+        KeyBindings.Add (Key.Enter, Command.HotKey);
+
+        TitleChanged += Button_TitleChanged;
+    }
+
+    private void Button_TitleChanged (object sender, StateEventArgs<string> e)
+    {
+        base.Text = e.NewValue;
+        TextFormatter.HotKeySpecifier = HotKeySpecifier;
+    }
+
+    /// <inheritdoc />
+    public override string Text
+    {
+        get => base.Title;
+        set => base.Text = base.Title = value;
+    }
+
+    /// <inheritdoc />
+    public override Rune HotKeySpecifier
+    {
+        get => base.HotKeySpecifier;
+        set => TextFormatter.HotKeySpecifier = base.HotKeySpecifier = value;
     }
 
     /// <summary>Gets or sets whether the <see cref="Button"/> is the default action to activate in a dialog.</summary>
@@ -83,16 +99,6 @@ public class Button : View
     /// <summary></summary>
     public bool NoPadding { get; set; }
 
-    /// <summary>
-    ///     The event fired when the user clicks the primary mouse button within the Bounds of this <see cref="View"/> or
-    ///     if the user presses the action key while this view is focused. (TODO: IsDefault)
-    /// </summary>
-    /// <remarks>
-    ///     Client code can hook up to this event, it is raised when the button is activated either with the mouse or the
-    ///     keyboard.
-    /// </remarks>
-    public event EventHandler Clicked;
-
     /// <inheritdoc/>
     public override bool MouseEvent (MouseEvent me)
     {
@@ -107,7 +113,7 @@ public class Button : View
                     Draw ();
                 }
 
-                OnClicked ();
+                OnAccept ();
             }
 
             return true;
@@ -116,9 +122,6 @@ public class Button : View
         return false;
     }
 
-    /// <summary>Virtual method to invoke the <see cref="Clicked"/> event.</summary>
-    public virtual void OnClicked () { Clicked?.Invoke (this, EventArgs.Empty); }
-
     /// <inheritdoc/>
     public override bool OnEnter (View view)
     {

+ 81 - 106
Terminal.Gui/Views/CheckBox.cs

@@ -1,4 +1,5 @@
-namespace Terminal.Gui;
+#nullable enable
+namespace Terminal.Gui;
 
 /// <summary>The <see cref="CheckBox"/> <see cref="View"/> shows an on/off toggle that the user can set</summary>
 public class CheckBox : View
@@ -18,7 +19,6 @@ public class CheckBox : View
         _charNullChecked = Glyphs.NullChecked;
         _charChecked = Glyphs.Checked;
         _charUnChecked = Glyphs.UnChecked;
-        HotKeySpecifier = (Rune)'_';
 
         // Ensures a height of 1 if AutoSize is set to false
         Height = 1;
@@ -27,25 +27,33 @@ public class CheckBox : View
         AutoSize = true;
 
         // Things this view knows how to do
-        AddCommand (Command.ToggleChecked, () => ToggleChecked ());
+        AddCommand (Command.Accept, OnToggled);
+        AddCommand (Command.HotKey, OnToggled);
 
-        AddCommand (
-                    Command.Accept,
-                    () =>
-                    {
-                        if (!HasFocus)
-                        {
-                            SetFocus ();
-                        }
+        // Default keybindings for this view
+        KeyBindings.Add (Key.Space, Command.Accept);
 
-                        ToggleChecked ();
+        TitleChanged += Checkbox_TitleChanged;
+    }
 
-                        return true;
-                    }
-                   );
+    private void Checkbox_TitleChanged (object? sender, StateEventArgs<string> e)
+    {
+        base.Text = e.NewValue;
+        TextFormatter.HotKeySpecifier = HotKeySpecifier;
+    }
 
-        // Default keybindings for this view
-        KeyBindings.Add (Key.Space, Command.ToggleChecked);
+    /// <inheritdoc />
+    public override string Text
+    {
+        get => base.Title;
+        set => base.Text = base.Title = value;
+    }
+
+    /// <inheritdoc />
+    public override Rune HotKeySpecifier
+    {
+        get => base.HotKeySpecifier;
+        set => TextFormatter.HotKeySpecifier = base.HotKeySpecifier = value;
     }
 
     /// <summary>
@@ -79,43 +87,6 @@ public class CheckBox : View
         }
     }
 
-    /// <inheritdoc/>
-    public override Key HotKey
-    {
-        get => base.HotKey;
-        set
-        {
-            if (value is null)
-            {
-                throw new ArgumentException (nameof (value));
-            }
-
-            Key prev = base.HotKey;
-
-            if (prev != value)
-            {
-                base.HotKey = TextFormatter.HotKey = value;
-
-                // Also add Alt+HotKey
-                if (prev != Key.Empty && KeyBindings.TryGet (prev.WithAlt, out _))
-                {
-                    if (value.KeyCode == KeyCode.Null)
-                    {
-                        KeyBindings.Remove (prev.WithAlt);
-                    }
-                    else
-                    {
-                        KeyBindings.Replace (prev.WithAlt, value.WithAlt);
-                    }
-                }
-                else if (value != Key.Empty)
-                {
-                    KeyBindings.Add (value.WithAlt, Command.Accept);
-                }
-            }
-        }
-    }
-
     /// <inheritdoc/>
     public override bool MouseEvent (MouseEvent me)
     {
@@ -124,9 +95,7 @@ public class CheckBox : View
             return false;
         }
 
-        ToggleChecked ();
-
-        return true;
+        return OnToggled () == true;
     }
 
     /// <inheritdoc/>
@@ -138,17 +107,61 @@ public class CheckBox : View
     }
 
     /// <summary>Called when the <see cref="Checked"/> property changes. Invokes the <see cref="Toggled"/> event.</summary>
-    public virtual void OnToggled (ToggleEventArgs e) { Toggled?.Invoke (this, e); }
+    /// <remarks>
+    /// </remarks>
+    /// <returns>If <see langword="true"/> the <see cref="Toggled"/> event was canceled.</returns>
+    public bool? OnToggled ()
+    {
+        StateEventArgs<bool?> e = new (Checked, false);
+
+        if (AllowNullChecked)
+        {
+            switch (Checked)
+            {
+                case null:
+                    e.NewValue = true;
+
+                    break;
+                case true:
+                    e.NewValue = false;
+
+                    break;
+                case false:
+                    e.NewValue = null;
+
+                    break;
+            }
+        }
+        else
+        {
+            e.NewValue = !Checked;
+        }
+
+        Toggled?.Invoke (this, e);
+        if (e.Cancel)
+        {
+            return e.Cancel;
+        }
+
+        Checked = e.NewValue;
+
+        SetNeedsDisplay ();
+        SetFocus ();
+        OnAccept ();
+
+        return true;
+    }
 
     /// <inheritdoc/>
     public override void PositionCursor () { Move (0, 0); }
 
-    /// <summary>Toggled event, raised when the <see cref="CheckBox"/>  is toggled.</summary>
+    /// <summary>Toggled event, raised when the <see cref="CheckBox"/> is toggled.</summary>
     /// <remarks>
-    ///     Client code can hook up to this event, it is raised when the <see cref="CheckBox"/> is activated either with
-    ///     the mouse or the keyboard. The passed <c>bool</c> contains the previous state.
+    /// <para>
+    ///    This event can be cancelled. If cancelled, the <see cref="CheckBox"/> will not change its state.
+    /// </para>
     /// </remarks>
-    public event EventHandler<ToggleEventArgs> Toggled;
+    public event EventHandler<StateEventArgs<bool?>>? Toggled;
 
     /// <inheritdoc/>
     protected override void UpdateTextFormatterText ()
@@ -171,58 +184,20 @@ public class CheckBox : View
     private Rune GetCheckedState ()
     {
         return Checked switch
-               {
-                   true => _charChecked,
-                   false => _charUnChecked,
-                   var _ => _charNullChecked
-               };
+        {
+            true => _charChecked,
+            false => _charUnChecked,
+            var _ => _charNullChecked
+        };
     }
 
     private string GetFormatterText ()
     {
-        if (AutoSize || string.IsNullOrEmpty (Text) || Frame.Width <= 2)
+        if (AutoSize || string.IsNullOrEmpty (Title) || Frame.Width <= 2)
         {
             return Text;
         }
 
         return Text [..Math.Min (Frame.Width - 2, Text.GetRuneCount ())];
     }
-
-    private bool ToggleChecked ()
-    {
-        if (!HasFocus)
-        {
-            SetFocus ();
-        }
-
-        bool? previousChecked = Checked;
-
-        if (AllowNullChecked)
-        {
-            switch (previousChecked)
-            {
-                case null:
-                    Checked = true;
-
-                    break;
-                case true:
-                    Checked = false;
-
-                    break;
-                case false:
-                    Checked = null;
-
-                    break;
-            }
-        }
-        else
-        {
-            Checked = !Checked;
-        }
-
-        OnToggled (new ToggleEventArgs (previousChecked, Checked));
-        SetNeedsDisplay ();
-
-        return true;
-    }
 }

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

@@ -197,10 +197,10 @@ public class ColorPicker : View
     /// <summary>Add the KeyBindinds.</summary>
     private void AddKeyBindings ()
     {
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-        KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.CursorLeft, Command.Left);
+        KeyBindings.Add (Key.CursorRight, Command.Right);
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
     }
 
     /// <summary>Draw a box for one color.</summary>

+ 21 - 16
Terminal.Gui/Views/ComboBox.cs

@@ -6,6 +6,7 @@
 //
 
 using System.Collections;
+using System.ComponentModel;
 
 namespace Terminal.Gui;
 
@@ -30,6 +31,7 @@ public class ComboBox : View
         _listview = new ComboListView (this, HideDropdownListOnClick) { CanFocus = true, TabStop = false };
 
         _search.TextChanged += Search_Changed;
+        _search.Accept += Search_Accept;
 
         _listview.Y = Pos.Bottom (_search);
         _listview.OpenSelectedItem += (sender, a) => Selected ();
@@ -66,7 +68,7 @@ public class ComboBox : View
 
                      SetNeedsLayout ();
                      SetNeedsDisplay ();
-                     Search_Changed (this, new TextChangedEventArgs (Text));
+                     Search_Changed (this, new StateEventArgs<string> (string.Empty, Text));
                  };
 
         // Things this view knows how to do
@@ -84,16 +86,16 @@ public class ComboBox : View
         AddCommand (Command.UnixEmulation, () => UnixEmulation ());
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.Enter, Command.Accept);
-        KeyBindings.Add (KeyCode.F4, Command.ToggleExpandCollapse);
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-        KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
-        KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
-        KeyBindings.Add (KeyCode.Home, Command.TopHome);
-        KeyBindings.Add (KeyCode.End, Command.BottomEnd);
-        KeyBindings.Add (KeyCode.Esc, Command.Cancel);
-        KeyBindings.Add (KeyCode.U | KeyCode.CtrlMask, Command.UnixEmulation);
+        KeyBindings.Add (Key.Enter, Command.Accept);
+        KeyBindings.Add (Key.F4, Command.ToggleExpandCollapse);
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.PageDown, Command.PageDown);
+        KeyBindings.Add (Key.PageUp, Command.PageUp);
+        KeyBindings.Add (Key.Home, Command.TopHome);
+        KeyBindings.Add (Key.End, Command.BottomEnd);
+        KeyBindings.Add (Key.Esc, Command.Cancel);
+        KeyBindings.Add (Key.U.WithCtrl, Command.UnixEmulation);
     }
 
     /// <inheritdoc/>
@@ -184,8 +186,8 @@ public class ComboBox : View
             if (SuperView is { } && SuperView.Subviews.Contains (this))
             {
                 SelectedItem = -1;
-                _search.Text = "";
-                Search_Changed (this, new TextChangedEventArgs (""));
+                _search.Text = string.Empty;
+                Search_Changed (this, new StateEventArgs<string> (string.Empty, _search.Text)); 
                 SetNeedsDisplay ();
             }
         }
@@ -651,11 +653,14 @@ public class ComboBox : View
         SetSearchSet ();
     }
 
-    private void Search_Changed (object sender, TextChangedEventArgs e)
+    // Tell TextField to handle Accept Command (Enter)
+    void Search_Accept (object sender, CancelEventArgs e) { e.Cancel = true; }
+
+    private void Search_Changed (object sender, StateEventArgs<string> e)
     {
         if (_source is null)
         {
-            // Object initialization		
+            // Object initialization
             return;
         }
 
@@ -714,7 +719,7 @@ public class ComboBox : View
 
         SetValue (_listview.SelectedItem > -1 ? _searchset [_listview.SelectedItem] : _text);
         _search.CursorPosition = _search.Text.GetColumns ();
-        Search_Changed (this, new TextChangedEventArgs (_search.Text));
+        Search_Changed (this, new StateEventArgs<string> (_search.Text, _search.Text));
         OnOpenSelectedItem ();
         Reset (true);
         HideList ();

+ 12 - 8
Terminal.Gui/Views/DateField.cs

@@ -183,15 +183,15 @@ public class DateField : TextField
         }
     }
 
-    private void DateField_Changing (object sender, TextChangingEventArgs e)
+    private void DateField_Changing (object sender, StateEventArgs<string> e)
     {
         try
         {
             var spaces = 0;
 
-            for (var i = 0; i < e.NewText.Length; i++)
+            for (var i = 0; i < e.NewValue.Length; i++)
             {
-                if (e.NewText [i] == ' ')
+                if (e.NewValue [i] == ' ')
                 {
                     spaces++;
                 }
@@ -202,14 +202,14 @@ public class DateField : TextField
             }
 
             spaces += FormatLength;
-            string trimedText = e.NewText [..spaces];
+            string trimedText = e.NewValue [..spaces];
             spaces -= FormatLength;
             trimedText = trimedText.Replace (new string (' ', spaces), " ");
             var date = Convert.ToDateTime (trimedText).ToString (_format.Trim ());
 
-            if ($" {date}" != e.NewText)
+            if ($" {date}" != e.NewValue)
             {
-                e.NewText = $" {date}".Replace (RightToLeftMark, "");
+                e.NewValue = $" {date}".Replace (RightToLeftMark, "");
             }
 
             AdjCursorPosition (CursorPosition);
@@ -402,11 +402,10 @@ public class DateField : TextField
         AddCommand (Command.Right, () => MoveRight ());
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.Delete, Command.DeleteCharRight);
+        KeyBindings.Add (Key.Delete, Command.DeleteCharRight);
         KeyBindings.Add (Key.D.WithCtrl, Command.DeleteCharRight);
 
         KeyBindings.Add (Key.Backspace, Command.DeleteCharLeft);
-        KeyBindings.Add (Key.D.WithAlt, Command.DeleteCharLeft);
 
         KeyBindings.Add (Key.Home, Command.LeftHome);
         KeyBindings.Add (Key.A.WithCtrl, Command.LeftHome);
@@ -419,6 +418,11 @@ public class DateField : TextField
 
         KeyBindings.Add (Key.CursorRight, Command.Right);
         KeyBindings.Add (Key.F.WithCtrl, Command.Right);
+
+#if UNIX_KEY_BINDINGS
+        KeyBindings.Add (Key.D.WithAlt, Command.DeleteCharLeft);
+#endif
+
     }
 
     private bool SetText (Rune key)

+ 2 - 2
Terminal.Gui/Views/DatePicker.cs

@@ -222,7 +222,7 @@ public class DatePicker : View
             Text = GetBackButtonText ()
         };
 
-        _previousMonthButton.Clicked += (sender, e) =>
+        _previousMonthButton.Accept += (sender, e) =>
                                         {
                                             Date = _date.AddMonths (-1);
                                             CreateCalendar ();
@@ -239,7 +239,7 @@ public class DatePicker : View
             Text = GetBackButtonText ()
         };
 
-        _nextMonthButton.Clicked += (sender, e) =>
+        _nextMonthButton.Accept += (sender, e) =>
                                     {
                                         Date = _date.AddMonths (1);
                                         CreateCalendar ();

+ 15 - 15
Terminal.Gui/Views/FileDialog.cs

@@ -67,7 +67,7 @@ public class FileDialog : Dialog
         {
             Y = Pos.AnchorEnd (1), X = Pos.Function (CalculateOkButtonPosX), IsDefault = true, Text = Style.OkButtonText
         };
-        _btnOk.Clicked += (s, e) => Accept (true);
+        _btnOk.Accept += (s, e) => Accept (true);
 
         _btnOk.KeyDown += (s, k) =>
                           {
@@ -83,19 +83,19 @@ public class FileDialog : Dialog
                                   NavigateIf (k, KeyCode.CursorUp, _tableView);
                                   NavigateIf (k, KeyCode.CursorRight, _btnOk);
                               };
-        _btnCancel.Clicked += (s, e) => { Application.RequestStop (); };
+        _btnCancel.Accept += (s, e) => { Application.RequestStop (); };
 
         _btnUp = new Button { X = 0, Y = 1, NoPadding = true };
         _btnUp.Text = GetUpButtonText ();
-        _btnUp.Clicked += (s, e) => _history.Up ();
+        _btnUp.Accept += (s, e) => _history.Up ();
 
         _btnBack = new Button { X = Pos.Right (_btnUp) + 1, Y = 1, NoPadding = true };
         _btnBack.Text = GetBackButtonText ();
-        _btnBack.Clicked += (s, e) => _history.Back ();
+        _btnBack.Accept += (s, e) => _history.Back ();
 
         _btnForward = new Button { X = Pos.Right (_btnBack) + 1, Y = 1, NoPadding = true };
         _btnForward.Text = GetForwardButtonText ();
-        _btnForward.Clicked += (s, e) => _history.Forward ();
+        _btnForward.Accept += (s, e) => _history.Forward ();
 
         _tbPath = new TextField { Width = Dim.Fill (), CaptionColor = new Color (Color.Black) };
 
@@ -128,7 +128,7 @@ public class FileDialog : Dialog
             FullRowSelect = true,
             CollectionNavigator = new FileDialogCollectionNavigator (this)
         };
-        _tableView.KeyBindings.Add (KeyCode.Space, Command.ToggleChecked);
+        _tableView.KeyBindings.Add (Key.Space, Command.Select);
         _tableView.MouseClick += OnTableViewMouseClick;
         _tableView.Style.InvertSelectedCellFirstCharacter = true;
         Style.TableStyle = _tableView.Style;
@@ -184,7 +184,7 @@ public class FileDialog : Dialog
 
         _btnToggleSplitterCollapse = new Button { Y = Pos.AnchorEnd (1), Text = GetToggleSplitterText (false) };
 
-        _btnToggleSplitterCollapse.Clicked += (s, e) =>
+        _btnToggleSplitterCollapse.Accept += (s, e) =>
                                               {
                                                   Tile tile = _splitContainer.Tiles.ElementAt (0);
 
@@ -200,7 +200,7 @@ public class FileDialog : Dialog
             CaptionColor = new Color (Color.Black),
             Width = 30,
             Y = Pos.AnchorEnd (1),
-            HotKey = KeyCode.F | KeyCode.AltMask
+            HotKey = Key.F.WithAlt
         };
         _spinnerView = new SpinnerView { X = Pos.Right (_tbFind) + 1, Y = Pos.AnchorEnd (1), Visible = false };
 
@@ -248,10 +248,10 @@ public class FileDialog : Dialog
         _tableView.KeyUp += (s, k) => k.Handled = TableView_KeyUp (k);
         _tableView.SelectedCellChanged += TableView_SelectedCellChanged;
 
-        _tableView.KeyBindings.Add (KeyCode.Home, Command.TopHome);
-        _tableView.KeyBindings.Add (KeyCode.End, Command.BottomEnd);
-        _tableView.KeyBindings.Add (KeyCode.Home | KeyCode.ShiftMask, Command.TopHomeExtend);
-        _tableView.KeyBindings.Add (KeyCode.End | KeyCode.ShiftMask, Command.BottomEndExtend);
+        _tableView.KeyBindings.Add (Key.Home, Command.TopHome);
+        _tableView.KeyBindings.Add (Key.End, Command.BottomEnd);
+        _tableView.KeyBindings.Add (Key.Home.WithShift, Command.TopHomeExtend);
+        _tableView.KeyBindings.Add (Key.End.WithShift, Command.BottomEndExtend);
 
         _treeView.KeyDown += (s, k) =>
                              {
@@ -657,7 +657,7 @@ public class FileDialog : Dialog
         ApplySort ();
     }
 
-    private void Accept (IEnumerable<FileSystemInfoStats> toMultiAccept)
+    private new void Accept (IEnumerable<FileSystemInfoStats> toMultiAccept)
     {
         if (!AllowsMultipleSelection)
         {
@@ -676,7 +676,7 @@ public class FileDialog : Dialog
         FinishAccept ();
     }
 
-    private void Accept (IFileInfo f)
+    private new void Accept (IFileInfo f)
     {
         if (!IsCompatibleWithOpenMode (f.FullName, out string reason))
         {
@@ -696,7 +696,7 @@ public class FileDialog : Dialog
         FinishAccept ();
     }
 
-    private void Accept (bool allowMulti)
+    private new void Accept (bool allowMulti)
     {
         if (allowMulti && TryAcceptMulti ())
         {

+ 4 - 4
Terminal.Gui/Views/GraphView/GraphView.cs

@@ -73,10 +73,10 @@ public class GraphView : View
                     }
                    );
 
-        KeyBindings.Add (KeyCode.CursorRight, Command.ScrollRight);
-        KeyBindings.Add (KeyCode.CursorLeft, Command.ScrollLeft);
-        KeyBindings.Add (KeyCode.CursorUp, Command.ScrollUp);
-        KeyBindings.Add (KeyCode.CursorDown, Command.ScrollDown);
+        KeyBindings.Add (Key.CursorRight, Command.ScrollRight);
+        KeyBindings.Add (Key.CursorLeft, Command.ScrollLeft);
+        KeyBindings.Add (Key.CursorUp, Command.ScrollUp);
+        KeyBindings.Add (Key.CursorDown, Command.ScrollDown);
 
         // Not bound by default (preserves backwards compatibility)
         //KeyBindings.Add (Key.PageUp, Command.PageUp);

+ 17 - 17
Terminal.Gui/Views/HexView.cs

@@ -54,7 +54,7 @@ public class HexView : View
         AddCommand (Command.Right, () => MoveRight ());
         AddCommand (Command.LineDown, () => MoveDown (bytesPerLine));
         AddCommand (Command.LineUp, () => MoveUp (bytesPerLine));
-        AddCommand (Command.ToggleChecked, () => ToggleSide ());
+        AddCommand (Command.Accept, () => ToggleSide ());
         AddCommand (Command.PageUp, () => MoveUp (bytesPerLine * Frame.Height));
         AddCommand (Command.PageDown, () => MoveDown (bytesPerLine * Frame.Height));
         AddCommand (Command.TopHome, () => MoveHome ());
@@ -69,24 +69,24 @@ public class HexView : View
                    );
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-        KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-        KeyBindings.Add (KeyCode.Enter, Command.ToggleChecked);
+        KeyBindings.Add (Key.CursorLeft, Command.Left);
+        KeyBindings.Add (Key.CursorRight, Command.Right);
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.Enter, Command.Accept);
 
-        KeyBindings.Add ('v' + KeyCode.AltMask, Command.PageUp);
-        KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
+        KeyBindings.Add (Key.V.WithAlt, Command.PageUp);
+        KeyBindings.Add (Key.PageUp, Command.PageUp);
 
-        KeyBindings.Add (KeyCode.V | KeyCode.CtrlMask, Command.PageDown);
-        KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
+        KeyBindings.Add (Key.V.WithCtrl, Command.PageDown);
+        KeyBindings.Add (Key.PageDown, Command.PageDown);
 
-        KeyBindings.Add (KeyCode.Home, Command.TopHome);
-        KeyBindings.Add (KeyCode.End, Command.BottomEnd);
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.CtrlMask, Command.StartOfLine);
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.CtrlMask, Command.EndOfLine);
-        KeyBindings.Add (KeyCode.CursorUp | KeyCode.CtrlMask, Command.StartOfPage);
-        KeyBindings.Add (KeyCode.CursorDown | KeyCode.CtrlMask, Command.EndOfPage);
+        KeyBindings.Add (Key.Home, Command.TopHome);
+        KeyBindings.Add (Key.End, Command.BottomEnd);
+        KeyBindings.Add (Key.CursorLeft.WithCtrl, Command.StartOfLine);
+        KeyBindings.Add (Key.CursorRight.WithCtrl, Command.EndOfLine);
+        KeyBindings.Add (Key.CursorUp.WithCtrl, Command.StartOfPage);
+        KeyBindings.Add (Key.CursorDown.WithCtrl, Command.EndOfPage);
 
         LayoutComplete += HexView_LayoutComplete;
     }
@@ -478,7 +478,7 @@ public class HexView : View
         }
 
         // Ignore control characters and other special keys
-        if (keyEvent.KeyCode < KeyCode.Space || keyEvent.KeyCode > KeyCode.CharMask)
+        if (keyEvent < Key.Space || keyEvent.KeyCode > KeyCode.CharMask)
         {
             return false;
         }

+ 42 - 41
Terminal.Gui/Views/Label.cs

@@ -1,4 +1,6 @@
-namespace Terminal.Gui;
+using System.Reflection.Metadata.Ecma335;
+
+namespace Terminal.Gui;
 
 /// <summary>
 ///     The Label <see cref="View"/> displays a string at a given position and supports multiple lines separated by
@@ -17,38 +19,44 @@ public class Label : View
         AutoSize = true;
 
         // Things this view knows how to do
-        AddCommand (
-                    Command.Default,
-                    () =>
-                    {
-                        // BUGBUG: This is a hack, but it does work.
-                        bool can = CanFocus;
-                        CanFocus = true;
-                        SetFocus ();
-                        SuperView.FocusNext ();
-                        CanFocus = can;
-
-                        return true;
-                    }
-                   );
-        AddCommand (Command.Accept, () => AcceptKey ());
+        AddCommand (Command.HotKey, FocusNext);
 
         // Default key bindings for this view
-        KeyBindings.Add (KeyCode.Space, Command.Accept);
+        KeyBindings.Add (Key.Space, Command.Accept);
+
+        TitleChanged += Label_TitleChanged;
+    }
+
+    private void Label_TitleChanged (object sender, StateEventArgs<string> e)
+    {
+        base.Text = e.NewValue;
+        TextFormatter.HotKeySpecifier = HotKeySpecifier;
+    }
+
+    /// <inheritdoc />
+    public override string Text
+    {
+        get => base.Title;
+        set => base.Text = base.Title = value;
     }
 
-    /// <summary>
-    ///     The event fired when the user clicks the primary mouse button within the Bounds of this <see cref="View"/> or
-    ///     if the user presses the action key while this view is focused. (TODO: IsDefault)
-    /// </summary>
-    /// <remarks>
-    ///     Client code can hook up to this event, it is raised when the button is activated either with the mouse or the
-    ///     keyboard.
-    /// </remarks>
-    public event EventHandler Clicked;
+    /// <inheritdoc />
+    public override Rune HotKeySpecifier
+    {
+        get => base.HotKeySpecifier;
+        set => TextFormatter.HotKeySpecifier = base.HotKeySpecifier = value;
+    }
 
-    /// <summary>Virtual method to invoke the <see cref="Clicked"/> event.</summary>
-    public virtual void OnClicked () { Clicked?.Invoke (this, EventArgs.Empty); }
+    private new bool? FocusNext ()
+    {
+        var me = SuperView?.Subviews.IndexOf (this) ?? -1;
+        if (me != -1 && me < SuperView?.Subviews.Count - 1)
+        {
+            SuperView?.Subviews [me + 1].SetFocus ();
+        }
+
+        return true;
+    }
 
     /// <inheritdoc/>
     public override bool OnEnter (View view)
@@ -77,6 +85,11 @@ public class Label : View
 
         if (mouseEvent.Flags == MouseFlags.Button1Clicked)
         {
+            if (!CanFocus)
+            {
+                FocusNext ();
+            }
+
             if (!HasFocus && SuperView is { })
             {
                 if (!SuperView.HasFocus)
@@ -88,23 +101,11 @@ public class Label : View
                 SetNeedsDisplay ();
             }
 
-            OnClicked ();
+            OnAccept ();
 
             return true;
         }
 
         return false;
     }
-
-    private bool AcceptKey ()
-    {
-        if (!HasFocus)
-        {
-            SetFocus ();
-        }
-
-        OnClicked ();
-
-        return true;
-    }
 }

+ 22 - 16
Terminal.Gui/Views/ListView.cs

@@ -113,26 +113,27 @@ public class ListView : View
         AddCommand (Command.PageDown, () => MovePageDown ());
         AddCommand (Command.TopHome, () => MoveHome ());
         AddCommand (Command.BottomEnd, () => MoveEnd ());
+        AddCommand (Command.Accept, () => OnOpenSelectedItem ());
         AddCommand (Command.OpenSelectedItem, () => OnOpenSelectedItem ());
-        AddCommand (Command.ToggleChecked, () => MarkUnmarkRow ());
+        AddCommand (Command.Select, () => MarkUnmarkRow ());
 
         // Default keybindings for all ListViews
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-        KeyBindings.Add (KeyCode.P | KeyCode.CtrlMask, Command.LineUp);
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.P.WithCtrl, Command.LineUp);
 
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
-        KeyBindings.Add (KeyCode.N | KeyCode.CtrlMask, Command.LineDown);
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.N.WithCtrl, Command.LineDown);
 
-        KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
+        KeyBindings.Add (Key.PageUp, Command.PageUp);
 
-        KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
-        KeyBindings.Add (KeyCode.V | KeyCode.CtrlMask, Command.PageDown);
+        KeyBindings.Add (Key.PageDown, Command.PageDown);
+        KeyBindings.Add (Key.V.WithCtrl, Command.PageDown);
 
-        KeyBindings.Add (KeyCode.Home, Command.TopHome);
+        KeyBindings.Add (Key.Home, Command.TopHome);
 
-        KeyBindings.Add (KeyCode.End, Command.BottomEnd);
+        KeyBindings.Add (Key.End, Command.BottomEnd);
 
-        KeyBindings.Add (KeyCode.Enter, Command.OpenSelectedItem);
+        KeyBindings.Add (Key.Enter, Command.OpenSelectedItem);
     }
 
     /// <summary>Gets or sets whether this <see cref="ListView"/> allows items to be marked.</summary>
@@ -150,11 +151,11 @@ public class ListView : View
 
             if (_allowsMarking)
             {
-                KeyBindings.Add (KeyCode.Space, Command.ToggleChecked);
+                KeyBindings.Add (Key.Space, Command.Select);
             }
             else
             {
-                KeyBindings.Remove (KeyCode.Space);
+                KeyBindings.Remove (Key.Space);
             }
 
             SetNeedsDisplay ();
@@ -691,9 +692,10 @@ public class ListView : View
         return base.OnEnter (view);
     }
 
+    // TODO: This should be cancelable
     /// <summary>Invokes the <see cref="OpenSelectedItem"/> event if it is defined.</summary>
-    /// <returns></returns>
-    public virtual bool OnOpenSelectedItem ()
+    /// <returns><see langword="true"/> if the <see cref="OpenSelectedItem"/> event was fired.</returns>
+    public bool OnOpenSelectedItem ()
     {
         if (_source.Count <= _selected || _selected < 0 || OpenSelectedItem is null)
         {
@@ -702,8 +704,12 @@ public class ListView : View
 
         object value = _source.ToList () [_selected];
 
-        OpenSelectedItem?.Invoke (this, new ListViewItemEventArgs (_selected, value));
+        if (OnAccept () == true)
+        {
+            return false;
+        }
 
+        OpenSelectedItem?.Invoke (this, new ListViewItemEventArgs (_selected, value));
         return true;
     }
 

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

@@ -464,16 +464,16 @@ internal sealed class Menu : View
                    );
         AddCommand (Command.Select, () => _host?.SelectItem (_menuItemToSelect));
         AddCommand (Command.ToggleExpandCollapse, () => SelectOrRun ());
-        AddCommand (Command.Default, () => _host?.SelectItem (_menuItemToSelect));
+        AddCommand (Command.HotKey, () => _host?.SelectItem (_menuItemToSelect));
 
         // Default key bindings for this view
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-        KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-        KeyBindings.Add (KeyCode.Esc, Command.Cancel);
-        KeyBindings.Add (KeyCode.Enter, Command.Accept);
-        KeyBindings.Add (KeyCode.F9, KeyBindingScope.HotKey, Command.ToggleExpandCollapse);
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.CursorLeft, Command.Left);
+        KeyBindings.Add (Key.CursorRight, Command.Right);
+        KeyBindings.Add (Key.Esc, Command.Cancel);
+        KeyBindings.Add (Key.Enter, Command.Accept);
+        KeyBindings.Add (Key.F9, KeyBindingScope.HotKey, Command.ToggleExpandCollapse);
 
         KeyBindings.Add (
                          KeyCode.CtrlMask | KeyCode.Space,
@@ -610,7 +610,7 @@ internal sealed class Menu : View
                 {
                     _menuBarItemToActivate = -1;
                     _menuItemToSelect = c;
-                    keyEvent.Scope = KeyBindingScope.HotKey;
+                    //keyEvent.Scope = KeyBindingScope.HotKey;
 
                     return base.OnInvokingKeyBindings (keyEvent);
                 }
@@ -619,7 +619,7 @@ internal sealed class Menu : View
 
                 if (FindShortcutInChildMenu (key, subMenu))
                 {
-                    keyEvent.Scope = KeyBindingScope.HotKey;
+                    //keyEvent.Scope = KeyBindingScope.HotKey;
 
                     return base.OnInvokingKeyBindings (keyEvent);
                 }

+ 16 - 59
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -313,12 +313,12 @@ public class MenuBar : View
         AddCommand (Command.Select, () => Run (_menuItemToSelect?.Action));
 
         // Default key bindings for this view
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-        KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-        KeyBindings.Add (KeyCode.Esc, Command.Cancel);
-        KeyBindings.Add (KeyCode.CursorDown, Command.Accept);
-        KeyBindings.Add (KeyCode.Enter, Command.Accept);
-        KeyBindings.Add ((KeyCode)Key, KeyBindingScope.HotKey, Command.ToggleExpandCollapse);
+        KeyBindings.Add (Key.CursorLeft, Command.Left);
+        KeyBindings.Add (Key.CursorRight, Command.Right);
+        KeyBindings.Add (Key.Esc, Command.Cancel);
+        KeyBindings.Add (Key.CursorDown, Command.Accept);
+        KeyBindings.Add (Key.Enter, Command.Accept);
+        KeyBindings.Add (Key, KeyBindingScope.HotKey, Command.ToggleExpandCollapse);
 
         KeyBindings.Add (
                          KeyCode.CtrlMask | KeyCode.Space,
@@ -588,7 +588,7 @@ public class MenuBar : View
         _selected = 0;
         SetNeedsDisplay ();
 
-        _previousFocused = SuperView is null ? Application.Current.Focused : SuperView.Focused;
+        _previousFocused = SuperView is null ? Application.Current?.Focused : SuperView.Focused;
         OpenMenu (_selected);
 
         if (!SelectEnabledItem (
@@ -654,46 +654,6 @@ public class MenuBar : View
         SetNeedsDisplay ();
     }
 
-    internal void AltKeyUpHandler (Key e)
-    {
-        if (e.KeyCode == KeyCode.AltMask)
-        {
-            e.Handled = true;
-
-            // User pressed Alt 
-            if (!IsMenuOpen && _openMenu is null && !_openedByAltKey)
-            {
-                // There's no open menu, the first menu item should be highlighted.
-                // The right way to do this is to SetFocus(MenuBar), but for some reason
-                // that faults.
-
-                GetMouseGrabViewInstance (this)?.CleanUp ();
-
-                IsMenuOpen = true;
-                _openedByAltKey = true;
-                _selected = 0;
-                CanFocus = true;
-
-                _lastFocused = SuperView == null
-                                   ? Application.Current.MostFocused
-                                   : SuperView.MostFocused;
-                SetFocus ();
-                SetNeedsDisplay ();
-                Application.GrabMouse (this);
-            }
-            else if (!_openedByHotKey)
-            {
-                // There's an open menu. Close it.
-                CleanUp ();
-            }
-            else
-            {
-                _openedByAltKey = false;
-                _openedByHotKey = false;
-            }
-        }
-    }
-
     internal void CleanUp ()
     {
         _isCleaning = true;
@@ -1554,15 +1514,13 @@ public class MenuBar : View
     }
 
     /// <inheritdoc/>
-    public override bool? OnInvokingKeyBindings (Key keyEvent)
+    public override bool? OnInvokingKeyBindings (Key key)
     {
         // This is a bit of a hack. We want to handle the key bindings for menu bar but
         // InvokeKeyBindings doesn't pass any context so we can't tell which item it is for.
         // So before we call the base class we set SelectedItem appropriately.
         // TODO: Figure out if there's a way to have KeyBindings pass context instead. Maybe a KeyBindingContext property?
 
-        KeyCode key = keyEvent.KeyCode;
-
         if (KeyBindings.TryGet (key, out _))
         {
             _menuBarItemToActivate = -1;
@@ -1572,12 +1530,12 @@ public class MenuBar : View
             for (var i = 0; i < Menus.Length; i++)
             {
                 // Recurse through the menu to find one with the shortcut.
-                if (FindShortcutInChildMenu (key, Menus [i], out _menuItemToSelect))
+                if (FindShortcutInChildMenu (key.KeyCode, Menus [i], out _menuItemToSelect))
                 {
                     _menuBarItemToActivate = i;
-                    keyEvent.Scope = KeyBindingScope.HotKey;
+                    //keyEvent.Scope = KeyBindingScope.HotKey;
 
-                    return base.OnInvokingKeyBindings (keyEvent);
+                    return base.OnInvokingKeyBindings (key);
                 }
 
                 // Now see if any of the menu bar items have a hot key that matches
@@ -1603,12 +1561,11 @@ public class MenuBar : View
                 // No submenu item matched (or the menu is closed)
 
                 // Check if one of the menu bar item has a hot key that matches
-                int hotKeyValue = Menus [i]?.HotKey.Value ?? default (int);
-                var hotKey = (KeyCode)hotKeyValue;
+                var hotKey = new Key ((char)Menus [i]?.HotKey.Value);
 
-                if (hotKey != KeyCode.Null)
+                if (hotKey != Key.Empty)
                 {
-                    bool matches = key == hotKey || key == (hotKey | KeyCode.AltMask);
+                    bool matches = key == hotKey || key == hotKey.WithAlt || key == hotKey.NoShift.WithAlt;
 
                     if (IsMenuOpen)
                     {
@@ -1619,7 +1576,7 @@ public class MenuBar : View
                     if (matches)
                     {
                         _menuBarItemToActivate = i;
-                        keyEvent.Scope = KeyBindingScope.HotKey;
+                        //keyEvent.Scope = KeyBindingScope.HotKey;
 
                         break;
                     }
@@ -1627,7 +1584,7 @@ public class MenuBar : View
             }
         }
 
-        return base.OnInvokingKeyBindings (keyEvent);
+        return base.OnInvokingKeyBindings (key);
     }
 
     // TODO: Update to use Key instead of KeyCode

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

@@ -451,7 +451,7 @@ public static class MessageBox
             int buttonId = n;
             Button b = buttonList [n];
 
-            b.Clicked += (s, e) =>
+            b.Accept += (s, e) =>
                          {
                              Clicked = buttonId;
                              Application.RequestStop ();

+ 11 - 13
Terminal.Gui/Views/RadioGroup.cs

@@ -16,7 +16,6 @@ public class RadioGroup : View
     /// </summary>
     public RadioGroup ()
     {
-        HotKeySpecifier = new Rune ('_');
         CanFocus = true;
 
         // Things this view knows how to do
@@ -65,17 +64,16 @@ public class RadioGroup : View
                     () =>
                     {
                         SelectItem ();
-
-                        return true;
+                        return !OnAccept ();
                     }
                    );
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
-        KeyBindings.Add (KeyCode.Home, Command.TopHome);
-        KeyBindings.Add (KeyCode.End, Command.BottomEnd);
-        KeyBindings.Add (KeyCode.Space, Command.Accept);
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.Home, Command.TopHome);
+        KeyBindings.Add (Key.End, Command.BottomEnd);
+        KeyBindings.Add (Key.Space, Command.Accept);
 
         LayoutStarted += RadioGroup_LayoutStarted;
     }
@@ -124,7 +122,7 @@ public class RadioGroup : View
             {
                 if (TextFormatter.FindHotKey (label, HotKeySpecifier, out _, out Key hotKey))
                 {
-                    AddKeyBindingsForHotKey (hotKey, KeyCode.Null);
+                    AddKeyBindingsForHotKey (hotKey, Key.Empty);
                 }
             }
 
@@ -135,7 +133,7 @@ public class RadioGroup : View
             {
                 if (TextFormatter.FindHotKey (label, HotKeySpecifier, out _, out Key hotKey))
                 {
-                    AddKeyBindingsForHotKey (KeyCode.Null, hotKey);
+                    AddKeyBindingsForHotKey (Key.Empty, hotKey);
                 }
             }
 
@@ -228,7 +226,7 @@ public class RadioGroup : View
             Driver.AddStr ($"{(i == _selected ? Glyphs.Selected : Glyphs.UnSelected)} ");
             TextFormatter.FindHotKey (rl, HotKeySpecifier, out int hotPos, out Key hotKey);
 
-            if (hotPos != -1 && hotKey != KeyCode.Null)
+            if (hotPos != -1 && hotKey != Key.Empty)
             {
                 Rune [] rlRunes = rl.ToRunes ();
 
@@ -316,8 +314,6 @@ public class RadioGroup : View
                     && key.NoAlt.NoCtrl.NoShift == hotKey)
                 {
                     SelectedItem = i;
-                    keyEvent.Scope = KeyBindingScope.HotKey;
-
                     break;
                 }
             }
@@ -343,6 +339,7 @@ public class RadioGroup : View
         return args.Cancel;
     }
 
+    // TODO: This should be cancelable
     /// <summary>Called whenever the current selected item changes. Invokes the <see cref="SelectedItemChanged"/> event.</summary>
     /// <param name="selectedItem"></param>
     /// <param name="previousSelectedItem"></param>
@@ -377,6 +374,7 @@ public class RadioGroup : View
     /// <summary>Allow to invoke the <see cref="SelectedItemChanged"/> after their creation.</summary>
     public void Refresh () { OnSelectedItemChanged (_selected, -1); }
 
+    // TODO: This should use StateEventArgs<int> and should be cancelable.
     /// <summary>Invoked when the selected radio label has changed.</summary>
     public event EventHandler<SelectedItemChangedArgs> SelectedItemChanged;
 

+ 17 - 17
Terminal.Gui/Views/ScrollView.cs

@@ -93,23 +93,23 @@ public class ScrollView : View
         AddCommand (Command.RightEnd, () => ScrollRight (_contentSize.Width));
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.CursorUp, Command.ScrollUp);
-        KeyBindings.Add (KeyCode.CursorDown, Command.ScrollDown);
-        KeyBindings.Add (KeyCode.CursorLeft, Command.ScrollLeft);
-        KeyBindings.Add (KeyCode.CursorRight, Command.ScrollRight);
-
-        KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
-        KeyBindings.Add ((KeyCode)'v' | KeyCode.AltMask, Command.PageUp);
-
-        KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
-        KeyBindings.Add (KeyCode.V | KeyCode.CtrlMask, Command.PageDown);
-
-        KeyBindings.Add (KeyCode.PageUp | KeyCode.CtrlMask, Command.PageLeft);
-        KeyBindings.Add (KeyCode.PageDown | KeyCode.CtrlMask, Command.PageRight);
-        KeyBindings.Add (KeyCode.Home, Command.TopHome);
-        KeyBindings.Add (KeyCode.End, Command.BottomEnd);
-        KeyBindings.Add (KeyCode.Home | KeyCode.CtrlMask, Command.LeftHome);
-        KeyBindings.Add (KeyCode.End | KeyCode.CtrlMask, Command.RightEnd);
+        KeyBindings.Add (Key.CursorUp, Command.ScrollUp);
+        KeyBindings.Add (Key.CursorDown, Command.ScrollDown);
+        KeyBindings.Add (Key.CursorLeft, Command.ScrollLeft);
+        KeyBindings.Add (Key.CursorRight, Command.ScrollRight);
+
+        KeyBindings.Add (Key.PageUp, Command.PageUp);
+        KeyBindings.Add (Key.V.WithAlt, Command.PageUp);
+
+        KeyBindings.Add (Key.PageDown, Command.PageDown);
+        KeyBindings.Add (Key.V.WithCtrl, Command.PageDown);
+
+        KeyBindings.Add (Key.PageUp.WithCtrl, Command.PageLeft);
+        KeyBindings.Add (Key.PageDown.WithCtrl, Command.PageRight);
+        KeyBindings.Add (Key.Home, Command.TopHome);
+        KeyBindings.Add (Key.End, Command.BottomEnd);
+        KeyBindings.Add (Key.Home.WithCtrl, Command.LeftHome);
+        KeyBindings.Add (Key.End.WithCtrl, Command.RightEnd);
 
         Initialized += (s, e) =>
                        {

+ 20 - 20
Terminal.Gui/Views/Slider.cs

@@ -1667,33 +1667,33 @@ public class Slider<T> : View
     {
         if (_config._sliderOrientation == Orientation.Horizontal)
         {
-            KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-            KeyBindings.Remove (KeyCode.CursorDown);
-            KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-            KeyBindings.Remove (KeyCode.CursorUp);
+            KeyBindings.Add (Key.CursorRight, Command.Right);
+            KeyBindings.Remove (Key.CursorDown);
+            KeyBindings.Add (Key.CursorLeft, Command.Left);
+            KeyBindings.Remove (Key.CursorUp);
 
-            KeyBindings.Add (KeyCode.CursorRight | KeyCode.CtrlMask, Command.RightExtend);
-            KeyBindings.Remove (KeyCode.CursorDown | KeyCode.CtrlMask);
-            KeyBindings.Add (KeyCode.CursorLeft | KeyCode.CtrlMask, Command.LeftExtend);
-            KeyBindings.Remove (KeyCode.CursorUp | KeyCode.CtrlMask);
+            KeyBindings.Add (Key.CursorRight.WithCtrl, Command.RightExtend);
+            KeyBindings.Remove (Key.CursorDown.WithCtrl);
+            KeyBindings.Add (Key.CursorLeft.WithCtrl, Command.LeftExtend);
+            KeyBindings.Remove (Key.CursorUp.WithCtrl);
         }
         else
         {
-            KeyBindings.Remove (KeyCode.CursorRight);
-            KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
-            KeyBindings.Remove (KeyCode.CursorLeft);
-            KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
+            KeyBindings.Remove (Key.CursorRight);
+            KeyBindings.Add (Key.CursorDown, Command.LineDown);
+            KeyBindings.Remove (Key.CursorLeft);
+            KeyBindings.Add (Key.CursorUp, Command.LineUp);
 
-            KeyBindings.Remove (KeyCode.CursorRight | KeyCode.CtrlMask);
-            KeyBindings.Add (KeyCode.CursorDown | KeyCode.CtrlMask, Command.RightExtend);
-            KeyBindings.Remove (KeyCode.CursorLeft | KeyCode.CtrlMask);
-            KeyBindings.Add (KeyCode.CursorUp | KeyCode.CtrlMask, Command.LeftExtend);
+            KeyBindings.Remove (Key.CursorRight.WithCtrl);
+            KeyBindings.Add (Key.CursorDown.WithCtrl, Command.RightExtend);
+            KeyBindings.Remove (Key.CursorLeft.WithCtrl);
+            KeyBindings.Add (Key.CursorUp.WithCtrl, Command.LeftExtend);
         }
 
-        KeyBindings.Add (KeyCode.Home, Command.LeftHome);
-        KeyBindings.Add (KeyCode.End, Command.RightEnd);
-        KeyBindings.Add (KeyCode.Enter, Command.Accept);
-        KeyBindings.Add (KeyCode.Space, Command.Accept);
+        KeyBindings.Add (Key.Home, Command.LeftHome);
+        KeyBindings.Add (Key.End, Command.RightEnd);
+        KeyBindings.Add (Key.Enter, Command.Accept);
+        KeyBindings.Add (Key.Space, Command.Accept);
     }
 
     private Dictionary<int, SliderOption<T>> GetSetOptionDictionary () { return _setOptions.ToDictionary (e => e, e => _options [e]); }

+ 4 - 4
Terminal.Gui/Views/StatusBar.cs

@@ -105,14 +105,14 @@ public class StatusBar : View
         {
             foreach (StatusItem item in _items)
             {
-                KeyBindings.Remove ((KeyCode)item.Shortcut);
+                KeyBindings.Remove (item.Shortcut);
             }
 
             _items = value;
 
             foreach (StatusItem item in _items)
             {
-                KeyBindings.Add ((KeyCode)item.Shortcut, KeyBindingScope.HotKey, Command.Accept);
+                KeyBindings.Add (item.Shortcut, KeyBindingScope.HotKey, Command.Accept);
             }
         }
     }
@@ -229,7 +229,7 @@ public class StatusBar : View
         // This is a bit of a hack. We want to handle the key bindings for status bar but
         // InvokeKeyBindings doesn't pass any context so we can't tell which item it is for.
         // So before we call the base class we set SelectedItem appropriately.
-        KeyCode key = keyEvent.KeyCode;
+        Key key = new (keyEvent);
 
         if (KeyBindings.TryGet (key, out _))
         {
@@ -239,7 +239,7 @@ public class StatusBar : View
                 if (item.Shortcut == key)
                 {
                     _itemToInvoke = item;
-                    keyEvent.Scope = KeyBindingScope.HotKey;
+                    //keyEvent.Scope = KeyBindingScope.HotKey;
 
                     break;
                 }

+ 8 - 8
Terminal.Gui/Views/TabView.cs

@@ -124,14 +124,14 @@ public class TabView : View
                    );
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-        KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-        KeyBindings.Add (KeyCode.Home, Command.LeftHome);
-        KeyBindings.Add (KeyCode.End, Command.RightEnd);
-        KeyBindings.Add (KeyCode.CursorDown, Command.NextView);
-        KeyBindings.Add (KeyCode.CursorUp, Command.PreviousView);
-        KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
-        KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
+        KeyBindings.Add (Key.CursorLeft, Command.Left);
+        KeyBindings.Add (Key.CursorRight, Command.Right);
+        KeyBindings.Add (Key.Home, Command.LeftHome);
+        KeyBindings.Add (Key.End, Command.RightEnd);
+        KeyBindings.Add (Key.CursorDown, Command.NextView);
+        KeyBindings.Add (Key.CursorUp, Command.PreviousView);
+        KeyBindings.Add (Key.PageDown, Command.PageDown);
+        KeyBindings.Add (Key.PageUp, Command.PageUp);
     }
 
     /// <summary>

+ 1 - 1
Terminal.Gui/Views/TableView/CheckBoxTableSourceWrapper.cs

@@ -26,7 +26,7 @@ public abstract class CheckBoxTableSourceWrapperBase : ITableSource
         Wrapping = toWrap;
         this.tableView = tableView;
 
-        tableView.KeyBindings.Add (KeyCode.Space, Command.ToggleChecked);
+        tableView.KeyBindings.Add (Key.Space, Command.Select);
 
         tableView.MouseClick += TableView_MouseClick;
         tableView.CellToggled += TableView_CellToggled;

+ 1 - 1
Terminal.Gui/Views/TableView/TableSelection.cs

@@ -13,7 +13,7 @@ public class TableSelection
     }
 
     /// <summary>
-    ///     True if the selection was made through <see cref="Command.ToggleChecked"/> and therefore should persist even
+    ///     True if the selection was made through <see cref="Command.Select"/> and therefore should persist even
     ///     through keyboard navigation.
     /// </summary>
     public bool IsToggled { get; set; }

+ 29 - 28
Terminal.Gui/Views/TableView/TableView.cs

@@ -273,7 +273,7 @@ public class TableView : View
                    );
 
         AddCommand (
-                    Command.ToggleChecked,
+                    Command.Select, // was Command.ToggleChecked
                     () =>
                     {
                         ToggleCurrentCellSelection ();
@@ -283,30 +283,31 @@ public class TableView : View
                    );
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-        KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
-        KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
-        KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
-        KeyBindings.Add (KeyCode.Home, Command.LeftHome);
-        KeyBindings.Add (KeyCode.End, Command.RightEnd);
-        KeyBindings.Add (KeyCode.Home | KeyCode.CtrlMask, Command.TopHome);
-        KeyBindings.Add (KeyCode.End | KeyCode.CtrlMask, Command.BottomEnd);
-
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.ShiftMask, Command.LeftExtend);
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.ShiftMask, Command.RightExtend);
-        KeyBindings.Add (KeyCode.CursorUp | KeyCode.ShiftMask, Command.LineUpExtend);
-        KeyBindings.Add (KeyCode.CursorDown | KeyCode.ShiftMask, Command.LineDownExtend);
-        KeyBindings.Add (KeyCode.PageUp | KeyCode.ShiftMask, Command.PageUpExtend);
-        KeyBindings.Add (KeyCode.PageDown | KeyCode.ShiftMask, Command.PageDownExtend);
-        KeyBindings.Add (KeyCode.Home | KeyCode.ShiftMask, Command.LeftHomeExtend);
-        KeyBindings.Add (KeyCode.End | KeyCode.ShiftMask, Command.RightEndExtend);
-        KeyBindings.Add (KeyCode.Home | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.TopHomeExtend);
-        KeyBindings.Add (KeyCode.End | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.BottomEndExtend);
-
-        KeyBindings.Add (KeyCode.A | KeyCode.CtrlMask, Command.SelectAll);
+        KeyBindings.Add (Key.CursorLeft, Command.Left);
+        KeyBindings.Add (Key.CursorRight, Command.Right);
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.PageUp, Command.PageUp);
+        KeyBindings.Add (Key.PageDown, Command.PageDown);
+        KeyBindings.Add (Key.Home, Command.LeftHome);
+        KeyBindings.Add (Key.End, Command.RightEnd);
+        KeyBindings.Add (Key.Home.WithCtrl, Command.TopHome);
+        KeyBindings.Add (Key.End.WithCtrl, Command.BottomEnd);
+
+        KeyBindings.Add (Key.CursorLeft.WithShift, Command.LeftExtend);
+        KeyBindings.Add (Key.CursorRight.WithShift, Command.RightExtend);
+        KeyBindings.Add (Key.CursorUp.WithShift, Command.LineUpExtend);
+        KeyBindings.Add (Key.CursorDown.WithShift, Command.LineDownExtend);
+        KeyBindings.Add (Key.PageUp.WithShift, Command.PageUpExtend);
+        KeyBindings.Add (Key.PageDown.WithShift, Command.PageDownExtend);
+        KeyBindings.Add (Key.Home.WithShift, Command.LeftHomeExtend);
+        KeyBindings.Add (Key.End.WithShift, Command.RightEndExtend);
+        KeyBindings.Add (Key.Home.WithCtrl.WithShift, Command.TopHomeExtend);
+        KeyBindings.Add (Key.End.WithCtrl.WithShift, Command.BottomEndExtend);
+
+        KeyBindings.Add (Key.A.WithCtrl, Command.SelectAll);
         KeyBindings.Add (CellActivationKey, Command.Accept);
+        KeyBindings.Add (Key.Space, Command.Select);
     }
 
     // TODO: Update to use Key instead of KeyCode
@@ -432,7 +433,7 @@ public class TableView : View
     }
 
     /// <summary>
-    ///     The symbol to add after each cell value and header value to visually seperate values (if not using vertical
+    ///     The symbol to add after each cell value and header value to visually separate values (if not using vertical
     ///     gridlines)
     /// </summary>
     public char SeparatorSymbol { get; set; } = ' ';
@@ -460,12 +461,12 @@ public class TableView : View
     }
 
     /// <summary>
-    ///     This event is raised when a cell is activated e.g. by double clicking or pressing
+    ///     This event is raised when a cell is activated e.g. by double-clicking or pressing
     ///     <see cref="CellActivationKey"/>
     /// </summary>
     public event EventHandler<CellActivatedEventArgs> CellActivated;
 
-    /// <summary>This event is raised when a cell is toggled (see <see cref="Command.ToggleChecked"/></summary>
+    /// <summary>This event is raised when a cell is toggled (see <see cref="Command.Select"/></summary>
     public event EventHandler<CellToggledEventArgs> CellToggled;
 
     /// <summary>
@@ -1487,7 +1488,7 @@ public class TableView : View
     /// <param name="pt1Y">Origin point for the selection in Y</param>
     /// <param name="pt2X">End point for the selection in X</param>
     /// <param name="pt2Y">End point for the selection in Y</param>
-    /// <param name="toggle">True if selection is result of <see cref="Command.ToggleChecked"/></param>
+    /// <param name="toggle">True if selection is result of <see cref="Command.Select"/></param>
     /// <returns></returns>
     private TableSelection CreateTableSelection (int pt1X, int pt1Y, int pt2X, int pt2Y, bool toggle = false)
     {

+ 0 - 19
Terminal.Gui/Views/TextChangedEventArgs.cs

@@ -1,19 +0,0 @@
-//
-// TextField.cs: single-line text editor with Emacs keybindings
-//
-// Authors:
-//   Miguel de Icaza ([email protected])
-//
-
-namespace Terminal.Gui;
-
-/// <summary>Event args for the <see cref="TextField.TextChanged"/> event</summary>
-public class TextChangedEventArgs : EventArgs
-{
-    /// <summary>Creates a new instance of the <see cref="TextChangedEventArgs"/> class</summary>
-    /// <param name="oldValue"></param>
-    public TextChangedEventArgs (string oldValue) { OldValue = oldValue; }
-
-    /// <summary>The old value before the text changed</summary>
-    public string OldValue { get; }
-}

+ 0 - 22
Terminal.Gui/Views/TextChangingEventArgs.cs

@@ -1,22 +0,0 @@
-//
-// TextField.cs: single-line text editor with Emacs keybindings
-//
-// Authors:
-//   Miguel de Icaza ([email protected])
-//
-
-namespace Terminal.Gui;
-
-/// <summary>An <see cref="EventArgs"/> which allows passing a cancelable new text value event.</summary>
-public class TextChangingEventArgs : EventArgs
-{
-    /// <summary>Initializes a new instance of <see cref="TextChangingEventArgs"/></summary>
-    /// <param name="newText">The new <see cref="TextField.Text"/> to be replaced.</param>
-    public TextChangingEventArgs (string newText) { NewText = newText; }
-
-    /// <summary>Flag which allows to cancel the new text value.</summary>
-    public bool Cancel { get; set; }
-
-    /// <summary>The new text to be replaced.</summary>
-    public string NewText { get; set; }
-}

+ 75 - 65
Terminal.Gui/Views/TextField.cs

@@ -1,3 +1,4 @@
+using System.Data;
 using System.Globalization;
 using Terminal.Gui.Resources;
 
@@ -340,82 +341,91 @@ public class TextField : View
                     }
                    );
 
+        // OnAccept returns true if the event is canceled.
+        // By Default pressing ENTER should be ignored (Invoke(Command.Accept) should return false).
+        AddCommand (Command.Accept, () => OnAccept() != true);
+
         // Default keybindings for this view
         // We follow this as closely as possible: https://en.wikipedia.org/wiki/Table_of_keyboard_shortcuts
-        KeyBindings.Add (KeyCode.Delete, Command.DeleteCharRight);
-        KeyBindings.Add (KeyCode.D | KeyCode.CtrlMask, Command.DeleteCharRight);
+        KeyBindings.Add (Key.Delete, Command.DeleteCharRight);
+        KeyBindings.Add (Key.D.WithCtrl, Command.DeleteCharRight);
+
+        KeyBindings.Add (Key.Backspace, Command.DeleteCharLeft);
 
-        KeyBindings.Add (KeyCode.Backspace, Command.DeleteCharLeft);
+        KeyBindings.Add (Key.Home.WithShift, Command.LeftHomeExtend);
+        KeyBindings.Add (Key.Home.WithShift.WithCtrl, Command.LeftHomeExtend);
+        KeyBindings.Add (Key.A.WithShift.WithCtrl, Command.LeftHomeExtend);
 
-        KeyBindings.Add (KeyCode.Home | KeyCode.ShiftMask, Command.LeftHomeExtend);
-        KeyBindings.Add (KeyCode.Home | KeyCode.ShiftMask | KeyCode.CtrlMask, Command.LeftHomeExtend);
-        KeyBindings.Add (KeyCode.A | KeyCode.ShiftMask | KeyCode.CtrlMask, Command.LeftHomeExtend);
+        KeyBindings.Add (Key.End.WithShift, Command.RightEndExtend);
+        KeyBindings.Add (Key.End.WithShift.WithCtrl, Command.RightEndExtend);
+        KeyBindings.Add (Key.E.WithShift.WithCtrl, Command.RightEndExtend);
 
-        KeyBindings.Add (KeyCode.End | KeyCode.ShiftMask, Command.RightEndExtend);
-        KeyBindings.Add (KeyCode.End | KeyCode.ShiftMask | KeyCode.CtrlMask, Command.RightEndExtend);
-        KeyBindings.Add (KeyCode.E | KeyCode.ShiftMask | KeyCode.CtrlMask, Command.RightEndExtend);
+        KeyBindings.Add (Key.Home, Command.LeftHome);
+        KeyBindings.Add (Key.Home.WithCtrl, Command.LeftHome);
+        KeyBindings.Add (Key.A.WithCtrl, Command.LeftHome);
 
-        KeyBindings.Add (KeyCode.Home, Command.LeftHome);
-        KeyBindings.Add (KeyCode.Home | KeyCode.CtrlMask, Command.LeftHome);
-        KeyBindings.Add (KeyCode.A | KeyCode.CtrlMask, Command.LeftHome);
+        KeyBindings.Add (Key.CursorLeft.WithShift, Command.LeftExtend);
+        KeyBindings.Add (Key.CursorUp.WithShift, Command.LeftExtend);
 
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.ShiftMask, Command.LeftExtend);
-        KeyBindings.Add (KeyCode.CursorUp | KeyCode.ShiftMask, Command.LeftExtend);
+        KeyBindings.Add (Key.CursorRight.WithShift, Command.RightExtend);
+        KeyBindings.Add (Key.CursorDown.WithShift, Command.RightExtend);
 
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.ShiftMask, Command.RightExtend);
-        KeyBindings.Add (KeyCode.CursorDown | KeyCode.ShiftMask, Command.RightExtend);
+        KeyBindings.Add (Key.CursorLeft.WithShift.WithCtrl, Command.WordLeftExtend);
+        KeyBindings.Add (Key.CursorUp.WithShift.WithCtrl, Command.WordLeftExtend);
 
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.ShiftMask | KeyCode.CtrlMask, Command.WordLeftExtend);
-        KeyBindings.Add (KeyCode.CursorUp | KeyCode.ShiftMask | KeyCode.CtrlMask, Command.WordLeftExtend);
-        KeyBindings.Add (('B' + KeyCode.ShiftMask) | KeyCode.AltMask, Command.WordLeftExtend);
+        KeyBindings.Add (Key.CursorRight.WithShift.WithCtrl, Command.WordRightExtend);
+        KeyBindings.Add (Key.CursorDown.WithShift.WithCtrl, Command.WordRightExtend);
 
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.ShiftMask | KeyCode.CtrlMask, Command.WordRightExtend);
-        KeyBindings.Add (KeyCode.CursorDown | KeyCode.ShiftMask | KeyCode.CtrlMask, Command.WordRightExtend);
-        KeyBindings.Add (('F' + KeyCode.ShiftMask) | KeyCode.AltMask, Command.WordRightExtend);
+        KeyBindings.Add (Key.CursorLeft, Command.Left);
+        KeyBindings.Add (Key.B.WithCtrl, Command.Left);
 
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-        KeyBindings.Add (KeyCode.B | KeyCode.CtrlMask, Command.Left);
+        KeyBindings.Add (Key.End, Command.RightEnd);
+        KeyBindings.Add (Key.End.WithCtrl, Command.RightEnd);
+        KeyBindings.Add (Key.E.WithCtrl, Command.RightEnd);
 
-        KeyBindings.Add (KeyCode.End, Command.RightEnd);
-        KeyBindings.Add (KeyCode.End | KeyCode.CtrlMask, Command.RightEnd);
-        KeyBindings.Add (KeyCode.E | KeyCode.CtrlMask, Command.RightEnd);
+        KeyBindings.Add (Key.CursorRight, Command.Right);
+        KeyBindings.Add (Key.F.WithCtrl, Command.Right);
 
-        KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-        KeyBindings.Add (KeyCode.F | KeyCode.CtrlMask, Command.Right);
+        KeyBindings.Add (Key.K.WithCtrl, Command.CutToEndLine);
+        KeyBindings.Add (Key.K.WithCtrl.WithShift, Command.CutToStartLine);
 
-        KeyBindings.Add (KeyCode.K | KeyCode.CtrlMask, Command.CutToEndLine);
-        KeyBindings.Add (KeyCode.K | KeyCode.AltMask, Command.CutToStartLine);
+        KeyBindings.Add (Key.Z.WithCtrl, Command.Undo);
 
-        KeyBindings.Add (KeyCode.Z | KeyCode.CtrlMask, Command.Undo);
-        KeyBindings.Add (KeyCode.Backspace | KeyCode.AltMask, Command.Undo);
+        KeyBindings.Add (Key.Y.WithCtrl, Command.Redo);
 
-        KeyBindings.Add (KeyCode.Y | KeyCode.CtrlMask, Command.Redo);
+        KeyBindings.Add (Key.CursorLeft.WithCtrl, Command.WordLeft);
+        KeyBindings.Add (Key.CursorUp.WithCtrl, Command.WordLeft);
 
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.CtrlMask, Command.WordLeft);
-        KeyBindings.Add (KeyCode.CursorUp | KeyCode.CtrlMask, Command.WordLeft);
-        KeyBindings.Add ('B' + KeyCode.AltMask, Command.WordLeft);
+        KeyBindings.Add (Key.CursorRight.WithCtrl, Command.WordRight);
+        KeyBindings.Add (Key.CursorDown.WithCtrl, Command.WordRight);
 
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.CtrlMask, Command.WordRight);
-        KeyBindings.Add (KeyCode.CursorDown | KeyCode.CtrlMask, Command.WordRight);
-        KeyBindings.Add ('F' + KeyCode.AltMask, Command.WordRight);
+#if UNIX_KEY_BINDINGS
+        KeyBindings.Add (Key.F.WithShift.WithAlt, Command.WordRightExtend);
+        KeyBindings.Add (Key.K.WithAlt, Command.CutToStartLine);
+        KeyBindings.Add (Key.B.WithShift.WithAlt, Command.WordLeftExtend);
+        KeyBindings.Add (Key.B.WithAlt, Command.WordLeft);
+        KeyBindings.Add (Key.F.WithAlt, Command.WordRight);
+        KeyBindings.Add (Key.Backspace.WithAlt, Command.Undo);
+#endif
 
-        KeyBindings.Add (KeyCode.Delete | KeyCode.CtrlMask, Command.KillWordForwards);
-        KeyBindings.Add (KeyCode.Backspace | KeyCode.CtrlMask, Command.KillWordBackwards);
-        KeyBindings.Add (KeyCode.Insert, Command.ToggleOverwrite);
-        KeyBindings.Add (KeyCode.C | KeyCode.CtrlMask, Command.Copy);
-        KeyBindings.Add (KeyCode.X | KeyCode.CtrlMask, Command.Cut);
-        KeyBindings.Add (KeyCode.V | KeyCode.CtrlMask, Command.Paste);
-        KeyBindings.Add (KeyCode.T | KeyCode.CtrlMask, Command.SelectAll);
+        KeyBindings.Add (Key.Delete.WithCtrl, Command.KillWordForwards);
+        KeyBindings.Add (Key.Backspace.WithCtrl, Command.KillWordBackwards);
+        KeyBindings.Add (Key.InsertChar, Command.ToggleOverwrite);
+        KeyBindings.Add (Key.C.WithCtrl, Command.Copy);
+        KeyBindings.Add (Key.X.WithCtrl, Command.Cut);
+        KeyBindings.Add (Key.V.WithCtrl, Command.Paste);
+        KeyBindings.Add (Key.T.WithCtrl, Command.SelectAll);
 
-        KeyBindings.Add (KeyCode.R | KeyCode.CtrlMask, Command.DeleteAll);
-        KeyBindings.Add (KeyCode.D | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.DeleteAll);
+        KeyBindings.Add (Key.R.WithCtrl, Command.DeleteAll);
+        KeyBindings.Add (Key.D.WithCtrl.WithShift, Command.DeleteAll);
 
         _currentCulture = Thread.CurrentThread.CurrentUICulture;
 
         ContextMenu = new ContextMenu { Host = this, MenuItems = BuildContextMenuBarItem () };
         ContextMenu.KeyChanged += ContextMenu_KeyChanged;
 
-        KeyBindings.Add (ContextMenu.Key.KeyCode, KeyBindingScope.HotKey, Command.ShowContextMenu);
+        KeyBindings.Add (ContextMenu.Key, KeyBindingScope.HotKey, Command.ShowContextMenu);
+        KeyBindings.Add (Key.Enter, Command.Accept);
     }
 
     /// <summary>
@@ -551,7 +561,7 @@ public class TextField : View
                 return;
             }
 
-            TextChangingEventArgs newText = OnTextChanging (value.Replace ("\t", "").Split ("\n") [0]);
+            StateEventArgs<string> newText = OnTextChanging (value.Replace ("\t", "").Split ("\n") [0]);
 
             if (newText.Cancel)
             {
@@ -564,7 +574,7 @@ public class TextField : View
             }
 
             ClearAllSelection ();
-            _text = newText.NewText.EnumerateRunes ().ToList ();
+            _text = newText.NewValue.EnumerateRunes ().ToList ();
 
             if (!Secret && !_historyText.IsFromHistory)
             {
@@ -580,7 +590,7 @@ public class TextField : View
                                  );
             }
 
-            TextChanged?.Invoke (this, new TextChangedEventArgs (oldText));
+            OnTextChanged (oldText, StringExtensions.ToString (_text));
 
             ProcessAutocomplete ();
 
@@ -1132,10 +1142,10 @@ public class TextField : View
 
     /// <summary>Virtual method that invoke the <see cref="TextChanging"/> event if it's defined.</summary>
     /// <param name="newText">The new text to be replaced.</param>
-    /// <returns>Returns the <see cref="TextChangingEventArgs"/></returns>
-    public virtual TextChangingEventArgs OnTextChanging (string newText)
+    /// <returns>Returns the <see cref="StringEventArgs"/></returns>
+    public virtual StateEventArgs<string> OnTextChanging (string newText)
     {
-        var ev = new TextChangingEventArgs (newText);
+        StateEventArgs<string> ev = new (string.Empty, newText);
         TextChanging?.Invoke (this, ev);
 
         return ev;
@@ -1258,17 +1268,17 @@ public class TextField : View
         SetNeedsDisplay ();
     }
 
-    /// <summary>
-    ///     Changed event, raised when the text has changed.
-    ///     <remarks>
-    ///         This event is raised when the <see cref="Text"/> changes. The passed <see cref="EventArgs"/> is a
-    ///         <see cref="string"/> containing the old value.
-    ///     </remarks>
-    /// </summary>
-    public event EventHandler<TextChangedEventArgs> TextChanged;
+    ///// <summary>
+    /////     Changed event, raised when the text has changed.
+    /////     <remarks>
+    /////         This event is raised when the <see cref="Text"/> changes. The passed <see cref="EventArgs"/> is a
+    /////         <see cref="string"/> containing the old value.
+    /////     </remarks>
+    ///// </summary>
+    //public event EventHandler<StateEventArgs<string>> TextChanged;
 
     /// <summary>Changing event, raised before the <see cref="Text"/> changes and can be canceled or changing the new text.</summary>
-    public event EventHandler<TextChangingEventArgs> TextChanging;
+    public event EventHandler<StateEventArgs<string>> TextChanging;
 
     /// <summary>Undoes the latest changes.</summary>
     public void Undo ()

+ 18 - 18
Terminal.Gui/Views/TextValidateField.cs

@@ -64,8 +64,8 @@ namespace Terminal.Gui
 
             /// <summary>Method that invoke the <see cref="TextChanged"/> event if it's defined.</summary>
             /// <param name="oldValue">The previous text before replaced.</param>
-            /// <returns>Returns the <see cref="TextChangedEventArgs"/></returns>
-            void OnTextChanged (TextChangedEventArgs oldValue);
+            /// <returns>Returns the <see cref="StringEventArgs"/></returns>
+            void OnTextChanged (StringEventArgs oldValue);
 
             /// <summary>
             ///     Changed event, raised when the text has changed.
@@ -74,7 +74,7 @@ namespace Terminal.Gui
             ///         <see cref="string"/> containing the old value.
             ///     </remarks>
             /// </summary>
-            event EventHandler<TextChangedEventArgs> TextChanged;
+            event EventHandler<StringEventArgs> TextChanged;
         }
 
         //////////////////////////////////////////////////////////////////////////////
@@ -125,7 +125,7 @@ namespace Terminal.Gui
             }
 
             /// <inheritdoc/>
-            public event EventHandler<TextChangedEventArgs> TextChanged;
+            public event EventHandler<StringEventArgs> TextChanged;
 
             /// <inheritdoc/>
             public string Text
@@ -206,7 +206,7 @@ namespace Terminal.Gui
 
                 if (result)
                 {
-                    OnTextChanged (new TextChangedEventArgs (oldValue));
+                    OnTextChanged (new StringEventArgs { NewValue = oldValue });
                 }
 
                 return result;
@@ -220,14 +220,14 @@ namespace Terminal.Gui
 
                 if (result)
                 {
-                    OnTextChanged (new TextChangedEventArgs (oldValue));
+                    OnTextChanged (new StringEventArgs { NewValue = oldValue });
                 }
 
                 return result;
             }
 
             /// <inheritdoc/>
-            public void OnTextChanged (TextChangedEventArgs oldValue) { TextChanged?.Invoke (this, oldValue); }
+            public void OnTextChanged (StringEventArgs oldValue) { TextChanged?.Invoke (this, oldValue); }
         }
 
         #endregion
@@ -260,7 +260,7 @@ namespace Terminal.Gui
             public bool ValidateOnInput { get; set; } = true;
 
             /// <inheritdoc/>
-            public event EventHandler<TextChangedEventArgs> TextChanged;
+            public event EventHandler<StringEventArgs> TextChanged;
 
             /// <inheritdoc/>
             public string Text
@@ -333,7 +333,7 @@ namespace Terminal.Gui
                 {
                     string oldValue = Text;
                     _text.RemoveAt (pos);
-                    OnTextChanged (new TextChangedEventArgs (oldValue));
+                    OnTextChanged (new StringEventArgs { NewValue = Text, OldValue = oldValue });
                 }
 
                 return true;
@@ -349,7 +349,7 @@ namespace Terminal.Gui
                 {
                     string oldValue = Text;
                     _text.Insert (pos, (Rune)ch);
-                    OnTextChanged (new TextChangedEventArgs (oldValue));
+                    OnTextChanged (new StringEventArgs { NewValue = Text, OldValue = oldValue });
 
                     return true;
                 }
@@ -358,7 +358,7 @@ namespace Terminal.Gui
             }
 
             /// <inheritdoc/>
-            public void OnTextChanged (TextChangedEventArgs oldValue) { TextChanged?.Invoke (this, oldValue); }
+            public void OnTextChanged (StringEventArgs oldValue) { TextChanged?.Invoke (this, oldValue); }
 
             /// <summary>Compiles the regex pattern for validation./></summary>
             private void CompileMask () { _regex = new Regex (StringExtensions.ToString (_pattern), RegexOptions.Compiled); }
@@ -462,15 +462,15 @@ namespace Terminal.Gui
                        );
 
             // Default keybindings for this view
-            KeyBindings.Add (KeyCode.Home, Command.LeftHome);
-            KeyBindings.Add (KeyCode.End, Command.RightEnd);
+            KeyBindings.Add (Key.Home, Command.LeftHome);
+            KeyBindings.Add (Key.End, Command.RightEnd);
 
-            KeyBindings.Add (KeyCode.Delete, Command.DeleteCharRight);
-            KeyBindings.Add (KeyCode.Delete, Command.DeleteCharRight);
+            KeyBindings.Add (Key.Delete, Command.DeleteCharRight);
+            KeyBindings.Add (Key.Delete, Command.DeleteCharRight);
 
-            KeyBindings.Add (KeyCode.Backspace, Command.DeleteCharLeft);
-            KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-            KeyBindings.Add (KeyCode.CursorRight, Command.Right);
+            KeyBindings.Add (Key.Backspace, Command.DeleteCharLeft);
+            KeyBindings.Add (Key.CursorLeft, Command.Left);
+            KeyBindings.Add (Key.CursorRight, Command.Right);
         }
 
         /// <summary>This property returns true if the input is valid.</summary>

+ 80 - 90
Terminal.Gui/Views/TextView.cs

@@ -2409,113 +2409,103 @@ public class TextView : View
                    );
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
-        KeyBindings.Add (KeyCode.V | KeyCode.CtrlMask, Command.PageDown);
+        KeyBindings.Add (Key.PageDown, Command.PageDown);
+        KeyBindings.Add (Key.V.WithCtrl, Command.PageDown);
 
-        KeyBindings.Add (KeyCode.PageDown | KeyCode.ShiftMask, Command.PageDownExtend);
+        KeyBindings.Add (Key.PageDown.WithShift, Command.PageDownExtend);
 
-        KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
-        KeyBindings.Add ('V' + KeyCode.AltMask, Command.PageUp);
+        KeyBindings.Add (Key.PageUp, Command.PageUp);
+        KeyBindings.Add (Key.V.WithAlt, Command.PageUp);
 
-        KeyBindings.Add (KeyCode.PageUp | KeyCode.ShiftMask, Command.PageUpExtend);
+        KeyBindings.Add (Key.PageUp.WithShift, Command.PageUpExtend);
 
-        KeyBindings.Add (KeyCode.N | KeyCode.CtrlMask, Command.LineDown);
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.N.WithCtrl, Command.LineDown);
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
 
-        KeyBindings.Add (KeyCode.CursorDown | KeyCode.ShiftMask, Command.LineDownExtend);
+        KeyBindings.Add (Key.CursorDown.WithShift, Command.LineDownExtend);
 
-        KeyBindings.Add (KeyCode.P | KeyCode.CtrlMask, Command.LineUp);
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.P.WithCtrl, Command.LineUp);
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
 
-        KeyBindings.Add (KeyCode.CursorUp | KeyCode.ShiftMask, Command.LineUpExtend);
+        KeyBindings.Add (Key.CursorUp.WithShift, Command.LineUpExtend);
 
-        KeyBindings.Add (KeyCode.F | KeyCode.CtrlMask, Command.Right);
-        KeyBindings.Add (KeyCode.CursorRight, Command.Right);
+        KeyBindings.Add (Key.F.WithCtrl, Command.Right);
+        KeyBindings.Add (Key.CursorRight, Command.Right);
 
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.ShiftMask, Command.RightExtend);
+        KeyBindings.Add (Key.CursorRight.WithShift, Command.RightExtend);
 
-        KeyBindings.Add (KeyCode.B | KeyCode.CtrlMask, Command.Left);
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
+        KeyBindings.Add (Key.B.WithCtrl, Command.Left);
+        KeyBindings.Add (Key.CursorLeft, Command.Left);
 
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.ShiftMask, Command.LeftExtend);
+        KeyBindings.Add (Key.CursorLeft.WithShift, Command.LeftExtend);
 
-        KeyBindings.Add (KeyCode.Backspace, Command.DeleteCharLeft);
+        KeyBindings.Add (Key.Backspace, Command.DeleteCharLeft);
 
-        KeyBindings.Add (KeyCode.Home, Command.StartOfLine);
-        KeyBindings.Add (KeyCode.A | KeyCode.CtrlMask, Command.StartOfLine);
+        KeyBindings.Add (Key.Home, Command.StartOfLine);
+        KeyBindings.Add (Key.A.WithCtrl, Command.StartOfLine);
 
-        KeyBindings.Add (KeyCode.Home | KeyCode.ShiftMask, Command.StartOfLineExtend);
+        KeyBindings.Add (Key.Home.WithShift, Command.StartOfLineExtend);
 
-        KeyBindings.Add (KeyCode.Delete, Command.DeleteCharRight);
-        KeyBindings.Add (KeyCode.D | KeyCode.CtrlMask, Command.DeleteCharRight);
+        KeyBindings.Add (Key.Delete, Command.DeleteCharRight);
+        KeyBindings.Add (Key.D.WithCtrl, Command.DeleteCharRight);
 
-        KeyBindings.Add (KeyCode.End, Command.EndOfLine);
-        KeyBindings.Add (KeyCode.E | KeyCode.CtrlMask, Command.EndOfLine);
+        KeyBindings.Add (Key.End, Command.EndOfLine);
+        KeyBindings.Add (Key.E.WithCtrl, Command.EndOfLine);
 
-        KeyBindings.Add (KeyCode.End | KeyCode.ShiftMask, Command.EndOfLineExtend);
+        KeyBindings.Add (Key.End.WithShift, Command.EndOfLineExtend);
 
-        KeyBindings.Add (KeyCode.K | KeyCode.CtrlMask, Command.CutToEndLine); // kill-to-end
+        KeyBindings.Add (Key.K.WithCtrl, Command.CutToEndLine); // kill-to-end
 
-        KeyBindings.Add (
-                         KeyCode.Delete | KeyCode.CtrlMask | KeyCode.ShiftMask,
-                         Command.CutToEndLine
-                        ); // kill-to-end
+        KeyBindings.Add (Key.Delete.WithCtrl.WithShift, Command.CutToEndLine); // kill-to-end
 
-        KeyBindings.Add (KeyCode.K | KeyCode.AltMask, Command.CutToStartLine); // kill-to-start
+        KeyBindings.Add (Key.K.WithAlt, Command.CutToStartLine); // kill-to-start
 
-        KeyBindings.Add (
-                         KeyCode.Backspace | KeyCode.CtrlMask | KeyCode.ShiftMask,
-                         Command.CutToStartLine
-                        ); // kill-to-start
+        KeyBindings.Add (Key.Backspace.WithCtrl.WithShift, Command.CutToStartLine); // kill-to-start
 
-        KeyBindings.Add (KeyCode.Y | KeyCode.CtrlMask, Command.Paste); // Control-y, yank
-        KeyBindings.Add (KeyCode.Space | KeyCode.CtrlMask, Command.ToggleExtend);
+        KeyBindings.Add (Key.Y.WithCtrl, Command.Paste); // Control-y, yank
+        KeyBindings.Add (Key.Space.WithCtrl, Command.ToggleExtend);
 
-        KeyBindings.Add ('C' + KeyCode.AltMask, Command.Copy);
-        KeyBindings.Add (KeyCode.C | KeyCode.CtrlMask, Command.Copy);
+        KeyBindings.Add (Key.C.WithAlt, Command.Copy);
+        KeyBindings.Add (Key.C.WithCtrl, Command.Copy);
 
-        KeyBindings.Add ('W' + KeyCode.AltMask, Command.Cut);
-        KeyBindings.Add (KeyCode.W | KeyCode.CtrlMask, Command.Cut);
-        KeyBindings.Add (KeyCode.X | KeyCode.CtrlMask, Command.Cut);
+        KeyBindings.Add (Key.W.WithAlt, Command.Cut);
+        KeyBindings.Add (Key.W.WithCtrl, Command.Cut);
+        KeyBindings.Add (Key.X.WithCtrl, Command.Cut);
 
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.CtrlMask, Command.WordLeft);
-        KeyBindings.Add ('B' + KeyCode.AltMask, Command.WordLeft);
+        KeyBindings.Add (Key.CursorLeft.WithCtrl, Command.WordLeft);
+        KeyBindings.Add (Key.B.WithAlt, Command.WordLeft);
 
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.WordLeftExtend);
+        KeyBindings.Add (Key.CursorLeft.WithCtrl.WithShift, Command.WordLeftExtend);
 
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.CtrlMask, Command.WordRight);
-        KeyBindings.Add ('F' + KeyCode.AltMask, Command.WordRight);
+        KeyBindings.Add (Key.CursorRight.WithCtrl, Command.WordRight);
+        KeyBindings.Add (Key.F.WithAlt, Command.WordRight);
 
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.WordRightExtend);
-        KeyBindings.Add (KeyCode.Delete | KeyCode.CtrlMask, Command.KillWordForwards); // kill-word-forwards
-
-        KeyBindings.Add (
-                         KeyCode.Backspace | KeyCode.CtrlMask,
-                         Command.KillWordBackwards
-                        ); // kill-word-backwards
+        KeyBindings.Add (Key.CursorRight.WithCtrl.WithShift, Command.WordRightExtend);
+        KeyBindings.Add (Key.Delete.WithCtrl, Command.KillWordForwards); // kill-word-forwards
+        KeyBindings.Add (Key.Backspace.WithCtrl, Command.KillWordBackwards); // kill-word-backwards
 
         // BUGBUG: If AllowsReturn is false, Key.Enter should not be bound (so that Toplevel can cause Command.Accept).
-        KeyBindings.Add (KeyCode.Enter, Command.NewLine);
-        KeyBindings.Add (KeyCode.End | KeyCode.CtrlMask, Command.BottomEnd);
-        KeyBindings.Add (KeyCode.End | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.BottomEndExtend);
-        KeyBindings.Add (KeyCode.Home | KeyCode.CtrlMask, Command.TopHome);
-        KeyBindings.Add (KeyCode.Home | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.TopHomeExtend);
-        KeyBindings.Add (KeyCode.T | KeyCode.CtrlMask, Command.SelectAll);
-        KeyBindings.Add (KeyCode.Insert, Command.ToggleOverwrite);
-        KeyBindings.Add (KeyCode.Tab, Command.Tab);
-        KeyBindings.Add (KeyCode.Tab | KeyCode.ShiftMask, Command.BackTab);
+        KeyBindings.Add (Key.Enter, Command.NewLine);
+        KeyBindings.Add (Key.End.WithCtrl, Command.BottomEnd);
+        KeyBindings.Add (Key.End.WithCtrl.WithShift, Command.BottomEndExtend);
+        KeyBindings.Add (Key.Home.WithCtrl, Command.TopHome);
+        KeyBindings.Add (Key.Home.WithCtrl.WithShift, Command.TopHomeExtend);
+        KeyBindings.Add (Key.T.WithCtrl, Command.SelectAll);
+        KeyBindings.Add (Key.InsertChar, Command.ToggleOverwrite);
+        KeyBindings.Add (Key.Tab, Command.Tab);
+        KeyBindings.Add (Key.Tab.WithShift, Command.BackTab);
 
-        KeyBindings.Add (KeyCode.Tab | KeyCode.CtrlMask, Command.NextView);
-        KeyBindings.Add ((KeyCode)Application.AlternateForwardKey, Command.NextView);
+        KeyBindings.Add (Key.Tab.WithCtrl, Command.NextView);
+        KeyBindings.Add (Application.AlternateForwardKey, Command.NextView);
 
-        KeyBindings.Add (KeyCode.Tab | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.PreviousView);
-        KeyBindings.Add ((KeyCode)Application.AlternateBackwardKey, Command.PreviousView);
+        KeyBindings.Add (Key.Tab.WithCtrl.WithShift, Command.PreviousView);
+        KeyBindings.Add (Application.AlternateBackwardKey, Command.PreviousView);
 
-        KeyBindings.Add (KeyCode.Z | KeyCode.CtrlMask, Command.Undo);
-        KeyBindings.Add (KeyCode.R | KeyCode.CtrlMask, Command.Redo);
+        KeyBindings.Add (Key.Z.WithCtrl, Command.Undo);
+        KeyBindings.Add (Key.R.WithCtrl, Command.Redo);
 
-        KeyBindings.Add (KeyCode.G | KeyCode.CtrlMask, Command.DeleteAll);
-        KeyBindings.Add (KeyCode.D | KeyCode.CtrlMask | KeyCode.ShiftMask, Command.DeleteAll);
+        KeyBindings.Add (Key.G.WithCtrl, Command.DeleteAll);
+        KeyBindings.Add (Key.D.WithCtrl.WithShift, Command.DeleteAll);
 
         _currentCulture = Thread.CurrentThread.CurrentUICulture;
 
@@ -2863,7 +2853,7 @@ public class TextView : View
 
     /// <summary>Sets or gets the text in the <see cref="TextView"/>.</summary>
     /// <remarks>
-    ///     The <see cref="TextChanged"/> event is fired whenever this property is set. Note, however, that Text is not
+    ///     The <see cref="View.TextChanged"/> event is fired whenever this property is set. Note, however, that Text is not
     ///     set by <see cref="TextView"/> as the user types.
     /// </remarks>
     public override string Text
@@ -2879,6 +2869,7 @@ public class TextView : View
         }
         set
         {
+            var old = Text;
             ResetPosition ();
             _model.LoadString (value);
 
@@ -2888,7 +2879,7 @@ public class TextView : View
                 _model = _wrapManager.WrapModel (_frameWidth, out _, out _, out _, out _);
             }
 
-            TextChanged?.Invoke (this, EventArgs.Empty);
+            OnTextChanged (old,Text);
             SetNeedsDisplay ();
 
             _historyText.Clear (Text);
@@ -2961,7 +2952,7 @@ public class TextView : View
 
     /// <summary>Raised when the contents of the <see cref="TextView"/> are changed.</summary>
     /// <remarks>
-    ///     Unlike the <see cref="TextChanged"/> event, this event is raised whenever the user types or otherwise changes
+    ///     Unlike the <see cref="View.TextChanged"/> event, this event is raised whenever the user types or otherwise changes
     ///     the contents of the <see cref="TextView"/>.
     /// </remarks>
     public event EventHandler<ContentsChangedEventArgs>? ContentsChanged;
@@ -3723,15 +3714,14 @@ public class TextView : View
     }
 
     /// <inheritdoc/>
-    public override bool OnKeyUp (Key a)
+    public override bool OnKeyUp (Key key)
     {
-        switch (a.KeyCode)
+        if (key == Key.Space.WithCtrl)
         {
-            case KeyCode.Space | KeyCode.CtrlMask:
-                return true;
+            return true;
         }
 
-        return base.OnKeyUp (a);
+        return base.OnKeyUp (key);
     }
 
     /// <inheritdoc/>
@@ -3993,12 +3983,12 @@ public class TextView : View
         SetNeedsDisplay ();
     }
 
-    /// <summary>Raised when the <see cref="Text"/> property of the <see cref="TextView"/> changes.</summary>
-    /// <remarks>
-    ///     The <see cref="Text"/> property of <see cref="TextView"/> only changes when it is explicitly set, not as the
-    ///     user types. To be notified as the user changes the contents of the TextView see <see cref="IsDirty"/>.
-    /// </remarks>
-    public event EventHandler? TextChanged;
+    ///// <summary>Raised when the <see cref="Text"/> property of the <see cref="TextView"/> changes.</summary>
+    ///// <remarks>
+    /////     The <see cref="Text"/> property of <see cref="TextView"/> only changes when it is explicitly set, not as the
+    /////     user types. To be notified as the user changes the contents of the TextView see <see cref="IsDirty"/>.
+    ///// </remarks>
+    //public event EventHandler? TextChanged;
 
     /// <summary>Undoes the latest changes.</summary>
     public void Undo ()
@@ -4377,7 +4367,7 @@ public class TextView : View
         DoNeededAction ();
     }
 
-    private void ContextMenu_KeyChanged (object sender, KeyChangedEventArgs e) { KeyBindings.Replace ((KeyCode)e.OldKey, (KeyCode)e.NewKey); }
+    private void ContextMenu_KeyChanged (object sender, KeyChangedEventArgs e) { KeyBindings.Replace (e.OldKey, e.NewKey); }
 
     private bool DeleteTextBackwards ()
     {
@@ -6465,8 +6455,8 @@ public class TextView : View
         _selectionStartRow = CurrentRow;
     }
 
-    private void Top_AlternateBackwardKeyChanged (object sender, KeyChangedEventArgs e) { KeyBindings.Replace ((KeyCode)e.OldKey, (KeyCode)e.NewKey); }
-    private void Top_AlternateForwardKeyChanged (object sender, KeyChangedEventArgs e) { KeyBindings.Replace ((KeyCode)e.OldKey, (KeyCode)e.NewKey); }
+    private void Top_AlternateBackwardKeyChanged (object sender, KeyChangedEventArgs e) { KeyBindings.Replace (e.OldKey, e.NewKey); }
+    private void Top_AlternateForwardKeyChanged (object sender, KeyChangedEventArgs e) { KeyBindings.Replace (e.OldKey, e.NewKey); }
 
     // Tries to snap the cursor to the tracking column
     private void TrackColumn ()

+ 9 - 7
Terminal.Gui/Views/Tile.cs

@@ -1,4 +1,6 @@
-namespace Terminal.Gui;
+using System.ComponentModel;
+
+namespace Terminal.Gui;
 
 /// <summary>
 ///     A single <see cref="ContentView"/> presented in a <see cref="TileView"/>. To create new instances use
@@ -59,7 +61,7 @@ public class Tile
     /// <param name="newTitle">The new <see cref="Title"/> to be replaced.</param>
     public virtual void OnTitleChanged (string oldTitle, string newTitle)
     {
-        var args = new TitleEventArgs (oldTitle, newTitle);
+        var args = new StringEventArgs (oldTitle, newTitle);
         TitleChanged?.Invoke (this, args);
     }
 
@@ -72,18 +74,18 @@ public class Tile
     /// <returns><c>true</c> if an event handler cancelled the Title change.</returns>
     public virtual bool OnTitleChanging (string oldTitle, string newTitle)
     {
-        var args = new TitleEventArgs (oldTitle, newTitle);
+        var args = new StringEventArgs (oldTitle, newTitle);
         TitleChanging?.Invoke (this, args);
 
         return args.Cancel;
     }
 
     /// <summary>Event fired after the <see cref="Title"/> has been changed.</summary>
-    public event EventHandler<TitleEventArgs> TitleChanged;
+    public event EventHandler<StringEventArgs> TitleChanged;
 
     /// <summary>
-    ///     Event fired when the <see cref="Title"/> is changing. Set <see cref="TitleEventArgs.Cancel"/> to <c>true</c>
-    ///     to cancel the Title change.
+    ///     Event fired when the <see cref="Title"/> is changing.
+    ///     <see cref="CancelEventArgs.Cancel"/> can be set to <c>true</c> to cancel the change.
     /// </summary>
-    public event EventHandler<TitleEventArgs> TitleChanging;
+    public event EventHandler<StringEventArgs> TitleChanging;
 }

+ 4 - 4
Terminal.Gui/Views/TileView.cs

@@ -880,10 +880,10 @@ public class TileView : View
 
             AddCommand (Command.LineDown, () => { return MoveSplitter (0, 1); });
 
-            KeyBindings.Add (KeyCode.CursorRight, Command.Right);
-            KeyBindings.Add (KeyCode.CursorLeft, Command.Left);
-            KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-            KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
+            KeyBindings.Add (Key.CursorRight, Command.Right);
+            KeyBindings.Add (Key.CursorLeft, Command.Left);
+            KeyBindings.Add (Key.CursorUp, Command.LineUp);
+            KeyBindings.Add (Key.CursorDown, Command.LineDown);
         }
 
         public int Idx { get; }

+ 12 - 9
Terminal.Gui/Views/TimeField.cs

@@ -59,11 +59,10 @@ public class TimeField : TextField
         AddCommand (Command.Right, () => MoveRight ());
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.Delete, Command.DeleteCharRight);
+        KeyBindings.Add (Key.Delete, Command.DeleteCharRight);
         KeyBindings.Add (Key.D.WithCtrl, Command.DeleteCharRight);
 
         KeyBindings.Add (Key.Backspace, Command.DeleteCharLeft);
-        KeyBindings.Add (Key.D.WithAlt, Command.DeleteCharLeft);
 
         KeyBindings.Add (Key.Home, Command.LeftHome);
         KeyBindings.Add (Key.A.WithCtrl, Command.LeftHome);
@@ -76,6 +75,10 @@ public class TimeField : TextField
 
         KeyBindings.Add (Key.CursorRight, Command.Right);
         KeyBindings.Add (Key.F.WithCtrl, Command.Right);
+
+#if UNIX_KEY_BINDINGS
+        KeyBindings.Add (Key.D.WithAlt, Command.DeleteCharLeft);
+#endif
     }
 
     /// <inheritdoc/>
@@ -427,15 +430,15 @@ public class TimeField : TextField
         return true;
     }
 
-    private void TextField_TextChanging (object sender, TextChangingEventArgs e)
+    private void TextField_TextChanging (object sender, StateEventArgs<string> e)
     {
         try
         {
             var spaces = 0;
 
-            for (var i = 0; i < e.NewText.Length; i++)
+            for (var i = 0; i < e.NewValue.Length; i++)
             {
-                if (e.NewText [i] == ' ')
+                if (e.NewValue [i] == ' ')
                 {
                     spaces++;
                 }
@@ -446,17 +449,17 @@ public class TimeField : TextField
             }
 
             spaces += FieldLength;
-            string trimedText = e.NewText [..spaces];
+            string trimedText = e.NewValue [..spaces];
             spaces -= FieldLength;
             trimedText = trimedText.Replace (new string (' ', spaces), " ");
 
-            if (trimedText != e.NewText)
+            if (trimedText != e.NewValue)
             {
-                e.NewText = trimedText;
+                e.NewValue = trimedText;
             }
 
             if (!TimeSpan.TryParseExact (
-                                         e.NewText.Trim (),
+                                         e.NewValue.Trim (),
                                          Format.Trim (),
                                          CultureInfo.CurrentCulture,
                                          TimeSpanStyles.None,

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

@@ -65,7 +65,7 @@ public static partial class Application
 
         View top = FindTopFromView (Top?.MostFocused);
 
-        if (top is { } && Top.Subviews.Count > 1 && Top.Subviews [Top.Subviews.Count - 1] != top)
+        if (top is Toplevel && Top.Subviews.Count > 1 && Top.Subviews [Top.Subviews.Count - 1] != top)
         {
             Top.BringSubviewToFront (top);
         }

+ 36 - 33
Terminal.Gui/Views/TreeView/TreeView.cs

@@ -7,7 +7,7 @@ using System.Collections.ObjectModel;
 namespace Terminal.Gui;
 
 /// <summary>
-///     Interface for all non generic members of <see cref="TreeView{T}"/>.
+///     Interface for all non-generic members of <see cref="TreeView{T}"/>.
 ///     <a href="../docs/treeview.md">See TreeView Deep Dive for more information</a>.
 /// </summary>
 public interface ITreeView
@@ -272,38 +272,31 @@ public class TreeView<T> : View, ITreeView where T : class
                     }
                    );
 
-        AddCommand (
-                    Command.Accept,
-                    () =>
-                    {
-                        ActivateSelectedObjectIfAny ();
-
-                        return true;
-                    }
-                   );
+        AddCommand (Command.Select, ActivateSelectedObjectIfAny);
+        AddCommand (Command.Accept, ActivateSelectedObjectIfAny);
 
         // Default keybindings for this view
-        KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
-        KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
-        KeyBindings.Add (KeyCode.PageUp | KeyCode.ShiftMask, Command.PageUpExtend);
-        KeyBindings.Add (KeyCode.PageDown | KeyCode.ShiftMask, Command.PageDownExtend);
-        KeyBindings.Add (KeyCode.CursorRight, Command.Expand);
-        KeyBindings.Add (KeyCode.CursorRight | KeyCode.CtrlMask, Command.ExpandAll);
-        KeyBindings.Add (KeyCode.CursorLeft, Command.Collapse);
-        KeyBindings.Add (KeyCode.CursorLeft | KeyCode.CtrlMask, Command.CollapseAll);
-
-        KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
-        KeyBindings.Add (KeyCode.CursorUp | KeyCode.ShiftMask, Command.LineUpExtend);
-        KeyBindings.Add (KeyCode.CursorUp | KeyCode.CtrlMask, Command.LineUpToFirstBranch);
-
-        KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
-        KeyBindings.Add (KeyCode.CursorDown | KeyCode.ShiftMask, Command.LineDownExtend);
-        KeyBindings.Add (KeyCode.CursorDown | KeyCode.CtrlMask, Command.LineDownToLastBranch);
-
-        KeyBindings.Add (KeyCode.Home, Command.TopHome);
-        KeyBindings.Add (KeyCode.End, Command.BottomEnd);
-        KeyBindings.Add (KeyCode.A | KeyCode.CtrlMask, Command.SelectAll);
-        KeyBindings.Add (ObjectActivationKey, Command.Accept);
+        KeyBindings.Add (Key.PageUp, Command.PageUp);
+        KeyBindings.Add (Key.PageDown, Command.PageDown);
+        KeyBindings.Add (Key.PageUp.WithShift, Command.PageUpExtend);
+        KeyBindings.Add (Key.PageDown.WithShift, Command.PageDownExtend);
+        KeyBindings.Add (Key.CursorRight, Command.Expand);
+        KeyBindings.Add (Key.CursorRight.WithCtrl, Command.ExpandAll);
+        KeyBindings.Add (Key.CursorLeft, Command.Collapse);
+        KeyBindings.Add (Key.CursorLeft.WithCtrl, Command.CollapseAll);
+
+        KeyBindings.Add (Key.CursorUp, Command.LineUp);
+        KeyBindings.Add (Key.CursorUp.WithShift, Command.LineUpExtend);
+        KeyBindings.Add (Key.CursorUp.WithCtrl, Command.LineUpToFirstBranch);
+
+        KeyBindings.Add (Key.CursorDown, Command.LineDown);
+        KeyBindings.Add (Key.CursorDown.WithShift, Command.LineDownExtend);
+        KeyBindings.Add (Key.CursorDown.WithCtrl, Command.LineDownToLastBranch);
+
+        KeyBindings.Add (Key.Home, Command.TopHome);
+        KeyBindings.Add (Key.End, Command.BottomEnd);
+        KeyBindings.Add (Key.A.WithCtrl, Command.SelectAll);
+        KeyBindings.Add (ObjectActivationKey, Command.Select);
     }
 
     /// <summary>
@@ -459,15 +452,25 @@ public class TreeView<T> : View, ITreeView where T : class
     ///     <para>Triggers the <see cref="ObjectActivated"/> event with the <see cref="SelectedObject"/>.</para>
     ///     <para>This method also ensures that the selected object is visible.</para>
     /// </summary>
-    public void ActivateSelectedObjectIfAny ()
+    /// <returns><see langword="true"/> if <see cref="ObjectActivated"/> was fired.</returns>
+    public bool? ActivateSelectedObjectIfAny ()
     {
+        if (OnAccept () == true)
+        {
+            return false;
+        }
+
         T o = SelectedObject;
 
         if (o is { })
         {
-            OnObjectActivated (new ObjectActivatedEventArgs<T> (this, o));
+            // TODO: Should this be cancelable?
+            ObjectActivatedEventArgs<T> e = new (this, o);
+            OnObjectActivated (e);
             PositionCursor ();
+            return true;
         }
+        return false;
     }
 
     /// <summary>Adds a new root level object unless it is already a root of the tree.</summary>

+ 8 - 10
Terminal.Gui/Views/Wizard/Wizard.cs

@@ -100,8 +100,8 @@ public class Wizard : Dialog
         NextFinishButton.IsDefault = true;
         AddButton (NextFinishButton);
 
-        BackButton.Clicked += BackBtn_Clicked;
-        NextFinishButton.Clicked += NextfinishBtn_Clicked;
+        BackButton.Accept += BackBtn_Clicked;
+        NextFinishButton.Accept += NextfinishBtn_Clicked;
 
         Loaded += Wizard_Loaded;
         Closing += Wizard_Closing;
@@ -110,7 +110,7 @@ public class Wizard : Dialog
         if (Modal)
         {
             KeyBindings.Clear (Command.QuitToplevel);
-            KeyBindings.Add (KeyCode.Esc, Command.QuitToplevel);
+            KeyBindings.Add (Key.Esc, Command.QuitToplevel);
         }
 
         SetNeedsLayout ();
@@ -408,17 +408,15 @@ public class Wizard : Dialog
     ///     <see cref="OnProcessKeyDown"/> to instead fire the <see cref="Cancelled"/> event when Wizard is being used as a
     ///     non-modal (see <see cref="Wizard.Modal"/>.
     /// </summary>
-    /// <param name="a"></param>
+    /// <param name="key"></param>
     /// <returns></returns>
-    public override bool OnProcessKeyDown (Key a)
+    public override bool OnProcessKeyDown (Key key)
     {
         //// BUGBUG: Why is this not handled by a key binding???
         if (!Modal)
         {
-            switch (a.KeyCode)
+            if (key == Key.Esc)
             {
-                // BUGBUG: This should be handled by Dialog 
-                case KeyCode.Esc:
                     var args = new WizardButtonEventArgs ();
                     Cancelled?.Invoke (this, args);
 
@@ -582,11 +580,11 @@ public class Wizard : Dialog
         // gets the first step if CurrentStep == null
     }
 
-    private void Wizard_TitleChanged (object sender, TitleEventArgs e)
+    private void Wizard_TitleChanged (object sender, StateEventArgs<string> e)
     {
         if (string.IsNullOrEmpty (_wizardTitle))
         {
-            _wizardTitle = e.NewTitle;
+            _wizardTitle = e.NewValue;
         }
     }
 }

+ 3 - 3
UICatalog/KeyBindingsDialog.cs

@@ -43,11 +43,11 @@ internal class KeyBindingsDialog : Dialog
 
         var btnChange = new Button { X = Pos.Percent (50), Y = 1, Text = "Ch_ange" };
         Add (btnChange);
-        btnChange.Clicked += RemapKey;
+        btnChange.Accept += RemapKey;
 
         var close = new Button { Text = "Ok" };
 
-        close.Clicked += (s, e) =>
+        close.Accept += (s, e) =>
                          {
                              Application.RequestStop ();
                              ViewTracker.Instance.StartUsingNewKeyMap (CurrentBindings);
@@ -55,7 +55,7 @@ internal class KeyBindingsDialog : Dialog
         AddButton (close);
 
         var cancel = new Button { Text = "Cancel" };
-        cancel.Clicked += (s, e) => Application.RequestStop ();
+        cancel.Accept += (s, e) => Application.RequestStop ();
         AddButton (cancel);
 
         // Register event handler as the last thing in constructor to prevent early calls

+ 3 - 3
UICatalog/Scenarios/ASCIICustomButton.cs

@@ -143,7 +143,7 @@ public class ASCIICustomButtonTest : Scenario
                     SetNeedsDisplay ();
                 }
 
-                OnClicked ();
+                OnAccept ();
 
                 return true;
             }
@@ -224,7 +224,7 @@ public class ASCIICustomButtonTest : Scenario
                     Height = BUTTON_HEIGHT
                 };
                 button.CustomInitialize ();
-                button.Clicked += Button_Clicked;
+                button.Accept += Button_Clicked;
                 button.PointerEnter += Button_PointerEnter;
                 button.MouseClick += Button_MouseClick;
                 button.KeyDown += Button_KeyPress;
@@ -243,7 +243,7 @@ public class ASCIICustomButtonTest : Scenario
                 Height = BUTTON_HEIGHT
             };
             closeButton.CustomInitialize ();
-            closeButton.Clicked += Button_Clicked;
+            closeButton.Accept += Button_Clicked;
             closeButton.PointerEnter += Button_PointerEnter;
             closeButton.MouseClick += Button_MouseClick;
             closeButton.KeyDown += Button_KeyPress;

+ 34 - 79
UICatalog/Scenarios/Adornments.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 using Terminal.Gui;
 
@@ -17,7 +18,7 @@ public class Adornments : Scenario
         ConfigurationManager.Apply ();
         Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
 
-        var view = new Window { Title = "The Window" };
+        var view = new Window { Title = "The _Window" };
         var tf1 = new TextField { Width = 10, Text = "TextField" };
         var color = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd (11) };
         color.BorderStyle = LineStyle.RoundedDotted;
@@ -35,7 +36,7 @@ public class Adornments : Scenario
 
         var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Press me!" };
 
-        button.Clicked += (s, e) =>
+        button.Accept += (s, e) =>
                               MessageBox.Query (20, 7, "Hi", $"Am I a {view.GetType ().Name}?", "Yes", "No");
 
         var label = new TextView
@@ -97,7 +98,7 @@ public class Adornments : Scenario
     {
         private readonly ColorPicker _backgroundColorPicker = new ()
         {
-            Title = "BG",
+            Title = "_BG",
             BoxWidth = 1,
             BoxHeight = 1,
             BorderStyle = LineStyle.Single,
@@ -106,7 +107,7 @@ public class Adornments : Scenario
 
         private readonly ColorPicker _foregroundColorPicker = new ()
         {
-            Title = "FG",
+            Title = "_FG",
             BoxWidth = 1,
             BoxHeight = 1,
             BorderStyle = LineStyle.Single,
@@ -187,37 +188,41 @@ public class Adornments : Scenario
             var editWidth = 3;
 
             _topEdit = new TextField { X = Pos.Center (), Y = 0, Width = editWidth };
-            _topEdit.TextChanging += Edit_TextChanging;
+
+            _topEdit.Accept += Edit_Accept;
             Add (_topEdit);
 
             _leftEdit = new TextField
             {
                 X = Pos.Left (_topEdit) - editWidth, Y = Pos.Bottom (_topEdit), Width = editWidth
             };
-            _leftEdit.TextChanging += Edit_TextChanging;
+
+            _leftEdit.Accept += Edit_Accept;
             Add (_leftEdit);
 
             _rightEdit = new TextField { X = Pos.Right (_topEdit), Y = Pos.Bottom (_topEdit), Width = editWidth };
-            _rightEdit.TextChanging += Edit_TextChanging;
+
+            _rightEdit.Accept += Edit_Accept;
             Add (_rightEdit);
 
             _bottomEdit = new TextField { X = Pos.Center (), Y = Pos.Bottom (_leftEdit), Width = editWidth };
-            _bottomEdit.TextChanging += Edit_TextChanging;
+
+            _bottomEdit.Accept += Edit_Accept;
             Add (_bottomEdit);
 
             var copyTop = new Button { X = Pos.Center () + 1, Y = Pos.Bottom (_bottomEdit), Text = "Cop_y Top" };
 
-            copyTop.Clicked += (s, e) =>
-                               {
-                                   Thickness = new Thickness (Thickness.Top);
+            copyTop.Accept += (s, e) =>
+                              {
+                                  Thickness = new Thickness (Thickness.Top);
 
-                                   if (string.IsNullOrEmpty (_topEdit.Text))
-                                   {
-                                       _topEdit.Text = "0";
-                                   }
+                                  if (string.IsNullOrEmpty (_topEdit.Text))
+                                  {
+                                      _topEdit.Text = "0";
+                                  }
 
-                                   _bottomEdit.Text = _leftEdit.Text = _rightEdit.Text = _topEdit.Text;
-                               };
+                                  _bottomEdit.Text = _leftEdit.Text = _rightEdit.Text = _topEdit.Text;
+                              };
             Add (copyTop);
 
             // Foreground ColorPicker.
@@ -258,67 +263,17 @@ public class Adornments : Scenario
             LayoutSubviews ();
             Height = GetAdornmentsThickness ().Vertical + 4 + 4;
             Width = GetAdornmentsThickness ().Horizontal + _foregroundColorPicker.Frame.Width * 2 - 3;
-        }
 
-        private void Edit_TextChanging (object sender, TextChangingEventArgs e)
-        {
-            try
-            {
-                if (string.IsNullOrEmpty (e.NewText))
-                {
-                    e.Cancel = true;
-                    ((TextField)sender).Text = "0";
-
-                    return;
-                }
 
-                switch (sender.ToString ())
-                {
-                    case var s when s == _topEdit.ToString ():
-                        Thickness = new Thickness (
-                                                   Thickness.Left,
-                                                   int.Parse (e.NewText),
-                                                   Thickness.Right,
-                                                   Thickness.Bottom
-                                                  );
-
-                        break;
-                    case var s when s == _leftEdit.ToString ():
-                        Thickness = new Thickness (
-                                                   int.Parse (e.NewText),
-                                                   Thickness.Top,
-                                                   Thickness.Right,
-                                                   Thickness.Bottom
-                                                  );
-
-                        break;
-                    case var s when s == _rightEdit.ToString ():
-                        Thickness = new Thickness (
-                                                   Thickness.Left,
-                                                   Thickness.Top,
-                                                   int.Parse (e.NewText),
-                                                   Thickness.Bottom
-                                                  );
-
-                        break;
-                    case var s when s == _bottomEdit.ToString ():
-                        Thickness = new Thickness (
-                                                   Thickness.Left,
-                                                   Thickness.Top,
-                                                   Thickness.Right,
-                                                   int.Parse (e.NewText)
-                                                  );
+        }
 
-                        break;
-                }
-            }
-            catch
-            {
-                if (!string.IsNullOrEmpty (e.NewText))
-                {
-                    e.Cancel = true;
-                }
-            }
+        private void Edit_Accept (object sender, CancelEventArgs e)
+        {
+            e.Cancel = true;
+            Thickness = new Thickness(int.Parse(_leftEdit.Text),
+                                      int.Parse(_topEdit.Text),
+                                      int.Parse (_rightEdit.Text),
+                                      int.Parse (_bottomEdit.Text));
         }
     }
 
@@ -343,7 +298,7 @@ public class Adornments : Scenario
                 {
                     X = 0,
                     Y = 0,
-                    Title = "Margin",
+                    Title = "_Margin",
                     Thickness = _viewToEdit.Margin.Thickness,
                     Color = new Attribute (_viewToEdit.Margin.ColorScheme.Normal),
                     SuperViewRendersLineCanvas = true
@@ -356,7 +311,7 @@ public class Adornments : Scenario
                 {
                     X = Pos.Left (_marginEditor),
                     Y = Pos.Bottom (_marginEditor),
-                    Title = "Border",
+                    Title = "B_order",
                     Thickness = _viewToEdit.Border.Thickness,
                     Color = new Attribute (_viewToEdit.Border.ColorScheme.Normal),
                     SuperViewRendersLineCanvas = true
@@ -373,7 +328,7 @@ public class Adornments : Scenario
                     Y = Pos.Top (_borderEditor),
                     SelectedItem = (int)_viewToEdit.Border.LineStyle,
                     BorderStyle = LineStyle.Double,
-                    Title = "Border Style",
+                    Title = "Border St_yle",
                     SuperViewRendersLineCanvas = true,
                     RadioLabels = borderStyleEnum.Select (
                                                           e => e.ToString ()
@@ -435,7 +390,7 @@ public class Adornments : Scenario
                 {
                     X = Pos.Left (_borderEditor),
                     Y = Pos.Bottom (rbBorderStyle),
-                    Title = "Padding",
+                    Title = "_Padding",
                     Thickness = _viewToEdit.Padding.Thickness,
                     Color = new Attribute (_viewToEdit.Padding.ColorScheme.Normal),
                     SuperViewRendersLineCanvas = true

+ 1 - 1
UICatalog/Scenarios/AllViewsTester.cs

@@ -291,7 +291,7 @@ public class AllViewsTester : Scenario
         _curView = CreateClass (_viewClasses.First ().Value);
     }
 
-    // TODO: Add Command.Default handler (pop a message box?)
+    // TODO: Add Command.HotKey handler (pop a message box?)
     private View CreateClass (Type type)
     {
         // If we are to create a generic Type

+ 2 - 2
UICatalog/Scenarios/BackgroundWorkerCollection.cs

@@ -263,7 +263,7 @@ public class BackgroundWorkerCollection : Scenario
 
             _start = new Button { Text = "Start", IsDefault = true, ClearOnVisibleFalse = false };
 
-            _start.Clicked += (s, e) =>
+            _start.Accept += (s, e) =>
                               {
                                   Staging = new Staging (DateTime.Now);
                                   RequestStop ();
@@ -271,7 +271,7 @@ public class BackgroundWorkerCollection : Scenario
             Add (_start);
 
             _close = new Button { Text = "Close" };
-            _close.Clicked += OnReportClosed;
+            _close.Accept += OnReportClosed;
             Add (_close);
 
             KeyDown += (s, e) =>

+ 12 - 12
UICatalog/Scenarios/Buttons.cs

@@ -22,12 +22,12 @@ public class Buttons : Scenario
         // This is the default button (IsDefault = true); if user presses ENTER in the TextField
         // the scenario will quit
         var defaultButton = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), IsDefault = true, Text = "_Quit" };
-        defaultButton.Clicked += (s, e) => Application.RequestStop ();
+        defaultButton.Accept += (s, e) => Application.RequestStop ();
         Win.Add (defaultButton);
 
         var swapButton = new Button { X = 50, Text = "S_wap Default (Absolute Layout)" };
 
-        swapButton.Clicked += (s, e) =>
+        swapButton.Accept += (s, e) =>
                               {
                                   defaultButton.IsDefault = !defaultButton.IsDefault;
                                   swapButton.IsDefault = !swapButton.IsDefault;
@@ -36,7 +36,7 @@ public class Buttons : Scenario
 
         static void DoMessage (Button button, string txt)
         {
-            button.Clicked += (s, e) =>
+            button.Accept += (s, e) =>
                               {
                                   string btnText = button.Text;
                                   MessageBox.Query ("Message", $"Did you click {txt}?", "Yes", "No");
@@ -87,11 +87,11 @@ public class Buttons : Scenario
         Win.Add (
                  button = new Button { X = 2, Y = Pos.Bottom (button) + 1, Text = "a Newline\nin the button" }
                 );
-        button.Clicked += (s, e) => MessageBox.Query ("Message", "Question?", "Yes", "No");
+        button.Accept += (s, e) => MessageBox.Query ("Message", "Question?", "Yes", "No");
 
         var textChanger = new Button { X = 2, Y = Pos.Bottom (button) + 1, Text = "Te_xt Changer" };
         Win.Add (textChanger);
-        textChanger.Clicked += (s, e) => textChanger.Text += "!";
+        textChanger.Accept += (s, e) => textChanger.Text += "!";
 
         Win.Add (
                  button = new Button
@@ -109,7 +109,7 @@ public class Buttons : Scenario
         Win.Add (removeButton);
 
         // This in interesting test case because `moveBtn` and below are laid out relative to this one!
-        removeButton.Clicked += (s, e) =>
+        removeButton.Accept += (s, e) =>
                                 {
                                     // Now this throw a InvalidOperationException on the TopologicalSort method as is expected.
                                     //Win.Remove (removeButton);
@@ -139,7 +139,7 @@ public class Buttons : Scenario
             Text = "Move This \u263b Button v_ia Pos"
         };
 
-        moveBtn.Clicked += (s, e) =>
+        moveBtn.Accept += (s, e) =>
                            {
                                moveBtn.X = moveBtn.Frame.X + 5;
 
@@ -160,7 +160,7 @@ public class Buttons : Scenario
             Text = "Size This \u263a Button _via Pos"
         };
 
-        sizeBtn.Clicked += (s, e) =>
+        sizeBtn.Accept += (s, e) =>
                            {
                                sizeBtn.Width = sizeBtn.Frame.Width + 5;
 
@@ -181,7 +181,7 @@ public class Buttons : Scenario
         // Demonstrates how changing the View.Frame property can move Views
         var moveBtnA = new Button { ColorScheme = Colors.ColorSchemes ["Error"], Text = "Move This Button via Frame" };
 
-        moveBtnA.Clicked += (s, e) =>
+        moveBtnA.Accept += (s, e) =>
                             {
                                 moveBtnA.Frame = new Rectangle (
                                                            moveBtnA.Frame.X + 5,
@@ -198,7 +198,7 @@ public class Buttons : Scenario
             Y = 2, ColorScheme = Colors.ColorSchemes ["Error"], Text = " ~  s  gui.cs   master ↑_10 = Сохранить"
         };
 
-        sizeBtnA.Clicked += (s, e) =>
+        sizeBtnA.Accept += (s, e) =>
                             {
                                 sizeBtnA.Frame = new Rectangle (
                                                            sizeBtnA.Frame.X,
@@ -268,7 +268,7 @@ public class Buttons : Scenario
             ColorScheme = Colors.ColorSchemes ["TopLevel"],
             Text = mhkb
         };
-        moveHotKeyBtn.Clicked += (s, e) => { moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text); };
+        moveHotKeyBtn.Accept += (s, e) => { moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text); };
         Win.Add (moveHotKeyBtn);
 
         var muhkb = " ~  s  gui.cs   master ↑10 = Сохранить";
@@ -283,7 +283,7 @@ public class Buttons : Scenario
             ColorScheme = Colors.ColorSchemes ["TopLevel"],
             Text = muhkb
         };
-        moveUnicodeHotKeyBtn.Clicked += (s, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); };
+        moveUnicodeHotKeyBtn.Accept += (s, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); };
         Win.Add (moveUnicodeHotKeyBtn);
 
         radioGroup.SelectedItemChanged += (s, args) =>

+ 15 - 4
UICatalog/Scenarios/CharacterMap.cs

@@ -3,6 +3,7 @@
 //#define BASE_DRAW_CONTENT
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Globalization;
 using System.Linq;
 using System.Net.Http;
@@ -64,8 +65,18 @@ public class CharacterMap : Scenario
         };
         Application.Top.Add (_errorLabel);
 
+#if TEXT_CHANGED_TO_JUMP
         jumpEdit.TextChanged += JumpEdit_TextChanged;
+#else
+        jumpEdit.Accept += JumpEditOnAccept;
 
+        void JumpEditOnAccept (object sender, CancelEventArgs e)
+        {
+            JumpEdit_TextChanged (sender, new StateEventArgs<string> (jumpEdit.Text, jumpEdit.Text));
+            // Cancel the event to prevent ENTER from being handled elsewhere
+            e.Cancel = true;
+        }
+#endif
         _categoryList = new TableView { X = Pos.Right (_charMap), Y = Pos.Bottom (jumpLabel), Height = Dim.Fill () };
 
         _categoryList.FullRowSelect = true;
@@ -212,7 +223,7 @@ public class CharacterMap : Scenario
         return item;
     }
 
-    private void JumpEdit_TextChanged (object sender, TextChangedEventArgs e)
+    private void JumpEdit_TextChanged (object sender, StateEventArgs<string> e)
     {
         var jumpEdit = sender as TextField;
 
@@ -941,18 +952,18 @@ internal class CharMap : ScrollView
 
             var dlg = new Dialog { Title = title, Buttons = [copyGlyph, copyCP, cancel] };
 
-            copyGlyph.Clicked += (s, a) =>
+            copyGlyph.Accept += (s, a) =>
                                  {
                                      CopyGlyph ();
                                      dlg.RequestStop ();
                                  };
 
-            copyCP.Clicked += (s, a) =>
+            copyCP.Accept += (s, a) =>
                               {
                                   CopyCodePoint ();
                                   dlg.RequestStop ();
                               };
-            cancel.Clicked += (s, a) => dlg.RequestStop ();
+            cancel.Accept += (s, a) => dlg.RequestStop ();
 
             var rune = (Rune)SelectedCodePoint;
             var label = new Label { Text = "IsAscii: ", X = 0, Y = 0 };

+ 1 - 1
UICatalog/Scenarios/ChineseUI.cs

@@ -33,7 +33,7 @@ public class ChineseUI : Scenario
 
         var btn = new Button { X = 1, Y = 1, Text = "你" }; // v1: A
 
-        btn.Clicked += (s, e) =>
+        btn.Accept += (s, e) =>
                        {
                            int result = MessageBox.Query (
                                                           "Confirm",

+ 1 - 1
UICatalog/Scenarios/Clipping.cs

@@ -67,7 +67,7 @@ public class Clipping : Scenario
         };
 
         var testButton = new Button { X = 2, Y = 2, Text = "click me" };
-        testButton.Clicked += (s, e) => { MessageBox.Query (10, 5, "Test", "test message", "Ok"); };
+        testButton.Accept += (s, e) => { MessageBox.Query (10, 5, "Test", "test message", "Ok"); };
         embedded3.Add (testButton);
         embedded2.Add (embedded3);
 

+ 2 - 2
UICatalog/Scenarios/ComboBoxIteration.cs

@@ -58,7 +58,7 @@ public class ComboBoxIteration : Scenario
 
         var btnTwo = new Button { X = Pos.Right (comboBox) + 1, Text = "Two" };
 
-        btnTwo.Clicked += (s, e) =>
+        btnTwo.Accept += (s, e) =>
                           {
                               items = new List<string> { "one", "two" };
                               comboBox.SetSource (items);
@@ -69,7 +69,7 @@ public class ComboBoxIteration : Scenario
 
         var btnThree = new Button { X = Pos.Right (comboBox) + 1, Y = Pos.Top (comboBox), Text = "Three" };
 
-        btnThree.Clicked += (s, e) =>
+        btnThree.Accept += (s, e) =>
                             {
                                 items = new List<string> { "one", "two", "three" };
                                 comboBox.SetSource (items);

+ 4 - 4
UICatalog/Scenarios/ComputedLayout.cs

@@ -318,7 +318,7 @@ public class ComputedLayout : Scenario
         var anchorButton = new Button { Text = "Button using AnchorEnd", Y = Pos.AnchorEnd () - 1 };
         anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
 
-        anchorButton.Clicked += (s, e) =>
+        anchorButton.Accept += (s, e) =>
                                 {
                                     // This demonstrates how to have a dynamically sized button
                                     // Each time the button is clicked the button's text gets longer
@@ -364,7 +364,7 @@ public class ComputedLayout : Scenario
             Text = "Left", Y = Pos.AnchorEnd () - 1 // Pos.Combine
         };
 
-        leftButton.Clicked += (s, e) =>
+        leftButton.Accept += (s, e) =>
                               {
                                   // This demonstrates how to have a dynamically sized button
                                   // Each time the button is clicked the button's text gets longer
@@ -380,7 +380,7 @@ public class ComputedLayout : Scenario
             Text = "Center", X = Pos.Center (), Y = Pos.AnchorEnd (1) // Pos.AnchorEnd(1)
         };
 
-        centerButton.Clicked += (s, e) =>
+        centerButton.Accept += (s, e) =>
                                 {
                                     // This demonstrates how to have a dynamically sized button
                                     // Each time the button is clicked the button's text gets longer
@@ -393,7 +393,7 @@ public class ComputedLayout : Scenario
         // show positioning vertically using another window and Pos.Bottom
         var rightButton = new Button { Text = "Right", Y = Pos.Y (centerButton) };
 
-        rightButton.Clicked += (s, e) =>
+        rightButton.Accept += (s, e) =>
                                {
                                    // This demonstrates how to have a dynamically sized button
                                    // Each time the button is clicked the button's text gets longer

+ 1 - 1
UICatalog/Scenarios/ContextMenus.cs

@@ -21,7 +21,7 @@ public class ContextMenus : Scenario
     {
         var text = "Context Menu";
         var width = 20;
-        KeyCode winContextMenuKey = KeyCode.Space | KeyCode.CtrlMask;
+        KeyCode winContextMenuKey = (KeyCode)Key.Space.WithCtrl;
 
         var label = new Label
         {

+ 3 - 3
UICatalog/Scenarios/CsvEditor.cs

@@ -299,13 +299,13 @@ public class CsvEditor : Scenario
 
         var ok = new Button { Text = "Ok", IsDefault = true };
 
-        ok.Clicked += (s, e) =>
+        ok.Accept += (s, e) =>
                       {
                           okPressed = true;
                           Application.RequestStop ();
                       };
         var cancel = new Button { Text = "Cancel" };
-        cancel.Clicked += (s, e) => { Application.RequestStop (); };
+        cancel.Accept += (s, e) => { Application.RequestStop (); };
         var d = new Dialog { Title = title, Buttons = [ok, cancel] };
 
         var lbl = new Label { X = 0, Y = 1, Text = label };
@@ -556,7 +556,7 @@ public class CsvEditor : Scenario
         }
     }
 
-    private void SelectedCellLabel_TextChanged (object sender, TextChangedEventArgs e)
+    private void SelectedCellLabel_TextChanged (object sender, StateEventArgs<string> e)
     {
         // if user is in the text control and editing the selected cell
         if (!_selectedCellLabel.HasFocus)

+ 43 - 33
UICatalog/Scenarios/Dialogs.cs

@@ -14,12 +14,27 @@ public class Dialogs : Scenario
     {
         var frame = new FrameView { X = Pos.Center (), Y = 1, Width = Dim.Percent (75), Title = "Dialog Options" };
 
-        var label = new Label { X = 0, Y = 0, TextAlignment = TextAlignment.Right, Text = "Width:" };
+        var numButtonsLabel = new Label
+        {
+            X = 0,
+            TextAlignment = TextAlignment.Right,
+            Text = "_Number of Buttons:"
+        };
+
+        var label = new Label {
+            X = 0, 
+            Y = 0,
+            AutoSize = false,
+            Width = Dim.Width (numButtonsLabel),
+            Height = 1,
+            TextAlignment = TextAlignment.Right,
+            Text = "_Width:"
+        };
         frame.Add (label);
 
         var widthEdit = new TextField
         {
-            X = Pos.Right (label) + 1,
+            X = Pos.Right (numButtonsLabel) + 1,
             Y = Pos.Top (label),
             Width = 5,
             Height = 1,
@@ -32,16 +47,16 @@ public class Dialogs : Scenario
             AutoSize = false,
             X = 0,
             Y = Pos.Bottom (label),
-            Width = Dim.Width (label),
+            Width = Dim.Width (numButtonsLabel),
             Height = 1,
             TextAlignment = TextAlignment.Right,
-            Text = "Height:"
+            Text = "_Height:"
         };
         frame.Add (label);
 
         var heightEdit = new TextField
         {
-            X = Pos.Right (label) + 1,
+            X = Pos.Right (numButtonsLabel) + 1,
             Y = Pos.Top (label),
             Width = 5,
             Height = 1,
@@ -67,10 +82,10 @@ public class Dialogs : Scenario
             AutoSize = false,
             X = 0,
             Y = Pos.Bottom (label),
-            Width = Dim.Width (label),
+            Width = Dim.Width (numButtonsLabel),
             Height = 1,
             TextAlignment = TextAlignment.Right,
-            Text = "Title:"
+            Text = "_Title:"
         };
         frame.Add (label);
 
@@ -84,22 +99,13 @@ public class Dialogs : Scenario
         };
         frame.Add (titleEdit);
 
-        label = new Label
-        {
-            AutoSize = false,
-            X = 0,
-            Y = Pos.Bottom (label),
-            Width = Dim.Width (label),
-            Height = 1,
-            TextAlignment = TextAlignment.Right,
-            Text = "Num Buttons:"
-        };
-        frame.Add (label);
+        numButtonsLabel.Y = Pos.Bottom (label);
+        frame.Add (numButtonsLabel);
 
         var numButtonsEdit = new TextField
         {
-            X = Pos.Right (label) + 1,
-            Y = Pos.Top (label),
+            X = Pos.Right (numButtonsLabel) + 1,
+            Y = Pos.Top (numButtonsLabel),
             Width = 5,
             Height = 1,
             Text = "3"
@@ -108,21 +114,25 @@ public class Dialogs : Scenario
 
         var glyphsNotWords = new CheckBox
         {
-            X = Pos.Left (numButtonsEdit),
-            Y = Pos.Bottom (label),
+            X = Pos.Right (numButtonsLabel) + 1,
+            Y = Pos.Bottom (numButtonsLabel),
             TextAlignment = TextAlignment.Right,
-            Text =
-                $"Add {char.ConvertFromUtf32 (CODE_POINT)} to button text to stress wide char support",
+            Text = $"_Add {char.ConvertFromUtf32 (CODE_POINT)} to button text to stress wide char support",
             Checked = false
         };
         frame.Add (glyphsNotWords);
 
         label = new Label
         {
-            X = 0, Y = Pos.Bottom (glyphsNotWords), TextAlignment = TextAlignment.Right, Text = "Button Style:"
+            AutoSize = false,
+            X = 0,
+            Y = Pos.Bottom (glyphsNotWords),
+            Width = Dim.Width (numButtonsLabel),
+            Height = 1,
+            TextAlignment = TextAlignment.Right,
+            Text = "Button St_yle:"
         };
         frame.Add (label);
-
         var styleRadioGroup = new RadioGroup
         {
             X = Pos.Right (label) + 1,
@@ -170,7 +180,7 @@ public class Dialogs : Scenario
             X = Pos.Center (), Y = Pos.Bottom (frame) + 2, IsDefault = true, Text = "_Show Dialog"
         };
 
-        showDialogButton.Clicked += (s, e) =>
+        showDialogButton.Accept += (s, e) =>
                                     {
                                         Dialog dlg = CreateDemoDialog (
                                                                        widthEdit,
@@ -233,7 +243,7 @@ public class Dialogs : Scenario
                     button = new Button { Text = NumberToWords.Convert (buttonId), IsDefault = buttonId == 0 };
                 }
 
-                button.Clicked += (s, e) =>
+                button.Accept += (s, e) =>
                                   {
                                       clicked = buttonId;
                                       Application.RequestStop ();
@@ -264,9 +274,9 @@ public class Dialogs : Scenario
                 dialog.Width = width;
             }
 
-            var add = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Add a button" };
+            var add = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "_Add a button" };
 
-            add.Clicked += (s, e) =>
+            add.Accept += (s, e) =>
                            {
                                int buttonId = buttons.Count;
                                Button button;
@@ -284,7 +294,7 @@ public class Dialogs : Scenario
                                    button = new Button { Text = NumberToWords.Convert (buttonId), IsDefault = buttonId == 0 };
                                }
 
-                               button.Clicked += (s, e) =>
+                               button.Accept += (s, e) =>
                                                  {
                                                      clicked = buttonId;
                                                      Application.RequestStop ();
@@ -303,10 +313,10 @@ public class Dialogs : Scenario
             {
                 X = Pos.Center (),
                 Y = Pos.Center () + 1,
-                Text = $"Add a {char.ConvertFromUtf32 (CODE_POINT)} to each button"
+                Text = $"A_dd a {char.ConvertFromUtf32 (CODE_POINT)} to each button"
             };
 
-            addChar.Clicked += (s, e) =>
+            addChar.Accept += (s, e) =>
                                {
                                    foreach (Button button in buttons)
                                    {

+ 16 - 16
UICatalog/Scenarios/DynamicMenuBar.cs

@@ -237,7 +237,7 @@ public class DynamicMenuBar : Scenario
             {
                 X = Pos.X (_lblShortcut), Y = Pos.Bottom (TextShortcut) + 1, Text = "Clear Shortcut"
             };
-            _btnShortcut.Clicked += (s, e) => { TextShortcut.Text = ""; };
+            _btnShortcut.Accept += (s, e) => { TextShortcut.Text = ""; };
             Add (_btnShortcut);
 
             CkbIsTopLevel.Toggled += (s, e) =>
@@ -419,7 +419,7 @@ public class DynamicMenuBar : Scenario
 
             var _btnOk = new Button { IsDefault = true, Text = "Ok" };
 
-            _btnOk.Clicked += (s, e) =>
+            _btnOk.Accept += (s, e) =>
                               {
                                   if (string.IsNullOrEmpty (TextTitle.Text))
                                   {
@@ -433,7 +433,7 @@ public class DynamicMenuBar : Scenario
                               };
             var _btnCancel = new Button { Text = "Cancel" };
 
-            _btnCancel.Clicked += (s, e) =>
+            _btnCancel.Accept += (s, e) =>
                                   {
                                       TextTitle.Text = string.Empty;
                                       Application.RequestStop ();
@@ -684,7 +684,7 @@ public class DynamicMenuBar : Scenario
             };
             Add (_frmMenuDetails);
 
-            _btnMenuBarUp.Clicked += (s, e) =>
+            _btnMenuBarUp.Accept += (s, e) =>
                                      {
                                          int i = _currentSelectedMenuBar;
 
@@ -706,7 +706,7 @@ public class DynamicMenuBar : Scenario
                                          }
                                      };
 
-            _btnMenuBarDown.Clicked += (s, e) =>
+            _btnMenuBarDown.Accept += (s, e) =>
                                        {
                                            int i = _currentSelectedMenuBar;
 
@@ -728,7 +728,7 @@ public class DynamicMenuBar : Scenario
                                            }
                                        };
 
-            _btnUp.Clicked += (s, e) =>
+            _btnUp.Accept += (s, e) =>
                               {
                                   int i = _lstMenus.SelectedItem;
                                   MenuItem menuItem = DataContext.Menus.Count > 0 ? DataContext.Menus [i].MenuItem : null;
@@ -750,7 +750,7 @@ public class DynamicMenuBar : Scenario
                                   }
                               };
 
-            _btnDown.Clicked += (s, e) =>
+            _btnDown.Accept += (s, e) =>
                                 {
                                     int i = _lstMenus.SelectedItem;
                                     MenuItem menuItem = DataContext.Menus.Count > 0 ? DataContext.Menus [i].MenuItem : null;
@@ -772,7 +772,7 @@ public class DynamicMenuBar : Scenario
                                     }
                                 };
 
-            _btnPreviowsParent.Clicked += (s, e) =>
+            _btnPreviowsParent.Accept += (s, e) =>
                                           {
                                               if (_currentMenuBarItem != null && _currentMenuBarItem.Parent != null)
                                               {
@@ -805,12 +805,12 @@ public class DynamicMenuBar : Scenario
             Add (_btnOk);
 
             var _btnCancel = new Button { X = Pos.Right (_btnOk) + 3, Y = Pos.Top (_btnOk), Text = "Cancel" };
-            _btnCancel.Clicked += (s, e) => { SetFrameDetails (_currentEditMenuBarItem); };
+            _btnCancel.Accept += (s, e) => { SetFrameDetails (_currentEditMenuBarItem); };
             Add (_btnCancel);
 
             _lstMenus.SelectedItemChanged += (s, e) => { SetFrameDetails (); };
 
-            _btnOk.Clicked += (s, e) =>
+            _btnOk.Accept += (s, e) =>
                               {
                                   if (string.IsNullOrEmpty (_frmMenuDetails.TextTitle.Text) && _currentEditMenuBarItem != null)
                                   {
@@ -836,7 +836,7 @@ public class DynamicMenuBar : Scenario
                                   }
                               };
 
-            _btnAdd.Clicked += (s, e) =>
+            _btnAdd.Accept += (s, e) =>
                                {
                                    if (MenuBar == null)
                                    {
@@ -897,7 +897,7 @@ public class DynamicMenuBar : Scenario
                                    }
                                };
 
-            _btnRemove.Clicked += (s, e) =>
+            _btnRemove.Accept += (s, e) =>
                                   {
                                       MenuItem menuItem = DataContext.Menus.Count > 0
                                                               ? DataContext.Menus [_lstMenus.SelectedItem].MenuItem
@@ -989,7 +989,7 @@ public class DynamicMenuBar : Scenario
                                    SetFrameDetails (menuBarItem);
                                };
 
-            _btnNext.Clicked += (s, e) =>
+            _btnNext.Accept += (s, e) =>
                                 {
                                     if (_menuBar != null && _currentSelectedMenuBar + 1 < _menuBar.Menus.Length)
                                     {
@@ -999,7 +999,7 @@ public class DynamicMenuBar : Scenario
                                     SelectCurrentMenuBarItem ();
                                 };
 
-            _btnPrevious.Clicked += (s, e) =>
+            _btnPrevious.Accept += (s, e) =>
                                     {
                                         if (_currentSelectedMenuBar - 1 > -1)
                                         {
@@ -1018,7 +1018,7 @@ public class DynamicMenuBar : Scenario
                                      }
                                  };
 
-            _btnAddMenuBar.Clicked += (s, e) =>
+            _btnAddMenuBar.Accept += (s, e) =>
                                       {
                                           var frameDetails = new DynamicMenuBarDetails (null);
                                           DynamicMenuItem item = frameDetails.EnterMenuItem ();
@@ -1050,7 +1050,7 @@ public class DynamicMenuBar : Scenario
                                           _menuBar.SetNeedsDisplay ();
                                       };
 
-            _btnRemoveMenuBar.Clicked += (s, e) =>
+            _btnRemoveMenuBar.Accept += (s, e) =>
                                          {
                                              if (_menuBar == null || _menuBar.Menus.Length == 0)
                                              {

+ 11 - 11
UICatalog/Scenarios/DynamicStatusBar.cs

@@ -203,7 +203,7 @@ public class DynamicStatusBar : Scenario
             {
                 X = Pos.X (_lblShortcut), Y = Pos.Bottom (TextShortcut) + 1, Text = "Clear Shortcut"
             };
-            _btnShortcut.Clicked += (s, e) => { TextShortcut.Text = ""; };
+            _btnShortcut.Accept += (s, e) => { TextShortcut.Text = ""; };
             Add (_btnShortcut);
         }
 
@@ -255,7 +255,7 @@ public class DynamicStatusBar : Scenario
 
             var _btnOk = new Button { IsDefault = true, Text = "OK" };
 
-            _btnOk.Clicked += (s, e) =>
+            _btnOk.Accept += (s, e) =>
                               {
                                   if (string.IsNullOrEmpty (TextTitle.Text))
                                   {
@@ -277,7 +277,7 @@ public class DynamicStatusBar : Scenario
                               };
             var _btnCancel = new Button { Text = "Cancel" };
 
-            _btnCancel.Clicked += (s, e) =>
+            _btnCancel.Accept += (s, e) =>
                                   {
                                       TextTitle.Text = string.Empty;
                                       Application.RequestStop ();
@@ -406,7 +406,7 @@ public class DynamicStatusBar : Scenario
             };
             Add (_frmStatusBarDetails);
 
-            _btnUp.Clicked += (s, e) =>
+            _btnUp.Accept += (s, e) =>
                               {
                                   int i = _lstItems.SelectedItem;
                                   StatusItem statusItem = DataContext.Items.Count > 0 ? DataContext.Items [i].StatusItem : null;
@@ -429,7 +429,7 @@ public class DynamicStatusBar : Scenario
                                   }
                               };
 
-            _btnDown.Clicked += (s, e) =>
+            _btnDown.Accept += (s, e) =>
                                 {
                                     int i = _lstItems.SelectedItem;
                                     StatusItem statusItem = DataContext.Items.Count > 0 ? DataContext.Items [i].StatusItem : null;
@@ -459,12 +459,12 @@ public class DynamicStatusBar : Scenario
             Add (_btnOk);
 
             var _btnCancel = new Button { X = Pos.Right (_btnOk) + 3, Y = Pos.Top (_btnOk), Text = "Cancel" };
-            _btnCancel.Clicked += (s, e) => { SetFrameDetails (_currentEditStatusItem); };
+            _btnCancel.Accept += (s, e) => { SetFrameDetails (_currentEditStatusItem); };
             Add (_btnCancel);
 
             _lstItems.SelectedItemChanged += (s, e) => { SetFrameDetails (); };
 
-            _btnOk.Clicked += (s, e) =>
+            _btnOk.Accept += (s, e) =>
                               {
                                   if (string.IsNullOrEmpty (_frmStatusBarDetails.TextTitle.Text) && _currentEditStatusItem != null)
                                   {
@@ -487,7 +487,7 @@ public class DynamicStatusBar : Scenario
                                   }
                               };
 
-            _btnAdd.Clicked += (s, e) =>
+            _btnAdd.Accept += (s, e) =>
                                {
                                    if (StatusBar == null)
                                    {
@@ -517,7 +517,7 @@ public class DynamicStatusBar : Scenario
                                    SetFrameDetails ();
                                };
 
-            _btnRemove.Clicked += (s, e) =>
+            _btnRemove.Accept += (s, e) =>
                                   {
                                       StatusItem statusItem = DataContext.Items.Count > 0
                                                                   ? DataContext.Items [_lstItems.SelectedItem].StatusItem
@@ -546,7 +546,7 @@ public class DynamicStatusBar : Scenario
                                    SetFrameDetails (statusItem);
                                };
 
-            _btnAddStatusBar.Clicked += (s, e) =>
+            _btnAddStatusBar.Accept += (s, e) =>
                                         {
                                             if (_statusBar != null)
                                             {
@@ -557,7 +557,7 @@ public class DynamicStatusBar : Scenario
                                             Add (_statusBar);
                                         };
 
-            _btnRemoveStatusBar.Clicked += (s, e) =>
+            _btnRemoveStatusBar.Accept += (s, e) =>
                                            {
                                                if (_statusBar == null)
                                                {

+ 7 - 7
UICatalog/Scenarios/Editor.cs

@@ -907,7 +907,7 @@ public class Editor : Scenario
             AutoSize = false,
             Text = "Find _Next"
         };
-        btnFindNext.Clicked += (s, e) => FindNext ();
+        btnFindNext.Accept += (s, e) => FindNext ();
         d.Add (btnFindNext);
 
         var btnFindPrevious = new Button
@@ -920,7 +920,7 @@ public class Editor : Scenario
             AutoSize = false,
             Text = "Find _Previous"
         };
-        btnFindPrevious.Clicked += (s, e) => FindPrevious ();
+        btnFindPrevious.Accept += (s, e) => FindPrevious ();
         d.Add (btnFindPrevious);
 
         txtToFind.TextChanged += (s, e) =>
@@ -940,7 +940,7 @@ public class Editor : Scenario
             AutoSize = false,
             Text = "Cancel"
         };
-        btnCancel.Clicked += (s, e) => { DisposeWinDialog (); };
+        btnCancel.Accept += (s, e) => { DisposeWinDialog (); };
         d.Add (btnCancel);
 
         var ckbMatchCase = new CheckBox
@@ -1157,7 +1157,7 @@ public class Editor : Scenario
             AutoSize = false,
             Text = "Replace _Next"
         };
-        btnFindNext.Clicked += (s, e) => ReplaceNext ();
+        btnFindNext.Accept += (s, e) => ReplaceNext ();
         d.Add (btnFindNext);
 
         label = new Label { X = Pos.Left (label), Y = Pos.Top (label) + 1, Text = "Replace:" };
@@ -1182,7 +1182,7 @@ public class Editor : Scenario
             AutoSize = false,
             Text = "Replace _Previous"
         };
-        btnFindPrevious.Clicked += (s, e) => ReplacePrevious ();
+        btnFindPrevious.Accept += (s, e) => ReplacePrevious ();
         d.Add (btnFindPrevious);
 
         var btnReplaceAll = new Button
@@ -1195,7 +1195,7 @@ public class Editor : Scenario
             AutoSize = false,
             Text = "Replace _All"
         };
-        btnReplaceAll.Clicked += (s, e) => ReplaceAll ();
+        btnReplaceAll.Accept += (s, e) => ReplaceAll ();
         d.Add (btnReplaceAll);
 
         txtToFind.TextChanged += (s, e) =>
@@ -1216,7 +1216,7 @@ public class Editor : Scenario
             AutoSize = false,
             Text = "Cancel"
         };
-        btnCancel.Clicked += (s, e) => { DisposeWinDialog (); };
+        btnCancel.Accept += (s, e) => { DisposeWinDialog (); };
         d.Add (btnCancel);
 
         var ckbMatchCase = new CheckBox

+ 1 - 1
UICatalog/Scenarios/FileDialogExamples.cs

@@ -232,7 +232,7 @@ public class FileDialogExamples : Scenario
 
     private void SetupHandler (Button btn)
     {
-        btn.Clicked += (s, e) =>
+        btn.Accept += (s, e) =>
                        {
                            try
                            {

+ 138 - 0
UICatalog/Scenarios/HotKeys.cs

@@ -0,0 +1,138 @@
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios;
+
+[ScenarioMetadata ("HotKeys", "Demonstrates how HotKeys work.")]
+[ScenarioCategory ("Controls")]
+[ScenarioCategory("Mouse and Keyboard")]
+public class HotKeys : Scenario
+{
+    public override void Init ()
+    {
+        Application.Init ();
+        ConfigurationManager.Themes.Theme = Theme;
+        ConfigurationManager.Apply ();
+        Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
+        Application.Top.BorderStyle = LineStyle.RoundedDotted;
+        Application.Top.Title = $"{Application.QuitKey} to _Quit - Scenario: {GetName ()}";
+    }
+
+    public override void Run ()
+    {
+        var textViewLabel = new Label { Text = "_TextView:", X = 0, Y = 0 };
+        Application.Top.Add (textViewLabel);
+        
+        var textField = new TextField (){ X = Pos.Right (textViewLabel) + 1, Y = 0, Width = 10 };
+        Application.Top.Add (textField);
+
+        var viewLabel = new Label { Text = "_View:", X = 0, Y = Pos.Bottom (textField) + 1 };
+        Application.Top.Add (viewLabel);
+
+        var view = new View () { 
+            Title = "View (_focusable)", 
+            Text = "Text renders _Underscore", 
+            CanFocus = true,
+            X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3,
+            BorderStyle = LineStyle.Dashed,
+        };
+        Application.Top.Add (view);
+
+        viewLabel = new Label { Text = "Vi_ew:", X = 0, Y = Pos.Bottom (view) + 1 };
+        Application.Top.Add (viewLabel);
+
+        view = new View ()
+        {
+            Title = "View (n_ot focusable)",
+            Text = "Text renders _Underscore",
+            X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3,
+            BorderStyle = LineStyle.Dashed,
+        };
+        Application.Top.Add (view);
+
+        var labelWithFrameLabel = new Label { Text = "_Label with Frame:", X = 0, Y = Pos.Bottom (view) + 1 };
+        Application.Top.Add (labelWithFrameLabel);
+
+        var labelWithFrameFocusable = new Label ()
+        {
+            AutoSize = false,
+            Title = "Label _with Frame (focusable)",
+            CanFocus = true,
+            X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3,
+            BorderStyle = LineStyle.Dashed,
+        };
+        Application.Top.Add (labelWithFrameFocusable);
+
+        labelWithFrameLabel = new Label { Text = "L_abel with Frame:", X = 0, Y = Pos.Bottom (labelWithFrameFocusable) + 1 };
+        Application.Top.Add (labelWithFrameLabel);
+
+        var labelWithFrame = new Label ()
+        {
+            AutoSize = false,
+            Title = "Label with Frame (_not focusable)",
+            X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3,
+            BorderStyle = LineStyle.Dashed,
+        };
+        Application.Top.Add (labelWithFrame);
+
+        
+        var buttonWithFrameLabel = new Label { Text = "_Button with Frame:", X = 0, Y = Pos.Bottom (labelWithFrame) + 1 };
+        Application.Top.Add (buttonWithFrameLabel);
+
+        var buttonWithFrameFocusable = new Button ()
+        {
+            AutoSize = false,
+            Title = "B_utton with Frame (focusable)",
+            CanFocus = true,
+            X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3,
+            BorderStyle = LineStyle.Dashed,
+        };
+        Application.Top.Add (buttonWithFrameFocusable);
+
+        buttonWithFrameLabel = new Label { Text = "Butt_on with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrameFocusable) + 1 };
+        Application.Top.Add (buttonWithFrameLabel);
+
+        var buttonWithFrame = new Button ()
+        {
+            AutoSize = false,
+            Title = "Button with Frame (not focusab_le)",
+            X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3,
+            CanFocus = false,
+            BorderStyle = LineStyle.Dashed,
+        };
+        Application.Top.Add (buttonWithFrame);
+
+
+
+        var checkboxWithFrameLabel = new Label { Text = "_Checkbox with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrame) + 1 };
+        Application.Top.Add (checkboxWithFrameLabel);
+
+        var checkboxWithFrameFocusable = new CheckBox
+        {
+            AutoSize = false,
+            Title = "C_heckbox with Frame (focusable)",
+            CanFocus = true,
+            X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3,
+            BorderStyle = LineStyle.Dashed,
+        };
+        Application.Top.Add (checkboxWithFrameFocusable);
+
+        checkboxWithFrameLabel = new Label { Text = "Checkb_ox with Frame:", X = 0, Y = Pos.Bottom (checkboxWithFrameFocusable) + 1 };
+        Application.Top.Add (checkboxWithFrameLabel);
+
+        var checkboxWithFrame = new CheckBox
+        {
+            AutoSize = false,
+            Title = "Checkbox with Frame (not focusable)",
+            X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3,
+            CanFocus = false,
+            BorderStyle = LineStyle.Dashed,
+        };
+        Application.Top.Add (checkboxWithFrame);
+
+
+        var button = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), Text = "_Press me!" };
+        Application.Top.Add (button);
+
+        Application.Run (Application.Top);
+    }
+}

+ 1 - 1
UICatalog/Scenarios/Images.cs

@@ -55,7 +55,7 @@ public class Images : Scenario
         };
         Win.Add (imageView);
 
-        btnOpenImage.Clicked += (_, _) =>
+        btnOpenImage.Accept += (_, _) =>
                                 {
                                     var ofd = new OpenDialog { Title = "Open Image", AllowsMultipleSelection = false };
                                     Application.Run (ofd);

+ 2 - 2
UICatalog/Scenarios/InteractiveTree.cs

@@ -86,13 +86,13 @@ public class InteractiveTree : Scenario
 
         var ok = new Button { Text = "Ok", IsDefault = true };
 
-        ok.Clicked += (s, e) =>
+        ok.Accept += (s, e) =>
                       {
                           okPressed = true;
                           Application.RequestStop ();
                       };
         var cancel = new Button { Text = "Cancel" };
-        cancel.Clicked += (s, e) => Application.RequestStop ();
+        cancel.Accept += (s, e) => Application.RequestStop ();
         var d = new Dialog { Title = title, Buttons = [ok, cancel] };
 
         var lbl = new Label { X = 0, Y = 1, Text = label };

+ 1 - 1
UICatalog/Scenarios/InvertColors.cs

@@ -31,7 +31,7 @@ public class InvertColors : Scenario
 
         var button = new Button { X = Pos.Center (), Y = foreColors.Length + 1, Text = "Invert color!" };
 
-        button.Clicked += (s, e) =>
+        button.Accept += (s, e) =>
                           {
                               foreach (Label label in labels)
                               {

+ 0 - 386
UICatalog/Scenarios/LabelsAsButtons.cs

@@ -1,386 +0,0 @@
-using System.Collections.Generic;
-using System.Text;
-using Terminal.Gui;
-
-namespace UICatalog.Scenarios;
-
-[ScenarioMetadata ("Labels As Buttons", "Illustrates that Button is really just a Label++")]
-[ScenarioCategory ("Controls")]
-[ScenarioCategory ("Proof of Concept")]
-public class LabelsAsLabels : Scenario
-{
-    public override void Setup ()
-    {
-        // Add a label & text field so we can demo IsDefault
-        var editLabel = new Label { X = 0, Y = 0, Text = "TextField (to demo IsDefault):" };
-        Win.Add (editLabel);
-
-        // Add a TextField using Absolute layout. 
-        var edit = new TextField { X = 31, Width = 15 };
-        Win.Add (edit);
-
-        // This is the default Label (IsDefault = true); if user presses ENTER in the TextField
-        // the scenario will quit
-        var defaultLabel = new Label
-        {
-            X = Pos.Center (),
-            Y = Pos.Bottom (Win) - 3,
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = "_Quit"
-        };
-        defaultLabel.Clicked += (s, e) => Application.RequestStop ();
-        Win.Add (defaultLabel);
-
-        var swapLabel = new Label
-        {
-            X = 50, HotKeySpecifier = (Rune)'_', CanFocus = true, Text = "S_wap Default (Absolute Layout)"
-        };
-
-        swapLabel.Clicked += (s, e) =>
-                             {
-                                 //defaultLabel.IsDefault = !defaultLabel.IsDefault;
-                                 //swapLabel.IsDefault = !swapLabel.IsDefault;
-                             };
-        Win.Add (swapLabel);
-
-        static void DoMessage (Label Label, string txt)
-        {
-            Label.Clicked += (s, e) =>
-                             {
-                                 string btnText = Label.Text;
-                                 MessageBox.Query ("Message", $"Did you click {txt}?", "Yes", "No");
-                             };
-        }
-
-        var colorLabelsLabel = new Label { X = 0, Y = Pos.Bottom (editLabel) + 1, Text = "Color Labels:" };
-        Win.Add (colorLabelsLabel);
-
-        //With this method there is no need to call Application.TopReady += () => Application.TopRedraw (Top.Bounds);
-        Pos x = Pos.Right (colorLabelsLabel) + 2;
-
-        foreach (KeyValuePair<string, ColorScheme> colorScheme in Colors.ColorSchemes)
-        {
-            var colorLabel = new Label
-            {
-                ColorScheme = colorScheme.Value,
-                X = x,
-                Y = Pos.Y (colorLabelsLabel),
-                HotKeySpecifier = (Rune)'_',
-                CanFocus = true,
-                Text = $"{colorScheme.Key}"
-            };
-            DoMessage (colorLabel, colorLabel.Text);
-            Win.Add (colorLabel);
-            x += colorLabel.Text.Length + 2;
-        }
-
-        Application.Top.Ready += (s, e) => Application.Top.Draw ();
-
-        Label Label;
-
-        Win.Add (
-                 Label = new Label
-                 {
-                     X = 2,
-                     Y = Pos.Bottom (colorLabelsLabel) + 1,
-                     HotKeySpecifier = (Rune)'_',
-                     CanFocus = true,
-                     Text =
-                         "A super long _Label that will probably expose a bug in clipping or wrapping of text. Will it?"
-                 }
-                );
-        DoMessage (Label, Label.Text);
-
-        // Note the 'N' in 'Newline' will be the hotkey
-        Win.Add (
-                 Label = new Label
-                 {
-                     X = 2,
-                     Y = Pos.Bottom (Label) + 1,
-                     HotKeySpecifier = (Rune)'_',
-                     CanFocus = true,
-                     TextAlignment = TextAlignment.Centered,
-                     VerticalTextAlignment = VerticalTextAlignment.Middle,
-                     Text = "a Newline\nin the Label"
-                 }
-                );
-        Label.Clicked += (s, e) => MessageBox.Query ("Message", "Question?", "Yes", "No");
-
-        var textChanger = new Label
-        {
-            X = 2,
-            Y = Pos.Bottom (Label) + 1,
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = "Te_xt Changer"
-        };
-        Win.Add (textChanger);
-        textChanger.Clicked += (s, e) => textChanger.Text += "!";
-
-        Win.Add (
-                 Label = new Label
-                 {
-                     X = Pos.Right (textChanger) + 2,
-                     Y = Pos.Y (textChanger),
-                     HotKeySpecifier = (Rune)'_',
-                     CanFocus = true,
-                     Text = "Lets see if this will move as \"Text Changer\" grows"
-                 }
-                );
-
-        var removeLabel = new Label
-        {
-            X = 2,
-            Y = Pos.Bottom (Label) + 1,
-            ColorScheme = Colors.ColorSchemes ["Error"],
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = "Remove this Label"
-        };
-        Win.Add (removeLabel);
-
-        // This in interesting test case because `moveBtn` and below are laid out relative to this one!
-        removeLabel.Clicked += (s, e) =>
-                               {
-                                   // Now this throw a InvalidOperationException on the TopologicalSort method as is expected.
-                                   //Win.Remove (removeLabel);
-
-                                   removeLabel.Visible = false;
-                                   Win.SetNeedsDisplay ();
-                               };
-
-        var computedFrame = new FrameView
-        {
-            X = 0,
-            Y = Pos.Bottom (removeLabel) + 1,
-            Width = Dim.Percent (50),
-            Height = 5,
-            Title = "Computed Layout"
-        };
-        Win.Add (computedFrame);
-
-        // Demonstrates how changing the View.Frame property can move Views
-        var moveBtn = new Label
-        {
-            X = 0,
-            Y = Pos.Center () - 1,
-            AutoSize = false,
-            Width = 30,
-            ColorScheme = Colors.ColorSchemes ["Error"],
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = "Move This \u263b Label _via Pos"
-        };
-
-        moveBtn.Clicked += (s, e) =>
-                           {
-                               moveBtn.X = moveBtn.Frame.X + 5;
-
-                               // This is already fixed with the call to SetNeedDisplay() in the Pos Dim.
-                               //computedFrame.LayoutSubviews (); // BUGBUG: This call should not be needed. View.X is not causing relayout correctly
-                           };
-        computedFrame.Add (moveBtn);
-
-        // Demonstrates how changing the View.Frame property can SIZE Views (#583)
-        var sizeBtn = new Label
-        {
-            X = 0,
-            Y = Pos.Center () + 1,
-            AutoSize = false,
-            Width = 30,
-            ColorScheme = Colors.ColorSchemes ["Error"],
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = "Size This \u263a Label _via Pos"
-        };
-
-        sizeBtn.Clicked += (s, e) =>
-                           {
-                               sizeBtn.Width = sizeBtn.Frame.Width + 5;
-
-                               //computedFrame.LayoutSubviews (); // FIXED: This call should not be needed. View.X is not causing relayout correctly
-                           };
-        computedFrame.Add (sizeBtn);
-
-        var absoluteFrame = new FrameView
-        {
-            X = Pos.Right (computedFrame),
-            Y = Pos.Bottom (removeLabel) + 1,
-            Width = Dim.Fill (),
-            Height = 5,
-            Title = "Absolute Layout"
-        };
-        Win.Add (absoluteFrame);
-
-        // Demonstrates how changing the View.Frame property can move Views
-        var moveBtnA = new Label
-        {
-            ColorScheme = Colors.ColorSchemes ["Error"],
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = "Move This Label via Frame"
-        };
-
-        moveBtnA.Clicked += (s, e) =>
-                            {
-                                moveBtnA.Frame = new Rectangle (
-                                                           moveBtnA.Frame.X + 5,
-                                                           moveBtnA.Frame.Y,
-                                                           moveBtnA.Frame.Width,
-                                                           moveBtnA.Frame.Height
-                                                          );
-                            };
-        absoluteFrame.Add (moveBtnA);
-
-        // Demonstrates how changing the View.Frame property can SIZE Views (#583)
-        var sizeBtnA = new Label
-        {
-            Y = 2,
-            ColorScheme = Colors.ColorSchemes ["Error"],
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            AutoSize = false,
-            Text = " ~  s  gui.cs   master ↑10 = Со_хранить"
-        };
-
-        sizeBtnA.Clicked += (s, e) =>
-                            {
-                                sizeBtnA.Frame = new Rectangle (
-                                                           sizeBtnA.Frame.X,
-                                                           sizeBtnA.Frame.Y,
-                                                           sizeBtnA.Frame.Width + 5,
-                                                           sizeBtnA.Frame.Height
-                                                          );
-                            };
-        absoluteFrame.Add (sizeBtnA);
-
-        var label = new Label
-        {
-            X = 2,
-            Y = Pos.Bottom (computedFrame) + 1,
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = "Text Alignment (changes the four Labels above): "
-        };
-        Win.Add (label);
-
-        var radioGroup = new RadioGroup
-        {
-            X = 4,
-            Y = Pos.Bottom (label) + 1,
-            SelectedItem = 2,
-            RadioLabels = new [] { "Left", "Right", "Centered", "Justified" }
-        };
-        Win.Add (radioGroup);
-
-        // Demo changing hotkey
-        string MoveHotkey (string txt)
-        {
-            // Remove the '_'
-            List<Rune> runes = txt.ToRuneList ();
-
-            int i = runes.IndexOf ((Rune)'_');
-            var start = "";
-
-            if (i > -1)
-            {
-                start = StringExtensions.ToString (runes.GetRange (0, i));
-            }
-
-            txt = start + StringExtensions.ToString (runes.GetRange (i + 1, runes.Count - (i + 1)));
-
-            runes = txt.ToRuneList ();
-
-            // Move over one or go to start
-            i++;
-
-            if (i >= runes.Count)
-            {
-                i = 0;
-            }
-
-            // Slip in the '_'
-            start = StringExtensions.ToString (runes.GetRange (0, i));
-
-            return start + '_' + StringExtensions.ToString (runes.GetRange (i, runes.Count - i));
-        }
-
-        var mhkb = "Click to Change th_is Label's Hotkey";
-
-        var moveHotKeyBtn = new Label
-        {
-            X = 2,
-            Y = Pos.Bottom (radioGroup) + 1,
-            AutoSize = false,
-            Width = Dim.Width (computedFrame) - 2,
-            ColorScheme = Colors.ColorSchemes ["TopLevel"],
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = mhkb
-        };
-        moveHotKeyBtn.Clicked += (s, e) => { moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text); };
-        Win.Add (moveHotKeyBtn);
-
-        var muhkb = " ~  s  gui.cs   master ↑10 = Сохранить";
-
-        var moveUnicodeHotKeyBtn = new Label
-        {
-            X = Pos.Left (absoluteFrame) + 1,
-            Y = Pos.Bottom (radioGroup) + 1,
-            AutoSize = false,
-            Width = Dim.Width (absoluteFrame) - 2,
-            ColorScheme = Colors.ColorSchemes ["TopLevel"],
-            HotKeySpecifier = (Rune)'_',
-            CanFocus = true,
-            Text = muhkb
-        };
-        moveUnicodeHotKeyBtn.Clicked += (s, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); };
-        Win.Add (moveUnicodeHotKeyBtn);
-
-        radioGroup.SelectedItemChanged += (s, args) =>
-                                          {
-                                              switch (args.SelectedItem)
-                                              {
-                                                  case 0:
-                                                      moveBtn.TextAlignment = TextAlignment.Left;
-                                                      sizeBtn.TextAlignment = TextAlignment.Left;
-                                                      moveBtnA.TextAlignment = TextAlignment.Left;
-                                                      sizeBtnA.TextAlignment = TextAlignment.Left;
-                                                      moveHotKeyBtn.TextAlignment = TextAlignment.Left;
-                                                      moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Left;
-
-                                                      break;
-                                                  case 1:
-                                                      moveBtn.TextAlignment = TextAlignment.Right;
-                                                      sizeBtn.TextAlignment = TextAlignment.Right;
-                                                      moveBtnA.TextAlignment = TextAlignment.Right;
-                                                      sizeBtnA.TextAlignment = TextAlignment.Right;
-                                                      moveHotKeyBtn.TextAlignment = TextAlignment.Right;
-                                                      moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Right;
-
-                                                      break;
-                                                  case 2:
-                                                      moveBtn.TextAlignment = TextAlignment.Centered;
-                                                      sizeBtn.TextAlignment = TextAlignment.Centered;
-                                                      moveBtnA.TextAlignment = TextAlignment.Centered;
-                                                      sizeBtnA.TextAlignment = TextAlignment.Centered;
-                                                      moveHotKeyBtn.TextAlignment = TextAlignment.Centered;
-                                                      moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Centered;
-
-                                                      break;
-                                                  case 3:
-                                                      moveBtn.TextAlignment = TextAlignment.Justified;
-                                                      sizeBtn.TextAlignment = TextAlignment.Justified;
-                                                      moveBtnA.TextAlignment = TextAlignment.Justified;
-                                                      sizeBtnA.TextAlignment = TextAlignment.Justified;
-                                                      moveHotKeyBtn.TextAlignment = TextAlignment.Justified;
-                                                      moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Justified;
-
-                                                      break;
-                                              }
-                                          };
-
-        Application.Top.Ready += (s, e) => radioGroup.Refresh ();
-    }
-}

+ 1 - 1
UICatalog/Scenarios/LineDrawing.cs

@@ -208,7 +208,7 @@ public class LineDrawing : Scenario
 
             _addLayerBtn = new Button { Text = "New Layer", X = Pos.Center (), Y = Pos.Bottom (_stylePicker) };
 
-            _addLayerBtn.Clicked += (s, a) => AddLayer?.Invoke ();
+            _addLayerBtn.Accept += (s, a) => AddLayer?.Invoke ();
             Add (_colorPicker, _stylePicker, _addLayerBtn);
         }
 

+ 3 - 3
UICatalog/Scenarios/ListColumns.cs

@@ -267,7 +267,7 @@ public class ListColumns : Scenario
         // if user clicks the mouse in TableView
         _listColView.MouseClick += (s, e) => { _listColView.ScreenToCell (e.MouseEvent.X, e.MouseEvent.Y, out int? clickedCol); };
 
-        _listColView.KeyBindings.Add (KeyCode.Space, Command.ToggleChecked);
+        _listColView.KeyBindings.Add (Key.Space, Command.Accept);
     }
 
     private void CloseExample () { _listColView.Table = null; }
@@ -279,13 +279,13 @@ public class ListColumns : Scenario
         var accepted = false;
         var ok = new Button { Text = "Ok", IsDefault = true };
 
-        ok.Clicked += (s, e) =>
+        ok.Accept += (s, e) =>
                       {
                           accepted = true;
                           Application.RequestStop ();
                       };
         var cancel = new Button { Text = "Cancel" };
-        cancel.Clicked += (s, e) => { Application.RequestStop (); };
+        cancel.Accept += (s, e) => { Application.RequestStop (); };
         var d = new Dialog { Title = prompt, Buttons = [ok, cancel] };
 
         var tf = new TextField { Text = getter (_listColView).ToString (), X = 0, Y = 1, Width = Dim.Fill () };

+ 7 - 6
UICatalog/Scenarios/ListViewWithSelection.cs

@@ -1,6 +1,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Text;
+using JetBrains.Annotations;
 using Terminal.Gui;
 
 namespace UICatalog.Scenarios;
@@ -102,9 +103,9 @@ public class ListViewWithSelection : Scenario
         Win.Add (keepCheckBox);
     }
 
-    private void _customRenderCB_Toggled (object sender, ToggleEventArgs e)
+    private void _customRenderCB_Toggled (object sender, StateEventArgs<bool?> stateEventArgs)
     {
-        if (e.OldValue == true)
+        if (stateEventArgs.OldValue == true)
         {
             _listView.SetSource (_scenarios);
         }
@@ -116,16 +117,16 @@ public class ListViewWithSelection : Scenario
         Win.SetNeedsDisplay ();
     }
 
-    private void AllowMarkingCB_Toggled (object sender, ToggleEventArgs e)
+    private void AllowMarkingCB_Toggled (object sender, [NotNull] StateEventArgs<bool?> stateEventArgs)
     {
-        _listView.AllowsMarking = (bool)!e.OldValue;
+        _listView.AllowsMarking = (bool)!stateEventArgs.OldValue;
         _allowMultipleCB.Visible = _listView.AllowsMarking;
         Win.SetNeedsDisplay ();
     }
 
-    private void AllowMultipleCB_Toggled (object sender, ToggleEventArgs e)
+    private void AllowMultipleCB_Toggled (object sender, [NotNull] StateEventArgs<bool?> stateEventArgs)
     {
-        _listView.AllowsMultipleSelection = (bool)!e.OldValue;
+        _listView.AllowsMultipleSelection = (bool)!stateEventArgs.OldValue;
         Win.SetNeedsDisplay ();
     }
 

+ 2 - 2
UICatalog/Scenarios/ListsAndCombos.cs

@@ -145,13 +145,13 @@ public class ListsAndCombos : Scenario
                                 };
 
         var btnMoveUp = new Button { X = 1, Y = Pos.Bottom (lbListView), Text = "Move _Up" };
-        btnMoveUp.Clicked += (s, e) => { listview.MoveUp (); };
+        btnMoveUp.Accept += (s, e) => { listview.MoveUp (); };
 
         var btnMoveDown = new Button
         {
             X = Pos.Right (btnMoveUp) + 1, Y = Pos.Bottom (lbListView), Text = "Move _Down"
         };
-        btnMoveDown.Clicked += (s, e) => { listview.MoveDown (); };
+        btnMoveDown.Accept += (s, e) => { listview.MoveDown (); };
 
         Win.Add (btnMoveUp, btnMoveDown);
     }

+ 3 - 3
UICatalog/Scenarios/Localization.cs

@@ -150,14 +150,14 @@ public class Localization : Scenario
         {
             X = Pos.Right (_allowAnyCheckBox) + 1, Y = Pos.Bottom (textAndFileDialogLabel) + 1, Text = "Open"
         };
-        openDialogButton.Clicked += (sender, e) => ShowFileDialog (false);
+        openDialogButton.Accept += (sender, e) => ShowFileDialog (false);
         Win.Add (openDialogButton);
 
         var saveDialogButton = new Button
         {
             X = Pos.Right (openDialogButton) + 1, Y = Pos.Bottom (textAndFileDialogLabel) + 1, Text = "Save"
         };
-        saveDialogButton.Clicked += (sender, e) => ShowFileDialog (true);
+        saveDialogButton.Accept += (sender, e) => ShowFileDialog (true);
         Win.Add (saveDialogButton);
 
         var wizardLabel = new Label
@@ -171,7 +171,7 @@ public class Localization : Scenario
         Win.Add (wizardLabel);
 
         var wizardButton = new Button { X = 2, Y = Pos.Bottom (wizardLabel) + 1, Text = "Open _wizard" };
-        wizardButton.Clicked += (sender, e) => ShowWizard ();
+        wizardButton.Accept += (sender, e) => ShowWizard ();
         Win.Add (wizardButton);
 
         Win.Unloaded += (sender, e) => Quit ();

+ 3 - 3
UICatalog/Scenarios/MenuBarScenario.cs

@@ -279,15 +279,15 @@ public class MenuBarScenario : Scenario
         menuBar.LayoutComplete += (s, e) => { _focusedView.Text = Application.Top.MostFocused?.ToString () ?? "None"; };
 
         var openBtn = new Button { X = Pos.Center (), Y = 4, Text = "_Open Menu", IsDefault = true };
-        openBtn.Clicked += (s, e) => { menuBar.OpenMenu (); };
+        openBtn.Accept += (s, e) => { menuBar.OpenMenu (); };
         Application.Top.Add (openBtn);
 
         var hideBtn = new Button { X = Pos.Center (), Y = Pos.Bottom (openBtn), Text = "Toggle Menu._Visible" };
-        hideBtn.Clicked += (s, e) => { menuBar.Visible = !menuBar.Visible; };
+        hideBtn.Accept += (s, e) => { menuBar.Visible = !menuBar.Visible; };
         Application.Top.Add (hideBtn);
 
         var enableBtn = new Button { X = Pos.Center (), Y = Pos.Bottom (hideBtn), Text = "_Toggle Menu.Enable" };
-        enableBtn.Clicked += (s, e) => { menuBar.Enabled = !menuBar.Enabled; };
+        enableBtn.Accept += (s, e) => { menuBar.Enabled = !menuBar.Enabled; };
         Application.Top.Add (enableBtn);
 
         Application.Top.Add (menuBar);

+ 1 - 1
UICatalog/Scenarios/MessageBoxes.cs

@@ -215,7 +215,7 @@ public class MessageBoxes : Scenario
             X = Pos.Center (), Y = Pos.Bottom (frame) + 2, IsDefault = true, Text = "_Show MessageBox"
         };
 
-        showMessageBoxButton.Clicked += (s, e) =>
+        showMessageBoxButton.Accept += (s, e) =>
                                         {
                                             try
                                             {

+ 2 - 2
UICatalog/Scenarios/MultiColouredTable.cs

@@ -100,13 +100,13 @@ public class MultiColouredTable : Scenario
 
         var ok = new Button { Text = "Ok", IsDefault = true };
 
-        ok.Clicked += (s, e) =>
+        ok.Accept += (s, e) =>
                       {
                           okPressed = true;
                           Application.RequestStop ();
                       };
         var cancel = new Button { Text = "Cancel" };
-        cancel.Clicked += (s, e) => { Application.RequestStop (); };
+        cancel.Accept += (s, e) => { Application.RequestStop (); };
         var d = new Dialog { Title = title, Buttons = [ok, cancel] };
 
         var lbl = new Label { X = 0, Y = 1, Text = label };

+ 4 - 4
UICatalog/Scenarios/Progress.cs

@@ -139,7 +139,7 @@ public class Progress : Scenario
 
         var startBoth = new Button { X = Pos.Center (), Y = Pos.Bottom (mainLoopTimeoutDemo) + 1, Text = "Start Both" };
 
-        startBoth.Clicked += (s, e) =>
+        startBoth.Accept += (s, e) =>
                              {
                                  systemTimerDemo.Start ();
                                  mainLoopTimeoutDemo.Start ();
@@ -186,15 +186,15 @@ public class Progress : Scenario
             Add (LeftFrame);
 
             var startButton = new Button { X = Pos.Right (LeftFrame) + 1, Y = 0, Text = "Start Timer" };
-            startButton.Clicked += (s, e) => Start ();
+            startButton.Accept += (s, e) => Start ();
             var pulseButton = new Button { X = Pos.Right (startButton) + 2, Y = Pos.Y (startButton), Text = "Pulse" };
-            pulseButton.Clicked += (s, e) => Pulse ();
+            pulseButton.Accept += (s, e) => Pulse ();
 
             var stopbutton = new Button
             {
                 X = Pos.Right (pulseButton) + 2, Y = Pos.Top (pulseButton), Text = "Stop Timer"
             };
-            stopbutton.Clicked += (s, e) => Stop ();
+            stopbutton.Accept += (s, e) => Stop ();
 
             Add (startButton);
             Add (pulseButton);

+ 3 - 3
UICatalog/Scenarios/ProgressBarStyles.cs

@@ -91,7 +91,7 @@ public class ProgressBarStyles : Scenario
         };
         editor.Add (fgColorPickerBtn);
 
-        fgColorPickerBtn.Clicked += (s, e) =>
+        fgColorPickerBtn.Accept += (s, e) =>
                                     {
                                         ColorName newColor = ChooseColor (
                                                                           fgColorPickerBtn.Text,
@@ -116,7 +116,7 @@ public class ProgressBarStyles : Scenario
         };
         editor.Add (bgColorPickerBtn);
 
-        bgColorPickerBtn.Clicked += (s, e) =>
+        bgColorPickerBtn.Accept += (s, e) =>
                                     {
                                         ColorName newColor = ChooseColor (
                                                                           fgColorPickerBtn.Text,
@@ -177,7 +177,7 @@ public class ProgressBarStyles : Scenario
         };
         editor.Add (continuousPB);
 
-        button.Clicked += (s, e) =>
+        button.Accept += (s, e) =>
                           {
                               if (_fractionTimer == null)
                               {

+ 1 - 1
UICatalog/Scenarios/RunTExample.cs

@@ -60,7 +60,7 @@ public class RunTExample : Scenario
             };
 
             // When login button is clicked display a message popup
-            btnLogin.Clicked += (s, e) =>
+            btnLogin.Accept += (s, e) =>
                                 {
                                     if (_usernameText.Text == "admin" && passwordText.Text == "password")
                                     {

+ 6 - 6
UICatalog/Scenarios/RuneWidthGreaterThanOne.cs

@@ -103,7 +103,7 @@ public class RuneWidthGreaterThanOne : Scenario
         _label.Text = "Enter your name 你:";
         _text.Text = "gui.cs 你:";
         _button.Text = "Say Hello 你";
-        _button.Clicked += MixedMessage;
+        _button.Accept += MixedMessage;
         _labelR.X = Pos.AnchorEnd (21);
         _labelR.Y = 18;
         _labelR.Text = "This is a test text 你";
@@ -123,7 +123,7 @@ public class RuneWidthGreaterThanOne : Scenario
         _label.Text = "Enter your name:";
         _text.Text = "gui.cs";
         _button.Text = "Say Hello";
-        _button.Clicked += NarrowMessage;
+        _button.Accept += NarrowMessage;
         _labelR.X = Pos.AnchorEnd (19);
         _labelR.Y = 18;
         _labelR.Text = "This is a test text";
@@ -140,15 +140,15 @@ public class RuneWidthGreaterThanOne : Scenario
         switch (_lastRunesUsed)
         {
             case "Narrow":
-                _button.Clicked -= NarrowMessage;
+                _button.Accept -= NarrowMessage;
 
                 break;
             case "Mixed":
-                _button.Clicked -= MixedMessage;
+                _button.Accept -= MixedMessage;
 
                 break;
             case "Wide":
-                _button.Clicked -= WideMessage;
+                _button.Accept -= WideMessage;
 
                 break;
         }
@@ -162,7 +162,7 @@ public class RuneWidthGreaterThanOne : Scenario
         _label.Text = "あなたの名前を入力してください:";
         _text.Text = "ティラミス";
         _button.Text = "こんにちはと言う";
-        _button.Clicked += WideMessage;
+        _button.Accept += WideMessage;
         _labelR.X = Pos.AnchorEnd (29);
         _labelR.Y = 18;
         _labelR.Text = "あなたの名前を入力してください";

+ 3 - 3
UICatalog/Scenarios/Scrolling.cs

@@ -84,7 +84,7 @@ public class Scrolling : Scenario
         Application.Top.Loaded += Top_Loaded;
 
         var pressMeButton = new Button { X = 3, Y = 3, Text = "Press me!" };
-        pressMeButton.Clicked += (s, e) => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No");
+        pressMeButton.Accept += (s, e) => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No");
         scrollView.Add (pressMeButton);
 
         var aLongButton = new Button
@@ -95,7 +95,7 @@ public class Scrolling : Scenario
             Width = Dim.Fill (3),
             Text = "A very long button. Should be wide enough to demo clipping!"
         };
-        aLongButton.Clicked += (s, e) => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No");
+        aLongButton.Accept += (s, e) => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No");
         scrollView.Add (aLongButton);
 
         scrollView.Add (
@@ -137,7 +137,7 @@ public class Scrolling : Scenario
         // TODO: Use Pos.Width instead of (Right-Left) when implemented (#502)
         anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
 
-        anchorButton.Clicked += (s, e) =>
+        anchorButton.Accept += (s, e) =>
                                 {
                                     // This demonstrates how to have a dynamically sized button
                                     // Each time the button is clicked the button's text gets longer

+ 1 - 1
UICatalog/Scenarios/SendKeys.cs

@@ -98,7 +98,7 @@ public class SendKeys : Scenario
             txtInput.SetFocus ();
         }
 
-        button.Clicked += (s, e) => ProcessInput ();
+        button.Accept += (s, e) => ProcessInput ();
 
         Win.KeyDown += (s, e) =>
                        {

+ 1 - 1
UICatalog/Scenarios/SingleBackgroundWorker.cs

@@ -101,7 +101,7 @@ public class SingleBackgroundWorker : Scenario
 
             var cancel = new Button { Text = "Cancel Worker" };
 
-            cancel.Clicked += (s, e) =>
+            cancel.Accept += (s, e) =>
                               {
                                   if (_worker == null)
                                   {

+ 5 - 5
UICatalog/Scenarios/TableEditor.cs

@@ -767,7 +767,7 @@ public class TableEditor : Scenario
                                      }
                                  };
 
-        _tableView.KeyBindings.Add (KeyCode.Space, Command.ToggleChecked);
+        _tableView.KeyBindings.Add (Key.Space, Command.Accept);
     }
 
     protected override void Dispose (bool disposing)
@@ -869,13 +869,13 @@ public class TableEditor : Scenario
 
         var ok = new Button { Text = "Ok", IsDefault = true };
 
-        ok.Clicked += (s, e) =>
+        ok.Accept += (s, e) =>
                       {
                           okPressed = true;
                           Application.RequestStop ();
                       };
         var cancel = new Button { Text = "Cancel" };
-        cancel.Clicked += (s, e) => { Application.RequestStop (); };
+        cancel.Accept += (s, e) => { Application.RequestStop (); };
         var d = new Dialog { Title = title, Buttons = [ok, cancel] };
 
         var lbl = new Label { X = 0, Y = 1, Text = _tableView.Table.ColumnNames [e.Col] };
@@ -1066,13 +1066,13 @@ public class TableEditor : Scenario
         var accepted = false;
         var ok = new Button { Text = "Ok", IsDefault = true };
 
-        ok.Clicked += (s, e) =>
+        ok.Accept += (s, e) =>
                       {
                           accepted = true;
                           Application.RequestStop ();
                       };
         var cancel = new Button { Text = "Cancel" };
-        cancel.Clicked += (s, e) => { Application.RequestStop (); };
+        cancel.Accept += (s, e) => { Application.RequestStop (); };
         var d = new Dialog { Title = prompt, Buttons = [ok, cancel] };
 
         ColumnStyle style = _tableView.Style.GetOrCreateColumnStyle (col.Value);

+ 35 - 19
UICatalog/Scenarios/Text.cs

@@ -21,9 +21,11 @@ public class Text : Scenario
     public override void Setup ()
     {
         // TextField is a simple, single-line text input control
+        var label = new Label { Text = "_TextField:" };
+        Win.Add (label);
         var textField = new TextField
         {
-            X = 1,
+            X = Pos.Right (label) + 1,
             Y = 0,
             Width = Dim.Percent (50) - 1,
 
@@ -34,17 +36,14 @@ public class Text : Scenario
 
         var singleWordGenerator = new SingleWordSuggestionGenerator ();
         textField.Autocomplete.SuggestionGenerator = singleWordGenerator;
-
         textField.TextChanging += TextField_TextChanging;
-
-        void TextField_TextChanging (object sender, TextChangingEventArgs e)
+        void TextField_TextChanging (object sender, StateEventArgs<string> e)
         {
-            singleWordGenerator.AllSuggestions = Regex.Matches (e.NewText, "\\w+")
+            singleWordGenerator.AllSuggestions = Regex.Matches (e.NewValue, "\\w+")
                                                       .Select (s => s.Value)
                                                       .Distinct ()
                                                       .ToList ();
         }
-
         Win.Add (textField);
 
         var labelMirroringTextField = new Label
@@ -53,16 +52,18 @@ public class Text : Scenario
             Y = Pos.Top (textField),
             AutoSize = false,
             Width = Dim.Fill (1) - 1,
+            Height = 1,
             Text = textField.Text
         };
         Win.Add (labelMirroringTextField);
-
         textField.TextChanged += (s, prev) => { labelMirroringTextField.Text = textField.Text; };
 
         // TextView is a rich (as in functionality, not formatting) text editing control
+        label = new Label { Text = "T_extView:", Y = Pos.Bottom (label) + 1 };
+        Win.Add (label);
         var textView = new TextView
         {
-            X = 1, Y = Pos.Bottom (textField) + 1, Width = Dim.Percent (50) - 1, Height = Dim.Percent (30)
+            X = Pos.Right (label) + 1, Y = Pos.Bottom (textField) + 1, Width = Dim.Percent (50) - 1, Height = Dim.Percent (30)
         };
         textView.Text = "TextView with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!";
         textView.DrawContent += TextView_DrawContent;
@@ -101,7 +102,7 @@ public class Text : Scenario
         // single-line mode.
         var chxMultiline = new CheckBox
         {
-            X = Pos.Left (textView), Y = Pos.Bottom (textView), Checked = textView.Multiline, Text = "Multiline"
+            X = Pos.Left (textView), Y = Pos.Bottom (textView), Checked = textView.Multiline, Text = "_Multiline"
         };
         Win.Add (chxMultiline);
 
@@ -110,7 +111,7 @@ public class Text : Scenario
             X = Pos.Right (chxMultiline) + 2,
             Y = Pos.Top (chxMultiline),
             Checked = textView.WordWrap,
-            Text = "Word Wrap"
+            Text = "_Word Wrap"
         };
         chxWordWrap.Toggled += (s, e) => textView.WordWrap = (bool)e.NewValue;
         Win.Add (chxWordWrap);
@@ -123,7 +124,7 @@ public class Text : Scenario
             X = Pos.Right (chxWordWrap) + 2,
             Y = Pos.Top (chxWordWrap),
             Checked = textView.AllowsTab,
-            Text = "Capture Tabs"
+            Text = "_Capture Tabs"
         };
 
         chxMultiline.Toggled += (s, e) =>
@@ -161,10 +162,17 @@ public class Text : Scenario
                                   };
         Win.Add (chxCaptureTabs);
 
+        // Hex editor
+        label = new Label { Text = "_HexView:", Y = Pos.Bottom (chxMultiline) + 1 };
+        Win.Add (label);
+
         var hexEditor =
             new HexView (
                          new MemoryStream (Encoding.UTF8.GetBytes ("HexEditor Unicode that shouldn't 𝔹Aℝ𝔽!"))
-                        ) { X = 1, Y = Pos.Bottom (chxMultiline) + 1, Width = Dim.Percent (50) - 1, Height = Dim.Percent (30) };
+                        )
+            {
+                X = Pos.Right (label) + 1, Y = Pos.Bottom (chxMultiline) + 1, Width = Dim.Percent (50) - 1, Height = Dim.Percent (30)
+            };
         Win.Add (hexEditor);
 
         var labelMirroringHexEditor = new Label
@@ -186,7 +194,11 @@ public class Text : Scenario
                             };
         Win.Add (labelMirroringHexEditor);
 
-        var dateField = new DateField (DateTime.Now) { X = 1, Y = Pos.Bottom (hexEditor) + 1, Width = 20 };
+        // DateField
+        label = new Label { Text = "_DateField:", Y = Pos.Bottom (hexEditor) + 1 };
+        Win.Add (label);
+
+        var dateField = new DateField (DateTime.Now) { X = Pos.Right (label) + 1, Y = Pos.Bottom (hexEditor) + 1, Width = 20 };
         Win.Add (dateField);
 
         var labelMirroringDateField = new Label
@@ -202,10 +214,14 @@ public class Text : Scenario
 
         dateField.TextChanged += (s, prev) => { labelMirroringDateField.Text = dateField.Text; };
 
+        // TimeField
+        label = new Label { Text = "T_imeField:", Y = Pos.Top (dateField), X = Pos.Right (labelMirroringDateField) + 5 };
+        Win.Add (label);
+
         _timeField = new TimeField
         {
-            X = Pos.Right (labelMirroringDateField) + 5,
-            Y = Pos.Bottom (hexEditor) + 1,
+            X = Pos.Right (label) + 1,
+            Y = Pos.Top (dateField),
             Width = 20,
             IsShortFormat = false,
             Time = DateTime.Now.TimeOfDay
@@ -230,7 +246,7 @@ public class Text : Scenario
         {
             X = Pos.Left (dateField),
             Y = Pos.Bottom (dateField) + 1,
-            Text = "NetMaskedTextProvider [ 999 000 LLL >LLL |AAA aaa ]"
+            Text = "_NetMaskedTextProvider [ 999 000 LLL >LLL |AAA aaa ]:"
         };
         Win.Add (netProviderLabel);
 
@@ -260,7 +276,7 @@ public class Text : Scenario
         {
             X = Pos.Left (netProviderLabel),
             Y = Pos.Bottom (netProviderLabel) + 1,
-            Text = "TextRegexProvider [ ^([0-9]?[0-9]?[0-9]|1000)$ ]"
+            Text = "Text_RegexProvider [ ^([0-9]?[0-9]?[0-9]|1000)$ ]:"
         };
         Win.Add (regexProvider);
 
@@ -291,12 +307,12 @@ public class Text : Scenario
 
         var labelAppendAutocomplete = new Label
         {
-            Y = Pos.Y (regexProviderField) + 2, X = 1, Text = "Append Autocomplete:"
+            Y = Pos.Y (regexProviderField) + 2, X = 1, Text = "_Append Autocomplete:"
         };
 
         var appendAutocompleteTextField = new TextField
         {
-            X = Pos.Right (labelAppendAutocomplete), Y = Pos.Top (labelAppendAutocomplete), Width = Dim.Fill ()
+            X = Pos.Right (labelAppendAutocomplete) + 1, Y = Pos.Top (labelAppendAutocomplete), Width = Dim.Fill ()
         };
         appendAutocompleteTextField.Autocomplete = new AppendAutocomplete (appendAutocompleteTextField);
 

+ 2 - 2
UICatalog/Scenarios/TextAlignments.cs

@@ -74,12 +74,12 @@ public class TextAlignments : Scenario
         Win.Add (edit);
 
         var unicodeSample = new Button { X = Pos.Right (edit) + 1, Y = 0, Text = "Unicode Sample" };
-        unicodeSample.Clicked += (s, e) => { edit.Text = unicodeSampleText; };
+        unicodeSample.Accept += (s, e) => { edit.Text = unicodeSampleText; };
         Win.Add (unicodeSample);
 
         var update = new Button { X = Pos.Right (edit) + 1, Y = Pos.Bottom (edit) - 1, Text = "_Update" };
 
-        update.Clicked += (s, e) =>
+        update.Accept += (s, e) =>
                           {
                               foreach (TextAlignment alignment in alignments)
                               {

+ 8 - 8
UICatalog/Scenarios/Threading.cs

@@ -54,7 +54,7 @@ public class Threading : Scenario
                 };
 
         _btnActionCancel = new Button { X = 1, Y = 1, Text = "Cancelable Load Items" };
-        _btnActionCancel.Clicked += (s, e) => Application.Invoke (CallLoadItemsAsync);
+        _btnActionCancel.Accept += (s, e) => Application.Invoke (CallLoadItemsAsync);
 
         Win.Add (new Label { X = Pos.X (_btnActionCancel), Y = Pos.Y (_btnActionCancel) + 4, Text = "Data Items:" });
 
@@ -82,24 +82,24 @@ public class Threading : Scenario
         var text = new TextField { X = 1, Y = 3, Width = 100, Text = "Type anything after press the button" };
 
         var btnAction = new Button { X = 80, Y = 10, Text = "Load Data Action" };
-        btnAction.Clicked += (s, e) => _action.Invoke ();
+        btnAction.Accept += (s, e) => _action.Invoke ();
         var btnLambda = new Button { X = 80, Y = 12, Text = "Load Data Lambda" };
-        btnLambda.Clicked += (s, e) => _lambda.Invoke ();
+        btnLambda.Accept += (s, e) => _lambda.Invoke ();
         var btnHandler = new Button { X = 80, Y = 14, Text = "Load Data Handler" };
-        btnHandler.Clicked += (s, e) => _handler.Invoke (null, EventArgs.Empty);
+        btnHandler.Accept += (s, e) => _handler.Invoke (null, EventArgs.Empty);
         var btnSync = new Button { X = 80, Y = 16, Text = "Load Data Synchronous" };
-        btnSync.Clicked += (s, e) => _sync.Invoke ();
+        btnSync.Accept += (s, e) => _sync.Invoke ();
         var btnMethod = new Button { X = 80, Y = 18, Text = "Load Data Method" };
-        btnMethod.Clicked += async (s, e) => await MethodAsync ();
+        btnMethod.Accept += async (s, e) => await MethodAsync ();
         var btnClearData = new Button { X = 80, Y = 20, Text = "Clear Data" };
 
-        btnClearData.Clicked += (s, e) =>
+        btnClearData.Accept += (s, e) =>
                                 {
                                     _itemsList.Source = null;
                                     LogJob ("Cleaning Data");
                                 };
         var btnQuit = new Button { X = 80, Y = 22, Text = "Quit" };
-        btnQuit.Clicked += (s, e) => Application.RequestStop ();
+        btnQuit.Accept += (s, e) => Application.RequestStop ();
 
         Win.Add (
                  _itemsList,

+ 1 - 1
UICatalog/Scenarios/TimeAndDate.cs

@@ -124,7 +124,7 @@ public class TimeAndDate : Scenario
             X = Pos.Center (), Y = Pos.Bottom (Win) - 5, Text = "Swap Long/Short & Read/Read Only"
         };
 
-        swapButton.Clicked += (s, e) =>
+        swapButton.Accept += (s, e) =>
                               {
                                   longTime.ReadOnly = !longTime.ReadOnly;
                                   shortTime.ReadOnly = !shortTime.ReadOnly;

Some files were not shown because too many files changed in this diff