Selaa lähdekoodia

Merge branch 'v2_3777-hexedit' of tig:tig/Terminal.Gui into v2_3777-hexedit

Tig 9 kuukautta sitten
vanhempi
commit
9d83e23000
100 muutettua tiedostoa jossa 2298 lisäystä ja 1884 poistoa
  1. 7 1
      .github/workflows/dotnet-core.yml
  2. 3 3
      .github/workflows/publish.yml
  3. 1 0
      .gitignore
  4. 1 1
      NativeAot/NativeAot.csproj
  5. 9 0
      NativeAot/PackTerminalGui.ps1
  6. 11 0
      NativeAot/PackTerminalGui.sh
  7. 9 0
      SelfContained/PackTerminalGui.ps1
  8. 11 0
      SelfContained/PackTerminalGui.sh
  9. 1 1
      SelfContained/SelfContained.csproj
  10. 3 3
      Terminal.Gui/Application/Application.Initialization.cs
  11. 75 191
      Terminal.Gui/Application/Application.Keyboard.cs
  12. 40 29
      Terminal.Gui/Application/Application.Mouse.cs
  13. 79 0
      Terminal.Gui/Application/Application.Navigation.cs
  14. 42 7
      Terminal.Gui/Application/Application.Run.cs
  15. 2 2
      Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs
  16. 211 44
      Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
  17. 3 3
      Terminal.Gui/ConsoleDrivers/NetDriver.cs
  18. 5 5
      Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
  19. 152 6
      Terminal.Gui/Drawing/Cell.cs
  20. 8 8
      Terminal.Gui/Drawing/CellEventArgs.cs
  21. 1 1
      Terminal.Gui/Drawing/LineCanvas.cs
  22. 1 1
      Terminal.Gui/Drawing/StraightLine.cs
  23. 101 0
      Terminal.Gui/Input/MouseEventArgs.cs
  24. 0 32
      Terminal.Gui/Input/MouseEventEventArgs.cs
  25. 2 49
      Terminal.Gui/Input/MouseFlags.cs
  26. 0 173
      Terminal.Gui/Input/ShortcutHelper.cs
  27. 9 0
      Terminal.Gui/Resources/Strings.Designer.cs
  28. 15 12
      Terminal.Gui/Resources/Strings.fr-FR.resx
  29. 58 55
      Terminal.Gui/Resources/Strings.ja-JP.resx
  30. 16 13
      Terminal.Gui/Resources/Strings.pt-PT.resx
  31. 264 261
      Terminal.Gui/Resources/Strings.resx
  32. 9 6
      Terminal.Gui/Resources/Strings.zh-Hans.resx
  33. 1 1
      Terminal.Gui/Terminal.Gui.csproj
  34. 1 1
      Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs
  35. 1 1
      Terminal.Gui/Text/Autocomplete/AutocompleteBase.cs
  36. 2 2
      Terminal.Gui/Text/Autocomplete/AutocompleteContext.cs
  37. 1 1
      Terminal.Gui/Text/Autocomplete/IAutocomplete.cs
  38. 1 1
      Terminal.Gui/Text/Autocomplete/PopupAutocomplete.PopUp.cs
  39. 2 2
      Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs
  40. 2 7
      Terminal.Gui/View/Adornment/Border.cs
  41. 1 1
      Terminal.Gui/View/Adornment/Padding.cs
  42. 1 1
      Terminal.Gui/View/Adornment/ShadowView.cs
  43. 10 1
      Terminal.Gui/View/CancelEventArgs.cs
  44. 1 1
      Terminal.Gui/View/Navigation/AdvanceFocusEventArgs.cs
  45. 2 4
      Terminal.Gui/View/Orientation/OrientationHelper.cs
  46. 141 182
      Terminal.Gui/View/View.Keyboard.cs
  47. 0 1
      Terminal.Gui/View/View.Layout.cs
  48. 96 85
      Terminal.Gui/View/View.Mouse.cs
  49. 2 2
      Terminal.Gui/Views/AutocompleteFilepathContext.cs
  50. 5 5
      Terminal.Gui/Views/Bar.cs
  51. 1 1
      Terminal.Gui/Views/Button.cs
  52. 2 3
      Terminal.Gui/Views/ColorBar.cs
  53. 2 2
      Terminal.Gui/Views/ColorPicker.16.cs
  54. 123 0
      Terminal.Gui/Views/ColorPicker.Prompt.cs
  55. 0 0
      Terminal.Gui/Views/ColorPicker.Style.cs
  56. 1 1
      Terminal.Gui/Views/ColorPicker.cs
  57. 6 5
      Terminal.Gui/Views/ComboBox.cs
  58. 9 6
      Terminal.Gui/Views/DateField.cs
  59. 13 13
      Terminal.Gui/Views/FileDialog.cs
  60. 1 1
      Terminal.Gui/Views/FrameView.cs
  61. 29 35
      Terminal.Gui/Views/HexView.cs
  62. 3 3
      Terminal.Gui/Views/HistoryTextItemEventArgs.cs
  63. 1 1
      Terminal.Gui/Views/Label.cs
  64. 56 4
      Terminal.Gui/Views/ListView.cs
  65. 9 15
      Terminal.Gui/Views/Menu/Menu.cs
  66. 4 4
      Terminal.Gui/Views/Menu/MenuBar.cs
  67. 5 5
      Terminal.Gui/Views/RadioGroup.cs
  68. 8 8
      Terminal.Gui/Views/ScrollBarView.cs
  69. 8 8
      Terminal.Gui/Views/ScrollView.cs
  70. 2 4
      Terminal.Gui/Views/Slider.cs
  71. 3 3
      Terminal.Gui/Views/TabMouseEventArgs.cs
  72. 6 14
      Terminal.Gui/Views/TabView.cs
  73. 3 3
      Terminal.Gui/Views/TableView/CheckBoxTableSourceWrapper.cs
  74. 14 12
      Terminal.Gui/Views/TableView/TableView.cs
  75. 2 2
      Terminal.Gui/Views/TableView/TreeTableSource.cs
  76. 52 70
      Terminal.Gui/Views/TextField.cs
  77. 2 2
      Terminal.Gui/Views/TextValidateField.cs
  78. 270 254
      Terminal.Gui/Views/TextView.cs
  79. 3 3
      Terminal.Gui/Views/TileView.cs
  80. 9 6
      Terminal.Gui/Views/TimeField.cs
  81. 1 1
      Terminal.Gui/Views/Toplevel.cs
  82. 9 9
      Terminal.Gui/Views/TreeView/Branch.cs
  83. 4 4
      Terminal.Gui/Views/TreeView/DrawTreeViewLineEventArgs.cs
  84. 8 15
      Terminal.Gui/Views/TreeView/TreeView.cs
  85. 2 2
      Terminal.Gui/Views/Wizard/Wizard.cs
  86. 4 4
      UICatalog/Scenarios/ASCIICustomButton.cs
  87. 1 1
      UICatalog/Scenarios/AdornmentsEditor.cs
  88. 1 1
      UICatalog/Scenarios/ArrangementEditor.cs
  89. 8 8
      UICatalog/Scenarios/Bars.cs
  90. 9 11
      UICatalog/Scenarios/CharacterMap.cs
  91. 5 5
      UICatalog/Scenarios/ContentScrolling.cs
  92. 3 3
      UICatalog/Scenarios/ContextMenus.cs
  93. 9 1
      UICatalog/Scenarios/Editor.cs
  94. 92 70
      UICatalog/Scenarios/Keys.cs
  95. 35 17
      UICatalog/Scenarios/LineDrawing.cs
  96. 1 1
      UICatalog/Scenarios/ListColumns.cs
  97. 3 3
      UICatalog/Scenarios/Mouse.cs
  98. 1 1
      UICatalog/Scenarios/ProgressBarStyles.cs
  99. 5 5
      UICatalog/Scenarios/Snake.cs
  100. 31 28
      UICatalog/Scenarios/SyntaxHighlighting.cs

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

@@ -90,7 +90,13 @@ jobs:
         dotnet-version: 8.x
         dotnet-version: 8.x
         dotnet-quality: 'ga'
         dotnet-quality: 'ga'
 
 
-    - name: Build Release
+    - name: Build Release Terminal.Gui
+      run: dotnet build Terminal.Gui/Terminal.Gui.csproj --configuration Release
+
+    - name: Pack Release Terminal.Gui
+      run: dotnet pack Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ./local_packages
+
+    - name: Build Release Solution
       run: dotnet build --configuration Release
       run: dotnet build --configuration Release
 
 
 
 

+ 3 - 3
.github/workflows/publish.yml

@@ -43,11 +43,11 @@ jobs:
     - name: Build Release
     - name: Build Release
       run: |
       run: |
         dotnet-gitversion /updateprojectfiles
         dotnet-gitversion /updateprojectfiles
-        dotnet build --no-incremental --nologo --force --configuration Release
-        dotnet test --configuration Release
+        dotnet build Terminal.Gui/Terminal.Gui.csproj --no-incremental --nologo --force --configuration Release
+        dotnet test Terminal.Gui/Terminal.Gui.csproj --configuration Release
 
 
     - name: Pack
     - name: Pack
-      run: dotnet pack -c Release --include-symbols -p:Version='${{ steps.gitversion.outputs.SemVer }}' 
+      run: dotnet pack Terminal.Gui/Terminal.Gui.csproj -c Release --include-symbols -p:Version='${{ steps.gitversion.outputs.SemVer }}' 
 
 
     # - name: Test to generate Code Coverage Report
     # - name: Test to generate Code Coverage Report
     #   run: |
     #   run: |

+ 1 - 0
.gitignore

@@ -61,3 +61,4 @@ demo.*
 *.tui/
 *.tui/
 
 
 *.dotCover
 *.dotCover
+/local_packages/

+ 1 - 1
NativeAot/NativeAot.csproj

@@ -15,7 +15,7 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
   <ItemGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
-    <PackageReference Include="Terminal.Gui" Version="[2.0.0-v2-develop.2189,3)" />
+    <PackageReference Include="Terminal.Gui" Version="2.0.0" />
     <TrimmerRootAssembly Include="Terminal.Gui" />
     <TrimmerRootAssembly Include="Terminal.Gui" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 9 - 0
NativeAot/PackTerminalGui.ps1

@@ -0,0 +1,9 @@
+# Step 1: Build and pack Terminal.Gui
+dotnet build ../Terminal.Gui/Terminal.Gui.csproj --configuration Release
+dotnet pack ../Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ../local_packages
+
+# Step 2: Restore NativeAot with the new package
+dotnet restore ./NativeAot.csproj --source ./local_packages
+
+# Step 3: Build NativeAot
+dotnet build ./NativeAot.csproj --configuration Release

+ 11 - 0
NativeAot/PackTerminalGui.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Step 1: Build and pack Terminal.Gui
+dotnet build ../Terminal.Gui/Terminal.Gui.csproj --configuration Release
+dotnet pack ../Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ../local_packages
+
+# Step 2: Restore NativeAot with the new package
+dotnet restore ./NativeAot.csproj --source ./local_packages
+
+# Step 3: Build NativeAot
+dotnet build ./NativeAot.csproj --configuration Release

+ 9 - 0
SelfContained/PackTerminalGui.ps1

@@ -0,0 +1,9 @@
+# Step 1: Build and pack Terminal.Gui
+dotnet build ../Terminal.Gui/Terminal.Gui.csproj --configuration Release
+dotnet pack ../Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ../local_packages
+
+# Step 2: Restore SelfContained with the new package
+dotnet restore ./SelfContained.csproj --source ./local_packages
+
+# Step 3: Build SelfContained
+dotnet build ./SelfContained.csproj --configuration Release

+ 11 - 0
SelfContained/PackTerminalGui.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Step 1: Build and pack Terminal.Gui
+dotnet build ../Terminal.Gui/Terminal.Gui.csproj --configuration Release
+dotnet pack ../Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ../local_packages
+
+# Step 2: Restore SelfContained with the new package
+dotnet restore ./SelfContained.csproj --source ./local_packages
+
+# Step 3: Build SelfContained
+dotnet build ./SelfContained.csproj --configuration Release

+ 1 - 1
SelfContained/SelfContained.csproj

@@ -18,7 +18,7 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
   <ItemGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
-    <PackageReference Include="Terminal.Gui" Version="[2.0.0-pre.1788,3)" />
+    <PackageReference Include="Terminal.Gui" Version="2.0.0" />
     <TrimmerRootAssembly Include="Terminal.Gui" />
     <TrimmerRootAssembly Include="Terminal.Gui" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 3 - 3
Terminal.Gui/Application/Application.Initialization.cs

@@ -178,9 +178,9 @@ public static partial class Application // Initialization (Init/Shutdown)
     }
     }
 
 
     private static void Driver_SizeChanged (object? sender, SizeChangedEventArgs e) { OnSizeChanging (e); }
     private static void Driver_SizeChanged (object? sender, SizeChangedEventArgs e) { OnSizeChanging (e); }
-    private static void Driver_KeyDown (object? sender, Key e) { OnKeyDown (e); }
-    private static void Driver_KeyUp (object? sender, Key e) { OnKeyUp (e); }
-    private static void Driver_MouseEvent (object? sender, MouseEvent e) { OnMouseEvent (e); }
+    private static void Driver_KeyDown (object? sender, Key e) { RaiseKeyDownEvent (e); }
+    private static void Driver_KeyUp (object? sender, Key e) { RaiseKeyUpEvent (e); }
+    private static void Driver_MouseEvent (object? sender, MouseEventArgs e) { RaiseMouseEvent (e); }
 
 
     /// <summary>Gets of list of <see cref="ConsoleDriver"/> types that are available.</summary>
     /// <summary>Gets of list of <see cref="ConsoleDriver"/> types that are available.</summary>
     /// <returns></returns>
     /// <returns></returns>

+ 75 - 191
Terminal.Gui/Application/Application.Keyboard.cs

@@ -3,94 +3,19 @@ namespace Terminal.Gui;
 
 
 public static partial class Application // Keyboard handling
 public static partial class Application // Keyboard handling
 {
 {
-    private static Key _nextTabGroupKey = Key.F6; // Resources/config.json overrrides
-    private static Key _nextTabKey = Key.Tab; // Resources/config.json overrrides
-    private static Key _prevTabGroupKey = Key.F6.WithShift; // Resources/config.json overrrides
-    private static Key _prevTabKey = Key.Tab.WithShift; // Resources/config.json overrrides
-    private static Key _quitKey = Key.Esc; // Resources/config.json overrrides
-    private static Key _arrangeKey = Key.F5.WithCtrl; // Resources/config.json overrrides
-
-    static Application () { AddApplicationKeyBindings (); }
-
-    /// <summary>Gets the key bindings for this view.</summary>
-    public static KeyBindings KeyBindings { get; internal set; } = new ();
-
-    /// <summary>
-    ///     Event fired when the user presses a key. Fired by <see cref="OnKeyDown"/>.
-    ///     <para>
-    ///         Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
-    ///         additional processing.
-    ///     </para>
-    /// </summary>
-    /// <remarks>
-    ///     All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
-    ///     <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
-    ///     <para>Fired after <see cref="KeyDown"/> and before <see cref="KeyUp"/>.</para>
-    /// </remarks>
-    public static event EventHandler<Key>? KeyDown;
-
     /// <summary>
     /// <summary>
-    ///     Event fired when the user releases a key. Fired by <see cref="OnKeyUp"/>.
-    ///     <para>
-    ///         Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
-    ///         additional processing.
-    ///     </para>
-    /// </summary>
-    /// <remarks>
-    ///     All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
-    ///     <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
-    ///     <para>Fired after <see cref="KeyDown"/>.</para>
-    /// </remarks>
-    public static event EventHandler<Key>? KeyUp;
-
-    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key NextTabGroupKey
-    {
-        get => _nextTabGroupKey;
-        set
-        {
-            if (_nextTabGroupKey != value)
-            {
-                ReplaceKey (_nextTabGroupKey, value);
-                _nextTabGroupKey = value;
-            }
-        }
-    }
-
-    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key NextTabKey
-    {
-        get => _nextTabKey;
-        set
-        {
-            if (_nextTabKey != value)
-            {
-                ReplaceKey (_nextTabKey, value);
-                _nextTabKey = value;
-            }
-        }
-    }
-
-    /// <summary>
-    ///     Called by the <see cref="ConsoleDriver"/> when the user presses a key. Fires the <see cref="KeyDown"/> event
-    ///     then calls <see cref="View.NewKeyDownEvent"/> on all top level views. Called after <see cref="OnKeyDown"/> and
-    ///     before <see cref="OnKeyUp"/>.
+    ///     Called when the user presses a key (by the <see cref="ConsoleDriver"/>). Raises the cancelable
+    ///     <see cref="KeyDown"/> event, then calls <see cref="View.NewKeyDownEvent"/> on all top level views, and finally
+    ///     if the key was not handled, invokes any Application-scoped <see cref="KeyBindings"/>.
     /// </summary>
     /// </summary>
     /// <remarks>Can be used to simulate key press events.</remarks>
     /// <remarks>Can be used to simulate key press events.</remarks>
-    /// <param name="keyEvent"></param>
+    /// <param name="key"></param>
     /// <returns><see langword="true"/> if the key was handled.</returns>
     /// <returns><see langword="true"/> if the key was handled.</returns>
-    public static bool OnKeyDown (Key keyEvent)
+    public static bool RaiseKeyDownEvent (Key key)
     {
     {
-        //if (!IsInitialized)
-        //{
-        //    return true;
-        //}
+        KeyDown?.Invoke (null, key);
 
 
-        KeyDown?.Invoke (null, keyEvent);
-
-        if (keyEvent.Handled)
+        if (key.Handled)
         {
         {
             return true;
             return true;
         }
         }
@@ -99,7 +24,7 @@ public static partial class Application // Keyboard handling
         {
         {
             foreach (Toplevel topLevel in TopLevels.ToList ())
             foreach (Toplevel topLevel in TopLevels.ToList ())
             {
             {
-                if (topLevel.NewKeyDownEvent (keyEvent))
+                if (topLevel.NewKeyDownEvent (key))
                 {
                 {
                     return true;
                     return true;
                 }
                 }
@@ -112,7 +37,7 @@ public static partial class Application // Keyboard handling
         }
         }
         else
         else
         {
         {
-            if (Top.NewKeyDownEvent (keyEvent))
+            if (Top.NewKeyDownEvent (key))
             {
             {
                 return true;
                 return true;
             }
             }
@@ -120,7 +45,7 @@ public static partial class Application // Keyboard handling
 
 
         // Invoke any Application-scoped KeyBindings.
         // Invoke any Application-scoped KeyBindings.
         // The first view that handles the key will stop the loop.
         // The first view that handles the key will stop the loop.
-        foreach (KeyValuePair<Key, KeyBinding> binding in KeyBindings.Bindings.Where (b => b.Key == keyEvent.KeyCode))
+        foreach (KeyValuePair<Key, KeyBinding> binding in KeyBindings.Bindings.Where (b => b.Key == key.KeyCode))
         {
         {
             if (binding.Value.BoundView is { })
             if (binding.Value.BoundView is { })
             {
             {
@@ -133,7 +58,7 @@ public static partial class Application // Keyboard handling
             }
             }
             else
             else
             {
             {
-                if (!KeyBindings.TryGet (keyEvent, KeyBindingScope.Application, out KeyBinding appBinding))
+                if (!KeyBindings.TryGet (key, KeyBindingScope.Application, out KeyBinding appBinding))
                 {
                 {
                     continue;
                     continue;
                 }
                 }
@@ -142,7 +67,7 @@ public static partial class Application // Keyboard handling
 
 
                 foreach (Command command in appBinding.Commands)
                 foreach (Command command in appBinding.Commands)
                 {
                 {
-                    toReturn = InvokeCommand (command, keyEvent, appBinding);
+                    toReturn = InvokeCommand (command, key, appBinding);
                 }
                 }
 
 
                 return toReturn ?? true;
                 return toReturn ?? true;
@@ -150,59 +75,66 @@ public static partial class Application // Keyboard handling
         }
         }
 
 
         return false;
         return false;
-    }
 
 
-    /// <summary>
-    ///     INTENRAL method to invoke one of the commands in <see cref="CommandImplementations"/>
-    /// </summary>
-    /// <param name="command"></param>
-    /// <param name="keyEvent"></param>
-    /// <param name="appBinding"></param>
-    /// <returns></returns>
-    /// <exception cref="NotSupportedException"></exception>
-    private static bool? InvokeCommand (Command command, Key keyEvent, KeyBinding appBinding)
-    {
-        if (!CommandImplementations!.ContainsKey (command))
+        static bool? InvokeCommand (Command command, Key key, KeyBinding appBinding)
         {
         {
-            throw new NotSupportedException (
-                                             @$"A KeyBinding was set up for the command {command} ({keyEvent}) but that command is not supported by Application."
-                                            );
-        }
+            if (!CommandImplementations!.ContainsKey (command))
+            {
+                throw new NotSupportedException (
+                                                 @$"A KeyBinding was set up for the command {command} ({key}) but that command is not supported by Application."
+                                                );
+            }
 
 
-        if (CommandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
-        {
-            var context = new CommandContext (command, keyEvent, appBinding); // Create the context here
+            if (CommandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
+            {
+                var context = new CommandContext (command, key, appBinding); // Create the context here
 
 
-            return implementation (context);
-        }
+                return implementation (context);
+            }
 
 
-        return false;
+            return false;
+        }
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Called by the <see cref="ConsoleDriver"/> when the user releases a key. Fires the <see cref="KeyUp"/> event
-    ///     then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="OnKeyDown"/>.
+    ///     Raised when the user presses a key.
+    ///     <para>
+    ///         Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
+    ///         additional processing.
+    ///     </para>
     /// </summary>
     /// </summary>
-    /// <remarks>Can be used to simulate key press events.</remarks>
-    /// <param name="a"></param>
+    /// <remarks>
+    ///     All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
+    ///     <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
+    ///     <para>Fired after <see cref="KeyDown"/> and before <see cref="KeyUp"/>.</para>
+    /// </remarks>
+    public static event EventHandler<Key>? KeyDown;
+
+    /// <summary>
+    ///     Called when the user releases a key (by the <see cref="ConsoleDriver"/>). Raises the cancelable <see cref="KeyUp"/>
+    ///     event
+    ///     then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="RaiseKeyDownEvent"/>.
+    /// </summary>
+    /// <remarks>Can be used to simulate key release events.</remarks>
+    /// <param name="key"></param>
     /// <returns><see langword="true"/> if the key was handled.</returns>
     /// <returns><see langword="true"/> if the key was handled.</returns>
-    public static bool OnKeyUp (Key a)
+    public static bool RaiseKeyUpEvent (Key key)
     {
     {
         if (!IsInitialized)
         if (!IsInitialized)
         {
         {
             return true;
             return true;
         }
         }
 
 
-        KeyUp?.Invoke (null, a);
+        KeyUp?.Invoke (null, key);
 
 
-        if (a.Handled)
+        if (key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
         foreach (Toplevel topLevel in TopLevels.ToList ())
         foreach (Toplevel topLevel in TopLevels.ToList ())
         {
         {
-            if (topLevel.NewKeyUpEvent (a))
+            if (topLevel.NewKeyUpEvent (key))
             {
             {
                 return true;
                 return true;
             }
             }
@@ -216,65 +148,12 @@ public static partial class Application // Keyboard handling
         return false;
         return false;
     }
     }
 
 
-    /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key PrevTabGroupKey
-    {
-        get => _prevTabGroupKey;
-        set
-        {
-            if (_prevTabGroupKey != value)
-            {
-                ReplaceKey (_prevTabGroupKey, value);
-                _prevTabGroupKey = value;
-            }
-        }
-    }
-
-    /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key PrevTabKey
-    {
-        get => _prevTabKey;
-        set
-        {
-            if (_prevTabKey != value)
-            {
-                ReplaceKey (_prevTabKey, value);
-                _prevTabKey = value;
-            }
-        }
-    }
+    #region Application-scoped KeyBindings
 
 
-    /// <summary>Gets or sets the key to quit the application.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key QuitKey
-    {
-        get => _quitKey;
-        set
-        {
-            if (_quitKey != value)
-            {
-                ReplaceKey (_quitKey, value);
-                _quitKey = value;
-            }
-        }
-    }
+    static Application () { AddApplicationKeyBindings (); }
 
 
-    /// <summary>Gets or sets the key to activate arranging views using the keyboard.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key ArrangeKey
-    {
-        get => _arrangeKey;
-        set
-        {
-            if (_arrangeKey != value)
-            {
-                ReplaceKey (_arrangeKey, value);
-                _arrangeKey = value;
-            }
-        }
-    }
+    /// <summary>Gets the Application-scoped key bindings.</summary>
+    public static KeyBindings KeyBindings { get; internal set; } = new ();
 
 
     internal static void AddApplicationKeyBindings ()
     internal static void AddApplicationKeyBindings ()
     {
     {
@@ -286,6 +165,7 @@ public static partial class Application // Keyboard handling
                     static () =>
                     static () =>
                     {
                     {
                         RequestStop ();
                         RequestStop ();
+
                         return true;
                         return true;
                     }
                     }
                    );
                    );
@@ -348,7 +228,7 @@ public static partial class Application // Keyboard handling
 
 
         KeyBindings.Clear ();
         KeyBindings.Clear ();
 
 
-        // Resources/config.json overrrides
+        // Resources/config.json overrides
         NextTabKey = Key.Tab;
         NextTabKey = Key.Tab;
         PrevTabKey = Key.Tab.WithShift;
         PrevTabKey = Key.Tab.WithShift;
         NextTabGroupKey = Key.F6;
         NextTabGroupKey = Key.F6;
@@ -397,6 +277,26 @@ public static partial class Application // Keyboard handling
                           .ToList ();
                           .ToList ();
     }
     }
 
 
+    private static void ReplaceKey (Key oldKey, Key newKey)
+    {
+        if (KeyBindings.Bindings.Count == 0)
+        {
+            return;
+        }
+
+        if (newKey == Key.Empty)
+        {
+            KeyBindings.Remove (oldKey);
+        }
+        else
+        {
+            KeyBindings.ReplaceKey (oldKey, newKey);
+        }
+    }
+
+
+    #endregion Application-scoped KeyBindings
+
     /// <summary>
     /// <summary>
     ///     <para>
     ///     <para>
     ///         Sets the function that will be invoked for a <see cref="Command"/>.
     ///         Sets the function that will be invoked for a <see cref="Command"/>.
@@ -420,20 +320,4 @@ public static partial class Application // Keyboard handling
     /// </summary>
     /// </summary>
     private static Dictionary<Command, View.CommandImplementation>? CommandImplementations { get; set; }
     private static Dictionary<Command, View.CommandImplementation>? CommandImplementations { get; set; }
 
 
-    private static void ReplaceKey (Key oldKey, Key newKey)
-    {
-        if (KeyBindings.Bindings.Count == 0)
-        {
-            return;
-        }
-
-        if (newKey == Key.Empty)
-        {
-            KeyBindings.Remove (oldKey);
-        }
-        else
-        {
-            KeyBindings.ReplaceKey (oldKey, newKey);
-        }
-    }
 }
 }

+ 40 - 29
Terminal.Gui/Application/Application.Mouse.cs

@@ -1,6 +1,5 @@
 #nullable enable
 #nullable enable
 using System.ComponentModel;
 using System.ComponentModel;
-using System.Diagnostics;
 
 
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
@@ -45,12 +44,12 @@ public static partial class Application // Mouse handling
     /// <param name="view">View that will receive all mouse events until <see cref="UngrabMouse"/> is invoked.</param>
     /// <param name="view">View that will receive all mouse events until <see cref="UngrabMouse"/> is invoked.</param>
     public static void GrabMouse (View? view)
     public static void GrabMouse (View? view)
     {
     {
-        if (view is null || OnGrabbingMouse (view))
+        if (view is null || RaiseGrabbingMouseEvent (view))
         {
         {
             return;
             return;
         }
         }
 
 
-        OnGrabbedMouse (view);
+        RaiseGrabbedMouseEvent (view);
         MouseGrabView = view;
         MouseGrabView = view;
     }
     }
 
 
@@ -66,16 +65,16 @@ public static partial class Application // Mouse handling
         ObjectDisposedException.ThrowIf (MouseGrabView.WasDisposed, MouseGrabView);
         ObjectDisposedException.ThrowIf (MouseGrabView.WasDisposed, MouseGrabView);
 #endif
 #endif
 
 
-        if (!OnUnGrabbingMouse (MouseGrabView))
+        if (!RaiseUnGrabbingMouseEvent (MouseGrabView))
         {
         {
             View view = MouseGrabView;
             View view = MouseGrabView;
             MouseGrabView = null;
             MouseGrabView = null;
-            OnUnGrabbedMouse (view);
+            RaiseUnGrabbedMouseEvent (view);
         }
         }
     }
     }
 
 
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
-    private static bool OnGrabbingMouse (View? view)
+    private static bool RaiseGrabbingMouseEvent (View? view)
     {
     {
         if (view is null)
         if (view is null)
         {
         {
@@ -89,7 +88,7 @@ public static partial class Application // Mouse handling
     }
     }
 
 
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
-    private static bool OnUnGrabbingMouse (View? view)
+    private static bool RaiseUnGrabbingMouseEvent (View? view)
     {
     {
         if (view is null)
         if (view is null)
         {
         {
@@ -103,7 +102,7 @@ public static partial class Application // Mouse handling
     }
     }
 
 
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
-    private static void OnGrabbedMouse (View? view)
+    private static void RaiseGrabbedMouseEvent (View? view)
     {
     {
         if (view is null)
         if (view is null)
         {
         {
@@ -114,7 +113,7 @@ public static partial class Application // Mouse handling
     }
     }
 
 
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
-    private static void OnUnGrabbedMouse (View? view)
+    private static void RaiseUnGrabbedMouseEvent (View? view)
     {
     {
         if (view is null)
         if (view is null)
         {
         {
@@ -124,20 +123,14 @@ public static partial class Application // Mouse handling
         UnGrabbedMouse?.Invoke (view, new (view));
         UnGrabbedMouse?.Invoke (view, new (view));
     }
     }
 
 
-    /// <summary>Event fired when a mouse move or click occurs. Coordinates are screen relative.</summary>
-    /// <remarks>
-    ///     <para>
-    ///         Use this event to receive mouse events in screen coordinates. Use <see cref="MouseEvent"/> to
-    ///         receive mouse events relative to a <see cref="View.Viewport"/>.
-    ///     </para>
-    ///     <para>The <see cref="MouseEvent.View"/> will contain the <see cref="View"/> that contains the mouse coordinates.</para>
-    /// </remarks>
-    public static event EventHandler<MouseEvent>? MouseEvent;
 
 
-    /// <summary>Called when a mouse event is raised by the driver.</summary>
+    /// <summary>
+    ///     INTERNAL API: Called when a mouse event is raised by the driver. Determines the view under the mouse and
+    ///     calls the appropriate View mouse event handlers.
+    /// </summary>
     /// <remarks>This method can be used to simulate a mouse event, e.g. in unit tests.</remarks>
     /// <remarks>This method can be used to simulate a mouse event, e.g. in unit tests.</remarks>
     /// <param name="mouseEvent">The mouse event with coordinates relative to the screen.</param>
     /// <param name="mouseEvent">The mouse event with coordinates relative to the screen.</param>
-    internal static void OnMouseEvent (MouseEvent mouseEvent)
+    internal static void RaiseMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         _lastMousePosition = mouseEvent.ScreenPosition;
         _lastMousePosition = mouseEvent.ScreenPosition;
 
 
@@ -177,9 +170,6 @@ public static partial class Application // Mouse handling
             return;
             return;
         }
         }
 
 
-        // We can combine this into the switch expression to reduce cognitive complexity even more and likely
-        // avoid one or two of these checks in the process, as well.
-
         WantContinuousButtonPressedView = deepestViewUnderMouse switch
         WantContinuousButtonPressedView = deepestViewUnderMouse switch
         {
         {
             { WantContinuousButtonPressed: true } => deepestViewUnderMouse,
             { WantContinuousButtonPressed: true } => deepestViewUnderMouse,
@@ -194,7 +184,7 @@ public static partial class Application // Mouse handling
         }
         }
 
 
         // Create a view-relative mouse event to send to the view that is under the mouse.
         // Create a view-relative mouse event to send to the view that is under the mouse.
-        MouseEvent? viewMouseEvent;
+        MouseEventArgs? viewMouseEvent;
 
 
         if (deepestViewUnderMouse is Adornment adornment)
         if (deepestViewUnderMouse is Adornment adornment)
         {
         {
@@ -208,7 +198,7 @@ public static partial class Application // Mouse handling
                 View = deepestViewUnderMouse
                 View = deepestViewUnderMouse
             };
             };
         }
         }
-        else if (deepestViewUnderMouse.ViewportToScreen (Rectangle.Empty with { Size = deepestViewUnderMouse.Viewport.Size }).Contains (mouseEvent.Position))
+        else if (deepestViewUnderMouse.ViewportToScreen (Rectangle.Empty with { Size = deepestViewUnderMouse.Viewport.Size }).Contains (mouseEvent.ScreenPosition))
         {
         {
             Point viewportLocation = deepestViewUnderMouse.ScreenToViewport (mouseEvent.ScreenPosition);
             Point viewportLocation = deepestViewUnderMouse.ScreenToViewport (mouseEvent.ScreenPosition);
 
 
@@ -224,7 +214,7 @@ public static partial class Application // Mouse handling
         {
         {
             // The mouse was outside any View's Viewport.
             // The mouse was outside any View's Viewport.
 
 
-           // Debug.Fail ("This should never happen. If it does please file an Issue!!");
+            // Debug.Fail ("This should never happen. If it does please file an Issue!!");
 
 
             return;
             return;
         }
         }
@@ -261,7 +251,29 @@ public static partial class Application // Mouse handling
         }
         }
     }
     }
 
 
-    internal static bool HandleMouseGrab (View? deepestViewUnderMouse, MouseEvent mouseEvent)
+
+#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
+    /// <summary>
+    /// Raised when a mouse event occurs. Can be cancelled by setting <see cref="MouseEventArgs.Handled"/> to <see langword="true"/>.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         <see cref="MouseEventArgs.ScreenPosition"/> coordinates are screen-relative.
+    ///     </para>
+    ///     <para>
+    ///         <see cref="MouseEventArgs.View"/> will be the deepest view under the under the mouse.
+    ///     </para>
+    ///     <para>
+    ///         <see cref="MouseEventArgs.Position"/> coordinates are view-relative. Only valid if <see cref="MouseEventArgs.View"/> is set.
+    ///     </para>
+    ///     <para>
+    ///         Use this evento to handle mouse events at the application level, before View-specific handling.
+    ///     </para>
+    /// </remarks>
+    public static event EventHandler<MouseEventArgs>? MouseEvent;
+#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
+
+    internal static bool HandleMouseGrab (View? deepestViewUnderMouse, MouseEventArgs mouseEvent)
     {
     {
         if (MouseGrabView is { })
         if (MouseGrabView is { })
         {
         {
@@ -276,7 +288,7 @@ public static partial class Application // Mouse handling
             // The coordinates are relative to the Bounds of the view that grabbed the mouse.
             // The coordinates are relative to the Bounds of the view that grabbed the mouse.
             Point frameLoc = MouseGrabView.ScreenToViewport (mouseEvent.ScreenPosition);
             Point frameLoc = MouseGrabView.ScreenToViewport (mouseEvent.ScreenPosition);
 
 
-            var viewRelativeMouseEvent = new MouseEvent
+            var viewRelativeMouseEvent = new MouseEventArgs
             {
             {
                 Position = frameLoc,
                 Position = frameLoc,
                 Flags = mouseEvent.Flags,
                 Flags = mouseEvent.Flags,
@@ -303,7 +315,6 @@ public static partial class Application // Mouse handling
 
 
     internal static readonly List<View?> _cachedViewsUnderMouse = new ();
     internal static readonly List<View?> _cachedViewsUnderMouse = new ();
 
 
-    // TODO: Refactor MouseEnter/LeaveEvents to not take MouseEvent param.
     /// <summary>
     /// <summary>
     ///     INTERNAL: Raises the MouseEnter and MouseLeave events for the views that are under the mouse.
     ///     INTERNAL: Raises the MouseEnter and MouseLeave events for the views that are under the mouse.
     /// </summary>
     /// </summary>

+ 79 - 0
Terminal.Gui/Application/Application.Navigation.cs

@@ -7,4 +7,83 @@ public static partial class Application // Navigation stuff
     ///     Gets the <see cref="ApplicationNavigation"/> instance for the current <see cref="Application"/>.
     ///     Gets the <see cref="ApplicationNavigation"/> instance for the current <see cref="Application"/>.
     /// </summary>
     /// </summary>
     public static ApplicationNavigation? Navigation { get; internal set; }
     public static ApplicationNavigation? Navigation { get; internal set; }
+
+    private static Key _nextTabGroupKey = Key.F6; // Resources/config.json overrides
+    private static Key _nextTabKey = Key.Tab; // Resources/config.json overrides
+    private static Key _prevTabGroupKey = Key.F6.WithShift; // Resources/config.json overrides
+    private static Key _prevTabKey = Key.Tab.WithShift; // Resources/config.json overrides
+
+    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key NextTabGroupKey
+    {
+        get => _nextTabGroupKey;
+        set
+        {
+            if (_nextTabGroupKey != value)
+            {
+                ReplaceKey (_nextTabGroupKey, value);
+                _nextTabGroupKey = value;
+            }
+        }
+    }
+
+    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key NextTabKey
+    {
+        get => _nextTabKey;
+        set
+        {
+            if (_nextTabKey != value)
+            {
+                ReplaceKey (_nextTabKey, value);
+                _nextTabKey = value;
+            }
+        }
+    }
+
+
+    /// <summary>
+    ///     Raised when the user releases a key.
+    ///     <para>
+    ///         Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
+    ///         additional processing.
+    ///     </para>
+    /// </summary>
+    /// <remarks>
+    ///     All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
+    ///     <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
+    ///     <para>Fired after <see cref="KeyDown"/>.</para>
+    /// </remarks>
+    public static event EventHandler<Key>? KeyUp;
+    /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key PrevTabGroupKey
+    {
+        get => _prevTabGroupKey;
+        set
+        {
+            if (_prevTabGroupKey != value)
+            {
+                ReplaceKey (_prevTabGroupKey, value);
+                _prevTabGroupKey = value;
+            }
+        }
+    }
+
+    /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key PrevTabKey
+    {
+        get => _prevTabKey;
+        set
+        {
+            if (_prevTabKey != value)
+            {
+                ReplaceKey (_prevTabKey, value);
+                _prevTabKey = value;
+            }
+        }
+    }
 }
 }

+ 42 - 7
Terminal.Gui/Application/Application.Run.cs

@@ -6,6 +6,41 @@ namespace Terminal.Gui;
 
 
 public static partial class Application // Run (Begin, Run, End, Stop)
 public static partial class Application // Run (Begin, Run, End, Stop)
 {
 {
+    private static Key _quitKey = Key.Esc; // Resources/config.json overrides
+
+    /// <summary>Gets or sets the key to quit the application.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key QuitKey
+    {
+        get => _quitKey;
+        set
+        {
+            if (_quitKey != value)
+            {
+                ReplaceKey (_quitKey, value);
+                _quitKey = value;
+            }
+        }
+    }
+
+    private static Key _arrangeKey = Key.F5.WithCtrl; // Resources/config.json overrides
+
+
+    /// <summary>Gets or sets the key to activate arranging views using the keyboard.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key ArrangeKey
+    {
+        get => _arrangeKey;
+        set
+        {
+            if (_arrangeKey != value)
+            {
+                ReplaceKey (_arrangeKey, value);
+                _arrangeKey = value;
+            }
+        }
+    }
+
     // When `End ()` is called, it is possible `RunState.Toplevel` is a different object than `Top`.
     // When `End ()` is called, it is possible `RunState.Toplevel` is a different object than `Top`.
     // This variable is set in `End` in this case so that `Begin` correctly sets `Top`.
     // This variable is set in `End` in this case so that `Begin` correctly sets `Top`.
     private static Toplevel? _cachedRunStateToplevel;
     private static Toplevel? _cachedRunStateToplevel;
@@ -45,14 +80,14 @@ public static partial class Application // Run (Begin, Run, End, Stop)
     {
     {
         ArgumentNullException.ThrowIfNull (toplevel);
         ArgumentNullException.ThrowIfNull (toplevel);
 
 
-#if DEBUG_IDISPOSABLE
-        Debug.Assert (!toplevel.WasDisposed);
+//#if DEBUG_IDISPOSABLE
+//        Debug.Assert (!toplevel.WasDisposed);
 
 
-        if (_cachedRunStateToplevel is { } && _cachedRunStateToplevel != toplevel)
-        {
-            Debug.Assert (_cachedRunStateToplevel.WasDisposed);
-        }
-#endif
+//        if (_cachedRunStateToplevel is { } && _cachedRunStateToplevel != toplevel)
+//        {
+//            Debug.Assert (_cachedRunStateToplevel.WasDisposed);
+//        }
+//#endif
 
 
         // Ensure the mouse is ungrabbed.
         // Ensure the mouse is ungrabbed.
         MouseGrabView = null;
         MouseGrabView = null;

+ 2 - 2
Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs

@@ -588,11 +588,11 @@ public abstract class ConsoleDriver
     public void OnKeyUp (Key a) { KeyUp?.Invoke (this, a); }
     public void OnKeyUp (Key a) { KeyUp?.Invoke (this, a); }
 
 
     /// <summary>Event fired when a mouse event occurs.</summary>
     /// <summary>Event fired when a mouse event occurs.</summary>
-    public event EventHandler<MouseEvent>? MouseEvent;
+    public event EventHandler<MouseEventArgs>? MouseEvent;
 
 
     /// <summary>Called when a mouse event occurs. Fires the <see cref="MouseEvent"/> event.</summary>
     /// <summary>Called when a mouse event occurs. Fires the <see cref="MouseEvent"/> event.</summary>
     /// <param name="a"></param>
     /// <param name="a"></param>
-    public void OnMouseEvent (MouseEvent a)
+    public void OnMouseEvent (MouseEventArgs a)
     {
     {
         // Ensure ScreenPosition is set
         // Ensure ScreenPosition is set
         a.ScreenPosition = a.Position;
         a.ScreenPosition = a.Position;

+ 211 - 44
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -39,7 +39,7 @@ internal class CursesDriver : ConsoleDriver
         }
         }
     }
     }
 
 
-    public override bool SupportsTrueColor => false;
+    public override bool SupportsTrueColor => true;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public override bool EnsureCursorVisibility () { return false; }
     public override bool EnsureCursorVisibility () { return false; }
@@ -200,8 +200,12 @@ internal class CursesDriver : ConsoleDriver
         if (!RunningUnitTests)
         if (!RunningUnitTests)
         {
         {
             Platform.Suspend ();
             Platform.Suspend ();
-            Curses.Window.Standard.redrawwin ();
-            Curses.refresh ();
+
+            if (Force16Colors)
+            {
+                Curses.Window.Standard.redrawwin ();
+                Curses.refresh ();
+            }
         }
         }
 
 
         StartReportingMouseMoves ();
         StartReportingMouseMoves ();
@@ -214,74 +218,232 @@ internal class CursesDriver : ConsoleDriver
         if (!RunningUnitTests && Col >= 0 && Col < Cols && Row >= 0 && Row < Rows)
         if (!RunningUnitTests && Col >= 0 && Col < Cols && Row >= 0 && Row < Rows)
         {
         {
             Curses.move (Row, Col);
             Curses.move (Row, Col);
-            Curses.raw ();
-            Curses.noecho ();
-            Curses.refresh ();
+
+            if (Force16Colors)
+            {
+                Curses.raw ();
+                Curses.noecho ();
+                Curses.refresh ();
+            }
         }
         }
     }
     }
 
 
-
     public override void UpdateScreen ()
     public override void UpdateScreen ()
     {
     {
-        for (var row = 0; row < Rows; row++)
+        if (Force16Colors)
         {
         {
-            if (!_dirtyLines [row])
+            for (var row = 0; row < Rows; row++)
             {
             {
-                continue;
-            }
-
-            _dirtyLines [row] = false;
-
-            for (var col = 0; col < Cols; col++)
-            {
-                if (Contents [row, col].IsDirty == false)
+                if (!_dirtyLines [row])
                 {
                 {
                     continue;
                     continue;
                 }
                 }
 
 
-                if (RunningUnitTests)
+                _dirtyLines [row] = false;
+
+                for (var col = 0; col < Cols; col++)
                 {
                 {
-                    // In unit tests, we don't want to actually write to the screen.
-                    continue;
-                }
+                    if (Contents [row, col].IsDirty == false)
+                    {
+                        continue;
+                    }
 
 
-                Curses.attrset (Contents [row, col].Attribute.GetValueOrDefault ().PlatformColor);
+                    if (RunningUnitTests)
+                    {
+                        // In unit tests, we don't want to actually write to the screen.
+                        continue;
+                    }
 
 
-                Rune rune = Contents [row, col].Rune;
+                    Curses.attrset (Contents [row, col].Attribute.GetValueOrDefault ().PlatformColor);
 
 
-                if (rune.IsBmp)
-                {
-                    // BUGBUG: CursesDriver doesn't render CharMap correctly for wide chars (and other Unicode) - Curses is doing something funky with glyphs that report GetColums() of 1 yet are rendered wide. E.g. 0x2064 (invisible times) is reported as 1 column but is rendered as 2. WindowsDriver & NetDriver correctly render this as 1 column, overlapping the next cell.
-                    if (rune.GetColumns () < 2)
+                    Rune rune = Contents [row, col].Rune;
+
+                    if (rune.IsBmp)
                     {
                     {
-                        Curses.mvaddch (row, col, rune.Value);
+                        // BUGBUG: CursesDriver doesn't render CharMap correctly for wide chars (and other Unicode) - Curses is doing something funky with glyphs that report GetColums() of 1 yet are rendered wide. E.g. 0x2064 (invisible times) is reported as 1 column but is rendered as 2. WindowsDriver & NetDriver correctly render this as 1 column, overlapping the next cell.
+                        if (rune.GetColumns () < 2)
+                        {
+                            Curses.mvaddch (row, col, rune.Value);
+                        }
+                        else /*if (col + 1 < Cols)*/
+                        {
+                            Curses.mvaddwstr (row, col, rune.ToString ());
+                        }
                     }
                     }
-                    else /*if (col + 1 < Cols)*/
+                    else
                     {
                     {
                         Curses.mvaddwstr (row, col, rune.ToString ());
                         Curses.mvaddwstr (row, col, rune.ToString ());
+
+                        if (rune.GetColumns () > 1 && col + 1 < Cols)
+                        {
+                            // TODO: This is a hack to deal with non-BMP and wide characters.
+                            //col++;
+                            Curses.mvaddch (row, ++col, '*');
+                        }
                     }
                     }
                 }
                 }
-                else
+            }
+
+            if (!RunningUnitTests)
+            {
+                Curses.move (Row, Col);
+                _window.wrefresh ();
+            }
+        }
+        else
+        {
+            if (RunningUnitTests
+                || Console.WindowHeight < 1
+                || Contents.Length != Rows * Cols
+                || Rows != Console.WindowHeight)
+            {
+                return;
+            }
+
+            var top = 0;
+            var left = 0;
+            int rows = Rows;
+            int cols = Cols;
+            var output = new StringBuilder ();
+            Attribute? redrawAttr = null;
+            int lastCol = -1;
+
+            CursorVisibility? savedVisibility = _currentCursorVisibility;
+            SetCursorVisibility (CursorVisibility.Invisible);
+
+            for (int row = top; row < rows; row++)
+            {
+                if (Console.WindowHeight < 1)
+                {
+                    return;
+                }
+
+                if (!_dirtyLines [row])
+                {
+                    continue;
+                }
+
+                if (!SetCursorPosition (0, row))
                 {
                 {
-                    Curses.mvaddwstr (row, col, rune.ToString ());
+                    return;
+                }
+
+                _dirtyLines [row] = false;
+                output.Clear ();
 
 
-                    if (rune.GetColumns () > 1 && col + 1 < Cols)
+                for (int col = left; col < cols; col++)
+                {
+                    lastCol = -1;
+                    var outputWidth = 0;
+
+                    for (; col < cols; col++)
                     {
                     {
-                        // TODO: This is a hack to deal with non-BMP and wide characters.
-                        //col++;
-                        Curses.mvaddch (row, ++col, '*');
+                        if (!Contents [row, col].IsDirty)
+                        {
+                            if (output.Length > 0)
+                            {
+                                WriteToConsole (output, ref lastCol, row, ref outputWidth);
+                            }
+                            else if (lastCol == -1)
+                            {
+                                lastCol = col;
+                            }
+
+                            if (lastCol + 1 < cols)
+                            {
+                                lastCol++;
+                            }
+
+                            continue;
+                        }
+
+                        if (lastCol == -1)
+                        {
+                            lastCol = col;
+                        }
+
+                        Attribute attr = Contents [row, col].Attribute.Value;
+
+                        // Performance: Only send the escape sequence if the attribute has changed.
+                        if (attr != redrawAttr)
+                        {
+                            redrawAttr = attr;
+
+                            output.Append (
+                                           EscSeqUtils.CSI_SetForegroundColorRGB (
+                                                                                  attr.Foreground.R,
+                                                                                  attr.Foreground.G,
+                                                                                  attr.Foreground.B
+                                                                                 )
+                                          );
+
+                            output.Append (
+                                           EscSeqUtils.CSI_SetBackgroundColorRGB (
+                                                                                  attr.Background.R,
+                                                                                  attr.Background.G,
+                                                                                  attr.Background.B
+                                                                                 )
+                                          );
+                        }
+
+                        outputWidth++;
+                        Rune rune = Contents [row, col].Rune;
+                        output.Append (rune);
+
+                        if (Contents [row, col].CombiningMarks.Count > 0)
+                        {
+                            // AtlasEngine does not support NON-NORMALIZED combining marks in a way
+                            // compatible with the driver architecture. Any CMs (except in the first col)
+                            // are correctly combined with the base char, but are ALSO treated as 1 column
+                            // width codepoints E.g. `echo "[e`u{0301}`u{0301}]"` will output `[é  ]`.
+                            // 
+                            // For now, we just ignore the list of CMs.
+                            //foreach (var combMark in Contents [row, col].CombiningMarks) {
+                            //	output.Append (combMark);
+                            //}
+                            // WriteToConsole (output, ref lastCol, row, ref outputWidth);
+                        }
+                        else if (rune.IsSurrogatePair () && rune.GetColumns () < 2)
+                        {
+                            WriteToConsole (output, ref lastCol, row, ref outputWidth);
+                            SetCursorPosition (col - 1, row);
+                        }
+
+                        Contents [row, col].IsDirty = false;
                     }
                     }
                 }
                 }
+
+                if (output.Length > 0)
+                {
+                    SetCursorPosition (lastCol, row);
+                    Console.Write (output);
+                }
             }
             }
-        }
 
 
-        if (!RunningUnitTests)
-        {
-            Curses.move (Row, Col);
-            _window.wrefresh ();
+            SetCursorPosition (0, 0);
+
+            _currentCursorVisibility = savedVisibility;
+
+            void WriteToConsole (StringBuilder output, ref int lastCol, int row, ref int outputWidth)
+            {
+                SetCursorPosition (lastCol, row);
+                Console.Write (output);
+                output.Clear ();
+                lastCol += outputWidth;
+                outputWidth = 0;
+            }
         }
         }
     }
     }
 
 
+    private bool SetCursorPosition (int col, int row)
+    {
+        // + 1 is needed because non-Windows is based on 1 instead of 0 and
+        // Console.CursorTop/CursorLeft isn't reliable.
+        Console.Out.Write (EscSeqUtils.CSI_SetCursorPosition (row + 1, col + 1));
+
+        return true;
+    }
+
     internal override void End ()
     internal override void End ()
     {
     {
         StopReportingMouseMoves ();
         StopReportingMouseMoves ();
@@ -405,7 +567,11 @@ internal class CursesDriver : ConsoleDriver
         if (!RunningUnitTests)
         if (!RunningUnitTests)
         {
         {
             Curses.CheckWinChange ();
             Curses.CheckWinChange ();
-            Curses.refresh ();
+
+            if (Force16Colors)
+            {
+                Curses.refresh ();
+            }
         }
         }
 
 
         return new MainLoop (_mainLoopDriver);
         return new MainLoop (_mainLoopDriver);
@@ -838,7 +1004,7 @@ internal class CursesDriver : ConsoleDriver
 
 
         _lastMouseFlags = mouseFlag;
         _lastMouseFlags = mouseFlag;
 
 
-        var me = new MouseEvent { Flags = mouseFlag, Position = pos };
+        var me = new MouseEventArgs { Flags = mouseFlag, Position = pos };
         //Debug.WriteLine ($"CursesDriver: ({me.Position}) - {me.Flags}");
         //Debug.WriteLine ($"CursesDriver: ({me.Position}) - {me.Flags}");
 
 
         OnMouseEvent (me);
         OnMouseEvent (me);
@@ -852,7 +1018,8 @@ internal class CursesDriver : ConsoleDriver
     /// <returns></returns>
     /// <returns></returns>
     private static Attribute MakeColor (short foreground, short background)
     private static Attribute MakeColor (short foreground, short background)
     {
     {
-        var v = (short)((ushort)foreground | (background << 4));
+        //var v = (short)((ushort)foreground | (background << 4));
+        var v = (short)(((ushort)(foreground & 0xffff) << 16) | (background & 0xffff));
 
 
         // TODO: for TrueColor - Use InitExtendedPair
         // TODO: for TrueColor - Use InitExtendedPair
         Curses.InitColorPair (v, foreground, background);
         Curses.InitColorPair (v, foreground, background);
@@ -872,7 +1039,7 @@ internal class CursesDriver : ConsoleDriver
     /// </remarks>
     /// </remarks>
     public override Attribute MakeColor (in Color foreground, in Color background)
     public override Attribute MakeColor (in Color foreground, in Color background)
     {
     {
-        if (!RunningUnitTests)
+        if (!RunningUnitTests && Force16Colors)
         {
         {
             return MakeColor (
             return MakeColor (
                               ColorNameToCursesColorNumber (foreground.GetClosestNamedColor16 ()),
                               ColorNameToCursesColorNumber (foreground.GetClosestNamedColor16 ()),

+ 3 - 3
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -1154,7 +1154,7 @@ internal class NetDriver : ConsoleDriver
 
 
                 break;
                 break;
             case EventType.Mouse:
             case EventType.Mouse:
-                MouseEvent me = ToDriverMouse (inputEvent.MouseEvent);
+                MouseEventArgs me = ToDriverMouse (inputEvent.MouseEvent);
                 //Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}");
                 //Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}");
                 OnMouseEvent (me);
                 OnMouseEvent (me);
 
 
@@ -1393,7 +1393,7 @@ internal class NetDriver : ConsoleDriver
         }
         }
     }
     }
 
 
-    private MouseEvent ToDriverMouse (NetEvents.MouseEvent me)
+    private MouseEventArgs ToDriverMouse (NetEvents.MouseEvent me)
     {
     {
        //System.Diagnostics.Debug.WriteLine ($"X: {me.Position.X}; Y: {me.Position.Y}; ButtonState: {me.ButtonState}");
        //System.Diagnostics.Debug.WriteLine ($"X: {me.Position.X}; Y: {me.Position.Y}; ButtonState: {me.ButtonState}");
 
 
@@ -1539,7 +1539,7 @@ internal class NetDriver : ConsoleDriver
             mouseFlag |= MouseFlags.ButtonAlt;
             mouseFlag |= MouseFlags.ButtonAlt;
         }
         }
 
 
-        return new MouseEvent { Position = me.Position, Flags = mouseFlag };
+        return new MouseEventArgs { Position = me.Position, Flags = mouseFlag };
     }
     }
 
 
     #endregion Mouse Handling
     #endregion Mouse Handling

+ 5 - 5
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1483,7 +1483,7 @@ internal class WindowsDriver : ConsoleDriver
                 break;
                 break;
 
 
             case WindowsConsole.EventType.Mouse:
             case WindowsConsole.EventType.Mouse:
-                MouseEvent me = ToDriverMouse (inputEvent.MouseEvent);
+                MouseEventArgs me = ToDriverMouse (inputEvent.MouseEvent);
 
 
                 if (me is null || me.Flags == MouseFlags.None)
                 if (me is null || me.Flags == MouseFlags.None)
                 {
                 {
@@ -1827,9 +1827,9 @@ internal class WindowsDriver : ConsoleDriver
             }
             }
             await Task.Delay (delay);
             await Task.Delay (delay);
 
 
-            var me = new MouseEvent
+            var me = new MouseEventArgs
             {
             {
-                Position = _pointMove,
+                ScreenPosition = _pointMove,
                 Flags = mouseFlag
                 Flags = mouseFlag
             };
             };
 
 
@@ -1883,7 +1883,7 @@ internal class WindowsDriver : ConsoleDriver
     }
     }
 
 
     [CanBeNull]
     [CanBeNull]
-    private MouseEvent ToDriverMouse (WindowsConsole.MouseEventRecord mouseEvent)
+    private MouseEventArgs ToDriverMouse (WindowsConsole.MouseEventRecord mouseEvent)
     {
     {
         var mouseFlag = MouseFlags.AllEvents;
         var mouseFlag = MouseFlags.AllEvents;
 
 
@@ -2127,7 +2127,7 @@ internal class WindowsDriver : ConsoleDriver
         //System.Diagnostics.Debug.WriteLine (
         //System.Diagnostics.Debug.WriteLine (
         //	$"point.X:{(point is { } ? ((Point)point).X : -1)};point.Y:{(point is { } ? ((Point)point).Y : -1)}");
         //	$"point.X:{(point is { } ? ((Point)point).X : -1)};point.Y:{(point is { } ? ((Point)point).Y : -1)}");
 
 
-        return new MouseEvent
+        return new MouseEventArgs
         {
         {
             Position = new (mouseEvent.MousePosition.X, mouseEvent.MousePosition.Y),
             Position = new (mouseEvent.MousePosition.X, mouseEvent.MousePosition.Y),
             Flags = mouseFlag
             Flags = mouseFlag

+ 152 - 6
Terminal.Gui/Drawing/Cell.cs

@@ -4,19 +4,18 @@
 ///     Represents a single row/column in a Terminal.Gui rendering surface (e.g. <see cref="LineCanvas"/> and
 ///     Represents a single row/column in a Terminal.Gui rendering surface (e.g. <see cref="LineCanvas"/> and
 ///     <see cref="ConsoleDriver"/>).
 ///     <see cref="ConsoleDriver"/>).
 /// </summary>
 /// </summary>
-public record struct Cell ()
+public record struct Cell (Attribute? Attribute = null, bool IsDirty = false, Rune Rune = default)
 {
 {
-
     /// <summary>The attributes to use when drawing the Glyph.</summary>
     /// <summary>The attributes to use when drawing the Glyph.</summary>
-    public Attribute? Attribute { get; set; } = null;
+    public Attribute? Attribute { get; set; } = Attribute;
 
 
     /// <summary>
     /// <summary>
     ///     Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.Cell"/> has been modified since the
     ///     Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.Cell"/> has been modified since the
     ///     last time it was drawn.
     ///     last time it was drawn.
     /// </summary>
     /// </summary>
-    public bool IsDirty { get; set; } = false;
+    public bool IsDirty { get; set; } = IsDirty;
 
 
-    private Rune _rune = default;
+    private Rune _rune = Rune;
 
 
     /// <summary>The character to display. If <see cref="Rune"/> is <see langword="null"/>, then <see cref="Rune"/> is ignored.</summary>
     /// <summary>The character to display. If <see cref="Rune"/> is <see langword="null"/>, then <see cref="Rune"/> is ignored.</summary>
     public Rune Rune
     public Rune Rune
@@ -29,6 +28,8 @@ public record struct Cell ()
         }
         }
     }
     }
 
 
+    private List<Rune> _combiningMarks;
+
     /// <summary>
     /// <summary>
     ///     The combining marks for <see cref="Rune"/> that when combined makes this Cell a combining sequence. If
     ///     The combining marks for <see cref="Rune"/> that when combined makes this Cell a combining sequence. If
     ///     <see cref="CombiningMarks"/> empty, then <see cref="CombiningMarks"/> is ignored.
     ///     <see cref="CombiningMarks"/> empty, then <see cref="CombiningMarks"/> is ignored.
@@ -37,8 +38,153 @@ public record struct Cell ()
     ///     Only valid in the rare case where <see cref="Rune"/> is a combining sequence that could not be normalized to a
     ///     Only valid in the rare case where <see cref="Rune"/> is a combining sequence that could not be normalized to a
     ///     single Rune.
     ///     single Rune.
     /// </remarks>
     /// </remarks>
-    internal List<Rune> CombiningMarks { get; } = new ();
+    internal List<Rune> CombiningMarks
+    {
+        get => _combiningMarks ?? [];
+        private set => _combiningMarks = value ?? [];
+    }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public override string ToString () { return $"[{Rune}, {Attribute}]"; }
     public override string ToString () { return $"[{Rune}, {Attribute}]"; }
+
+    /// <summary>Converts the string into a <see cref="List{Cell}"/>.</summary>
+    /// <param name="str">The string to convert.</param>
+    /// <param name="attribute">The <see cref="Gui.ColorScheme"/> to use.</param>
+    /// <returns></returns>
+    public static List<Cell> ToCellList (string str, Attribute? attribute = null)
+    {
+        List<Cell> cells = new ();
+
+        foreach (Rune rune in str.EnumerateRunes ())
+        {
+            cells.Add (new () { Rune = rune, Attribute = attribute });
+        }
+
+        return cells;
+    }
+
+    /// <summary>
+    ///     Splits a string into a List that will contain a <see cref="List{Cell}"/> for each line.
+    /// </summary>
+    /// <param name="content">The string content.</param>
+    /// <param name="attribute">The color scheme.</param>
+    /// <returns>A <see cref="List{Cell}"/> for each line.</returns>
+    public static List<List<Cell>> StringToLinesOfCells (string content, Attribute? attribute = null)
+    {
+        List<Cell> cells = content.EnumerateRunes ()
+                                  .Select (x => new Cell { Rune = x, Attribute = attribute })
+                                  .ToList ();
+
+        return SplitNewLines (cells);
+    }
+
+    /// <summary>Converts a <see cref="Cell"/> generic collection into a string.</summary>
+    /// <param name="cells">The enumerable cell to convert.</param>
+    /// <returns></returns>
+    public static string ToString (IEnumerable<Cell> cells)
+    {
+        var str = string.Empty;
+
+        foreach (Cell cell in cells)
+        {
+            str += cell.Rune.ToString ();
+        }
+
+        return str;
+    }
+
+    /// <summary>Converts a <see cref="List{Cell}"/> generic collection into a string.</summary>
+    /// <param name="cellsList">The enumerable cell to convert.</param>
+    /// <returns></returns>
+    public static string ToString (List<List<Cell>> cellsList)
+    {
+        var str = string.Empty;
+
+        for (var i = 0; i < cellsList.Count; i++)
+        {
+            IEnumerable<Cell> cellList = cellsList [i];
+            str += ToString (cellList);
+
+            if (i + 1 < cellsList.Count)
+            {
+                str += Environment.NewLine;
+            }
+        }
+
+        return str;
+    }
+
+    // Turns the string into cells, this does not split the contents on a newline if it is present.
+
+    internal static List<Cell> StringToCells (string str, Attribute? attribute = null)
+    {
+        List<Cell> cells = [];
+
+        foreach (Rune rune in str.ToRunes ())
+        {
+            cells.Add (new () { Rune = rune, Attribute = attribute });
+        }
+
+        return cells;
+    }
+
+    internal static List<Cell> ToCells (IEnumerable<Rune> runes, Attribute? attribute = null)
+    {
+        List<Cell> cells = new ();
+
+        foreach (Rune rune in runes)
+        {
+            cells.Add (new () { Rune = rune, Attribute = attribute });
+        }
+
+        return cells;
+    }
+
+    private static List<List<Cell>> SplitNewLines (List<Cell> cells)
+    {
+        List<List<Cell>> lines = [];
+        int start = 0, i = 0;
+        var hasCR = false;
+
+        // ASCII code 13 = Carriage Return.
+        // ASCII code 10 = Line Feed.
+        for (; i < cells.Count; i++)
+        {
+            if (cells [i].Rune.Value == 13)
+            {
+                hasCR = true;
+
+                continue;
+            }
+
+            if (cells [i].Rune.Value == 10)
+            {
+                if (i - start > 0)
+                {
+                    lines.Add (cells.GetRange (start, hasCR ? i - 1 - start : i - start));
+                }
+                else
+                {
+                    lines.Add (StringToCells (string.Empty));
+                }
+
+                start = i + 1;
+                hasCR = false;
+            }
+        }
+
+        if (i - start >= 0)
+        {
+            lines.Add (cells.GetRange (start, i - start));
+        }
+
+        return lines;
+    }
+
+    /// <summary>
+    ///     Splits a rune cell list into a List that will contain a <see cref="List{Cell}"/> for each line.
+    /// </summary>
+    /// <param name="cells">The cells list.</param>
+    /// <returns></returns>
+    public static List<List<Cell>> ToCells (List<Cell> cells) { return SplitNewLines (cells); }
 }
 }

+ 8 - 8
Terminal.Gui/Views/RuneCellEventArgs.cs → Terminal.Gui/Drawing/CellEventArgs.cs

@@ -1,27 +1,27 @@
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
-/// <summary>Args for events that relate to a specific <see cref="RuneCell"/>.</summary>
-public class RuneCellEventArgs
+/// <summary>Args for events that relate to a specific <see cref="Cell"/>.</summary>
+public record struct CellEventArgs
 {
 {
-    /// <summary>Creates a new instance of the <see cref="RuneCellEventArgs"/> class.</summary>
+    /// <summary>Creates a new instance of the <see cref="CellEventArgs"/> class.</summary>
     /// <param name="line">The line.</param>
     /// <param name="line">The line.</param>
     /// <param name="col">The col index.</param>
     /// <param name="col">The col index.</param>
     /// <param name="unwrappedPosition">The unwrapped row and col index.</param>
     /// <param name="unwrappedPosition">The unwrapped row and col index.</param>
-    public RuneCellEventArgs (List<RuneCell> line, int col, (int Row, int Col) unwrappedPosition)
+    public CellEventArgs (List<Cell> line, int col, (int Row, int Col) unwrappedPosition)
     {
     {
         Line = line;
         Line = line;
         Col = col;
         Col = col;
         UnwrappedPosition = unwrappedPosition;
         UnwrappedPosition = unwrappedPosition;
     }
     }
 
 
-    /// <summary>The index of the RuneCell in the line.</summary>
+    /// <summary>The index of the Cell in the line.</summary>
     public int Col { get; }
     public int Col { get; }
 
 
-    /// <summary>The list of runes the RuneCell is part of.</summary>
-    public List<RuneCell> Line { get; }
+    /// <summary>The list of runes the Cell is part of.</summary>
+    public List<Cell> Line { get; }
 
 
     /// <summary>
     /// <summary>
-    ///     The unwrapped row and column index into the text containing the RuneCell. Unwrapped means the text without
+    ///     The unwrapped row and column index into the text containing the Cell. Unwrapped means the text without
     ///     word wrapping or other visual formatting having been applied.
     ///     word wrapping or other visual formatting having been applied.
     /// </summary>
     /// </summary>
     public (int Row, int Col) UnwrappedPosition { get; }
     public (int Row, int Col) UnwrappedPosition { get; }

+ 1 - 1
Terminal.Gui/Drawing/LineCanvas.cs

@@ -138,7 +138,7 @@ public class LineCanvas : IDisposable
         int length,
         int length,
         Orientation orientation,
         Orientation orientation,
         LineStyle style,
         LineStyle style,
-        Attribute? attribute = default
+        Attribute? attribute = null
     )
     )
     {
     {
         _cachedViewport = Rectangle.Empty;
         _cachedViewport = Rectangle.Empty;

+ 1 - 1
Terminal.Gui/Drawing/StraightLine.cs

@@ -16,7 +16,7 @@ public class StraightLine
         int length,
         int length,
         Orientation orientation,
         Orientation orientation,
         LineStyle style,
         LineStyle style,
-        Attribute? attribute = default
+        Attribute? attribute = null
     )
     )
     {
     {
         Start = start;
         Start = start;

+ 101 - 0
Terminal.Gui/Input/MouseEventArgs.cs

@@ -0,0 +1,101 @@
+#nullable enable
+using System.ComponentModel;
+
+namespace Terminal.Gui;
+
+/// <summary>
+///     Specifies the event arguments for <see cref="Terminal.Gui.MouseEventArgs"/>. This is a higher-level construct than
+///     the wrapped <see cref="Terminal.Gui.MouseEventArgs"/> class and is used for the events defined on
+///     <see cref="View"/> and subclasses
+///     of View (e.g. <see cref="View.MouseEnter"/> and <see cref="View.MouseClick"/>).
+/// </summary>
+public class MouseEventArgs : HandledEventArgs
+{
+    /// <summary>
+    ///     Flags indicating the state of the mouse buttons and the type of event that occurred.
+    /// </summary>
+    public MouseFlags Flags { get; set; }
+
+    /// <summary>
+    ///     The screen-relative mouse position.
+    /// </summary>
+    public Point ScreenPosition { get; set; }
+
+    /// <summary>The deepest View who's <see cref="View.Frame"/> contains <see cref="ScreenPosition"/>.</summary>
+    public View? View { get; set; }
+
+    /// <summary>
+    ///     The position of the mouse in <see cref="View"/>'s Viewport-relative coordinates. Only valid if <see cref="View"/>
+    ///     is set.
+    /// </summary>
+    public Point Position { get; set; }
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the button pressed related flags.
+    /// </summary>
+    public bool IsPressed => Flags.HasFlag (MouseFlags.Button1Pressed)
+                             || Flags.HasFlag (MouseFlags.Button2Pressed)
+                             || Flags.HasFlag (MouseFlags.Button3Pressed)
+                             || Flags.HasFlag (MouseFlags.Button4Pressed);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the button released related flags.
+    /// </summary>
+    public bool IsReleased => Flags.HasFlag (MouseFlags.Button1Released)
+                              || Flags.HasFlag (MouseFlags.Button2Released)
+                              || Flags.HasFlag (MouseFlags.Button3Released)
+                              || Flags.HasFlag (MouseFlags.Button4Released);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the single-clicked related flags.
+    /// </summary>
+    public bool IsSingleClicked => Flags.HasFlag (MouseFlags.Button1Clicked)
+                                   || Flags.HasFlag (MouseFlags.Button2Clicked)
+                                   || Flags.HasFlag (MouseFlags.Button3Clicked)
+                                   || Flags.HasFlag (MouseFlags.Button4Clicked);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the double-clicked related flags.
+    /// </summary>
+    public bool IsDoubleClicked => Flags.HasFlag (MouseFlags.Button1DoubleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button2DoubleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button3DoubleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button4DoubleClicked);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the triple-clicked related flags.
+    /// </summary>
+    public bool IsTripleClicked => Flags.HasFlag (MouseFlags.Button1TripleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button2TripleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button3TripleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button4TripleClicked);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the mouse button clicked related flags.
+    /// </summary>
+    public bool IsSingleDoubleOrTripleClicked =>
+        Flags.HasFlag (MouseFlags.Button1Clicked)
+        || Flags.HasFlag (MouseFlags.Button2Clicked)
+        || Flags.HasFlag (MouseFlags.Button3Clicked)
+        || Flags.HasFlag (MouseFlags.Button4Clicked)
+        || Flags.HasFlag (MouseFlags.Button1DoubleClicked)
+        || Flags.HasFlag (MouseFlags.Button2DoubleClicked)
+        || Flags.HasFlag (MouseFlags.Button3DoubleClicked)
+        || Flags.HasFlag (MouseFlags.Button4DoubleClicked)
+        || Flags.HasFlag (MouseFlags.Button1TripleClicked)
+        || Flags.HasFlag (MouseFlags.Button2TripleClicked)
+        || Flags.HasFlag (MouseFlags.Button3TripleClicked)
+        || Flags.HasFlag (MouseFlags.Button4TripleClicked);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the mouse wheel related flags.
+    /// </summary>
+    public bool IsWheel => Flags.HasFlag (MouseFlags.WheeledDown)
+                           || Flags.HasFlag (MouseFlags.WheeledUp)
+                           || Flags.HasFlag (MouseFlags.WheeledLeft)
+                           || Flags.HasFlag (MouseFlags.WheeledRight);
+
+    /// <summary>Returns a <see cref="T:System.String"/> that represents the current <see cref="Terminal.Gui.MouseEventArgs"/>.</summary>
+    /// <returns>A <see cref="T:System.String"/> that represents the current <see cref="Terminal.Gui.MouseEventArgs"/>.</returns>
+    public override string ToString () { return $"({ScreenPosition}):{Flags}:{View?.Id}:{Position}"; }
+}

+ 0 - 32
Terminal.Gui/Input/MouseEventEventArgs.cs

@@ -1,32 +0,0 @@
-namespace Terminal.Gui;
-
-/// <summary>
-///     Specifies the event arguments for <see cref="Terminal.Gui.MouseEvent"/>. This is a higher-level construct than
-///     the wrapped <see cref="MouseEvent"/> class and is used for the events defined on <see cref="View"/> and subclasses
-///     of View (e.g. <see cref="View.MouseEnter"/> and <see cref="View.MouseClick"/>).
-/// </summary>
-public class MouseEventEventArgs : EventArgs
-{
-    /// <summary>Constructs.</summary>
-    /// <param name="me">The mouse event.</param>
-    public MouseEventEventArgs (MouseEvent me) { MouseEvent = me; }
-
-    /// <summary>
-    ///     Indicates if the current mouse event has already been processed and the driver should stop notifying any other
-    ///     event subscriber. It's important to set this value to true specially when updating any View's layout from inside the
-    ///     subscriber method.
-    /// </summary>
-    /// <remarks>
-    ///     This property forwards to the <see cref="MouseEvent.Handled"/> property and is provided as a convenience and
-    ///     for backwards compatibility
-    /// </remarks>
-    public bool Handled
-    {
-        get => MouseEvent.Handled;
-        set => MouseEvent.Handled = value;
-    }
-
-    // TODO: Merge MouseEvent and MouseEventEventArgs into a single class.
-    /// <summary>The <see cref="Terminal.Gui.MouseEvent"/> for the event.</summary>
-    public MouseEvent MouseEvent { get; set; }
-}

+ 2 - 49
Terminal.Gui/Input/Mouse.cs → Terminal.Gui/Input/MouseFlags.cs

@@ -1,12 +1,12 @@
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
-/// <summary>Mouse flags reported in <see cref="MouseEvent"/>.</summary>
+/// <summary>Mouse flags reported in <see cref="MouseEventArgs"/>.</summary>
 /// <remarks>They just happen to map to the ncurses ones.</remarks>
 /// <remarks>They just happen to map to the ncurses ones.</remarks>
 [Flags]
 [Flags]
 public enum MouseFlags
 public enum MouseFlags
 {
 {
     /// <summary>
     /// <summary>
-    ///    No mouse event. This is the default value for <see cref="MouseEvent.Flags"/> when no mouse event is being reported.
+    ///    No mouse event. This is the default value for <see cref="Terminal.Gui.MouseEventArgs.Flags"/> when no mouse event is being reported.
     /// </summary>
     /// </summary>
     None = 0,
     None = 0,
 
 
@@ -97,50 +97,3 @@ public enum MouseFlags
     /// <summary>Mask that captures all the events.</summary>
     /// <summary>Mask that captures all the events.</summary>
     AllEvents = 0x7ffffff
     AllEvents = 0x7ffffff
 }
 }
-
-// TODO: Merge MouseEvent and MouseEventEventArgs into a single class.
-
-/// <summary>
-///     Conveys the details of mouse events, such as coordinates and button state, from
-///     ConsoleDrivers up to <see cref="Application"/> and Views.
-/// </summary>
-/// <remarks>
-///     The <see cref="Application"/> class includes the <see cref="Application.MouseEvent"/> event which takes a
-///     MouseEvent argument.
-/// </remarks>
-public class MouseEvent
-{
-    /// <summary>Flags indicating the kind of mouse event that is being posted.</summary>
-    public MouseFlags Flags { get; set; }
-
-    /// <summary>The View at the location for the mouse event.</summary>
-    public View View { get; set; }
-
-    /// <summary>The position of the mouse in <see cref="Gui.View.Viewport"/>-relative coordinates.</summary>
-    public Point Position { get; set; }
-
-    /// <summary>
-    ///     The screen-relative mouse position.
-    /// </summary>
-    /// <remarks>
-    ///     <para>
-    ///         <see cref="Position"/> is <see cref="Gui.View.Viewport"/>-relative. When the mouse is grabbed by a view,
-    ///         <see cref="ScreenPosition"/> provides the mouse position screen-relative coordinates, enabling the grabbed view to know how much the
-    ///         mouse has moved.
-    ///     </para>
-    ///     <para>
-    ///         Calculated and processed in <see cref="Application.OnMouseEvent(MouseEvent)"/>.
-    ///     </para>
-    /// </remarks>
-    public Point ScreenPosition { get; set; }
-
-    /// <summary>
-    ///     Indicates if the current mouse event has been processed. Set this value to <see langword="true"/> to indicate the mouse
-    ///     event was handled.
-    /// </summary>
-    public bool Handled { get; set; }
-
-    /// <summary>Returns a <see cref="T:System.String"/> that represents the current <see cref="MouseEvent"/>.</summary>
-    /// <returns>A <see cref="T:System.String"/> that represents the current <see cref="MouseEvent"/>.</returns>
-    public override string ToString () { return $"({Position}):{Flags}"; }
-}

+ 0 - 173
Terminal.Gui/Input/ShortcutHelper.cs

@@ -1,173 +0,0 @@
-using System.Diagnostics;
-
-namespace Terminal.Gui;
-
-// TODO: Nuke when #2975 is completed
-/// <summary>Represents a helper to manipulate shortcut keys used on views.</summary>
-public class ShortcutHelper
-{
-    // TODO: Update this to use Key, not KeyCode
-    private KeyCode shortcut;
-
-    /// <summary>This is the global setting that can be used as a global shortcut to invoke the action on the view.</summary>
-    public virtual KeyCode Shortcut
-    {
-        get => shortcut;
-        set
-        {
-            if (shortcut != value && (PostShortcutValidation (value) || value is KeyCode.Null))
-            {
-                shortcut = value;
-            }
-        }
-    }
-
-    /// <summary>The keystroke combination used in the <see cref="Shortcut"/> as string.</summary>
-    public virtual string ShortcutTag => Key.ToString (shortcut, Key.Separator);
-
-    /// <summary>Lookup for a <see cref="KeyCode"/> on range of keys.</summary>
-    /// <param name="key">The source key.</param>
-    /// <param name="first">First key in range.</param>
-    /// <param name="last">Last key in range.</param>
-    public static bool CheckKeysFlagRange (KeyCode key, KeyCode first, KeyCode last)
-    {
-        for (var i = (uint)first; i < (uint)last; i++)
-        {
-            if ((key | (KeyCode)i) == key)
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /// <summary>Allows to retrieve a <see cref="KeyCode"/> from a <see cref="ShortcutTag"/></summary>
-    /// <param name="tag">The key as string.</param>
-    /// <param name="delimiter">The delimiter string.</param>
-    public static KeyCode GetShortcutFromTag (string tag, Rune delimiter = default)
-    {
-        string sCut = tag;
-
-        if (string.IsNullOrEmpty (sCut))
-        {
-            return default (KeyCode);
-        }
-
-        var key = KeyCode.Null;
-
-        //var hasCtrl = false;
-        if (delimiter == default (Rune))
-        {
-            delimiter = Key.Separator;
-        }
-
-        string [] keys = sCut.Split (delimiter.ToString ());
-
-        for (var i = 0; i < keys.Length; i++)
-        {
-            string k = keys [i];
-
-            if (k == "Ctrl")
-            {
-                //hasCtrl = true;
-                key |= KeyCode.CtrlMask;
-            }
-            else if (k == "Shift")
-            {
-                key |= KeyCode.ShiftMask;
-            }
-            else if (k == "Alt")
-            {
-                key |= KeyCode.AltMask;
-            }
-            else if (k.StartsWith ("F") && k.Length > 1)
-            {
-                int.TryParse (k.Substring (1), out int n);
-
-                for (var j = (uint)KeyCode.F1; j <= (uint)KeyCode.F12; j++)
-                {
-                    int.TryParse (((KeyCode)j).ToString ().Substring (1), out int f);
-
-                    if (f == n)
-                    {
-                        key |= (KeyCode)j;
-                    }
-                }
-            }
-            else
-            {
-                key |= (KeyCode)Enum.Parse (typeof (KeyCode), k);
-            }
-        }
-
-        return key;
-    }
-
-    /// <summary>Used at key up validation.</summary>
-    /// <param name="key">The key to validate.</param>
-    /// <returns><c>true</c> if is valid.<c>false</c>otherwise.</returns>
-    public static bool PostShortcutValidation (KeyCode key)
-    {
-        GetKeyToString (key, out KeyCode knm);
-
-        if (CheckKeysFlagRange (key, KeyCode.F1, KeyCode.F12) || ((key & (KeyCode.CtrlMask | KeyCode.ShiftMask | KeyCode.AltMask)) != 0 && knm != KeyCode.Null))
-        {
-            return true;
-        }
-
-        return false;
-    }
-
-    /// <summary>Used at key down or key press validation.</summary>
-    /// <param name="key">The key to validate.</param>
-    /// <returns><c>true</c> if is valid.<c>false</c>otherwise.</returns>
-    public static bool PreShortcutValidation (KeyCode key)
-    {
-        if ((key & (KeyCode.CtrlMask | KeyCode.ShiftMask | KeyCode.AltMask)) == 0
-            && !CheckKeysFlagRange (key, KeyCode.F1, KeyCode.F12))
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    /// <summary>Return key as string.</summary>
-    /// <param name="key">The key to extract.</param>
-    /// <param name="knm">Correspond to the non modifier key.</param>
-    private static string GetKeyToString (KeyCode key, out KeyCode knm)
-    {
-        if (key == KeyCode.Null)
-        {
-            knm = KeyCode.Null;
-
-            return "";
-        }
-
-        knm = key;
-        KeyCode mK = key & (KeyCode.AltMask | KeyCode.CtrlMask | KeyCode.ShiftMask);
-        knm &= ~mK;
-
-        for (var i = (uint)KeyCode.F1; i < (uint)KeyCode.F12; i++)
-        {
-            if (knm == (KeyCode)i)
-            {
-                mK |= (KeyCode)i;
-            }
-        }
-
-        knm &= ~mK;
-        uint.TryParse (knm.ToString (), out uint c);
-        string s = mK == KeyCode.Null ? "" : mK.ToString ();
-
-        if (s != "" && (knm != KeyCode.Null || c > 0))
-        {
-            s += ",";
-        }
-
-        s += c == 0 ? knm == KeyCode.Null ? "" : knm.ToString () : ((char)c).ToString ();
-
-        return s;
-    }
-}

+ 9 - 0
Terminal.Gui/Resources/Strings.Designer.cs

@@ -1437,6 +1437,15 @@ namespace Terminal.Gui.Resources {
             }
             }
         }
         }
         
         
+        /// <summary>
+        ///   Looks up a localized string similar to Co_lors.
+        /// </summary>
+        internal static string ctxColors {
+            get {
+                return ResourceManager.GetString("ctxColors", resourceCulture);
+            }
+        }
+        
         /// <summary>
         /// <summary>
         ///   Looks up a localized string similar to _Copy.
         ///   Looks up a localized string similar to _Copy.
         /// </summary>
         /// </summary>

+ 15 - 12
Terminal.Gui/Resources/Strings.fr-FR.resx

@@ -117,27 +117,27 @@
   <resheader name="writer">
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   </resheader>
+  <data name="ctxSelectAll" xml:space="preserve">
+    <value>Tout _sélectionner</value>
+  </data>
+  <data name="ctxDeleteAll" xml:space="preserve">
+    <value>_Tout supprimer</value>
+  </data>
   <data name="ctxCopy" xml:space="preserve">
   <data name="ctxCopy" xml:space="preserve">
     <value>_Copier</value>
     <value>_Copier</value>
   </data>
   </data>
   <data name="ctxCut" xml:space="preserve">
   <data name="ctxCut" xml:space="preserve">
     <value>Co_uper</value>
     <value>Co_uper</value>
   </data>
   </data>
-  <data name="ctxDeleteAll" xml:space="preserve">
-    <value>_Tout supprimer</value>
-  </data>
   <data name="ctxPaste" xml:space="preserve">
   <data name="ctxPaste" xml:space="preserve">
     <value>C_oller</value>
     <value>C_oller</value>
   </data>
   </data>
-  <data name="ctxRedo" xml:space="preserve">
-    <value>_Rétablir</value>
-  </data>
-  <data name="ctxSelectAll" xml:space="preserve">
-    <value>Tout _sélectionner</value>
-  </data>
   <data name="ctxUndo" xml:space="preserve">
   <data name="ctxUndo" xml:space="preserve">
     <value>_Annuler</value>
     <value>_Annuler</value>
   </data>
   </data>
+  <data name="ctxRedo" xml:space="preserve">
+    <value>_Rétablir</value>
+  </data>
   <data name="fdDirectory" xml:space="preserve">
   <data name="fdDirectory" xml:space="preserve">
     <value>_Dossier</value>
     <value>_Dossier</value>
   </data>
   </data>
@@ -168,16 +168,19 @@
   <data name="wzNext" xml:space="preserve">
   <data name="wzNext" xml:space="preserve">
     <value>Prochai_n...</value>
     <value>Prochai_n...</value>
   </data>
   </data>
+  <data name="btnOpen" xml:space="preserve">
+    <value>Ouvrir</value>
+  </data>
   <data name="btnSave" xml:space="preserve">
   <data name="btnSave" xml:space="preserve">
     <value>Enregistrer</value>
     <value>Enregistrer</value>
   </data>
   </data>
   <data name="btnSaveAs" xml:space="preserve">
   <data name="btnSaveAs" xml:space="preserve">
     <value>E_nregistrer sous</value>
     <value>E_nregistrer sous</value>
   </data>
   </data>
-  <data name="btnOpen" xml:space="preserve">
-    <value>Ouvrir</value>
-  </data>
   <data name="dpTitle" xml:space="preserve">
   <data name="dpTitle" xml:space="preserve">
     <value>Sélecteur de Date</value>
     <value>Sélecteur de Date</value>
   </data>
   </data>
+  <data name="ctxColors" xml:space="preserve">
+    <value>Cou_leurs</value>
+  </data>
 </root>
 </root>

+ 58 - 55
Terminal.Gui/Resources/Strings.ja-JP.resx

@@ -117,27 +117,27 @@
   <resheader name="writer">
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   </resheader>
+  <data name="ctxSelectAll" xml:space="preserve">
+    <value>全て選択 (_S)</value>
+  </data>
+  <data name="ctxDeleteAll" xml:space="preserve">
+    <value>全て削除 (_D)</value>
+  </data>
   <data name="ctxCopy" xml:space="preserve">
   <data name="ctxCopy" xml:space="preserve">
     <value>コピー (_C)</value>
     <value>コピー (_C)</value>
   </data>
   </data>
   <data name="ctxCut" xml:space="preserve">
   <data name="ctxCut" xml:space="preserve">
     <value>切り取り (_T)</value>
     <value>切り取り (_T)</value>
   </data>
   </data>
-  <data name="ctxDeleteAll" xml:space="preserve">
-    <value>全て削除 (_D)</value>
-  </data>
   <data name="ctxPaste" xml:space="preserve">
   <data name="ctxPaste" xml:space="preserve">
     <value>貼り付け (_P)</value>
     <value>貼り付け (_P)</value>
   </data>
   </data>
-  <data name="ctxRedo" xml:space="preserve">
-    <value>やり直し (_R)</value>
-  </data>
-  <data name="ctxSelectAll" xml:space="preserve">
-    <value>全て選択 (_S)</value>
-  </data>
   <data name="ctxUndo" xml:space="preserve">
   <data name="ctxUndo" xml:space="preserve">
     <value>元に戻す (_U)</value>
     <value>元に戻す (_U)</value>
   </data>
   </data>
+  <data name="ctxRedo" xml:space="preserve">
+    <value>やり直し (_R)</value>
+  </data>
   <data name="fdDirectory" xml:space="preserve">
   <data name="fdDirectory" xml:space="preserve">
     <value>ディレクトリ</value>
     <value>ディレクトリ</value>
   </data>
   </data>
@@ -171,44 +171,47 @@
   <data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
   <data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
     <value>同じ名前のディレクトリはすでに存在しました</value>
     <value>同じ名前のディレクトリはすでに存在しました</value>
   </data>
   </data>
-  <data name="fdDeleteBody" xml:space="preserve">
-    <value>“{0}”を削除もよろしいですか?この操作は元に戻りません</value>
-  </data>
-  <data name="fdType" xml:space="preserve">
-    <value>タイプ</value>
+  <data name="fdDirectoryMustExistFeedback" xml:space="preserve">
+    <value>すでに存在したディレクトリを選択してください</value>
   </data>
   </data>
-  <data name="fdSize" xml:space="preserve">
-    <value>サイズ</value>
+  <data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
+    <value>同じ名前のファイルはすでに存在しました</value>
   </data>
   </data>
-  <data name="fdPathCaption" xml:space="preserve">
-    <value>パスを入力</value>
+  <data name="fdFileMustExistFeedback" xml:space="preserve">
+    <value>すでに存在したファイルを選択してください</value>
   </data>
   </data>
   <data name="fdFilename" xml:space="preserve">
   <data name="fdFilename" xml:space="preserve">
     <value>ファイル名</value>
     <value>ファイル名</value>
   </data>
   </data>
-  <data name="fdNewTitle" xml:space="preserve">
-    <value>新規ディレクトリ</value>
-  </data>
-  <data name="btnNo" xml:space="preserve">
-    <value>いいえ (_N)</value>
-  </data>
-  <data name="btnYes" xml:space="preserve">
-    <value>はい (_Y)</value>
+  <data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
+    <value>すでに存在したファイルまたはディレクトリを選択してください</value>
   </data>
   </data>
   <data name="fdModified" xml:space="preserve">
   <data name="fdModified" xml:space="preserve">
     <value>変更日時</value>
     <value>変更日時</value>
   </data>
   </data>
-  <data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
-    <value>すでに存在したファイルまたはディレクトリを選択してください</value>
+  <data name="fdPathCaption" xml:space="preserve">
+    <value>パスを入力</value>
   </data>
   </data>
-  <data name="fdDirectoryMustExistFeedback" xml:space="preserve">
-    <value>すでに存在したディレクトリを選択してください</value>
+  <data name="fdSearchCaption" xml:space="preserve">
+    <value>検索を入力</value>
   </data>
   </data>
-  <data name="fdFileMustExistFeedback" xml:space="preserve">
-    <value>すでに存在したファイルを選択してください</value>
+  <data name="fdSize" xml:space="preserve">
+    <value>サイズ</value>
   </data>
   </data>
-  <data name="fdRenamePrompt" xml:space="preserve">
-    <value>名前:</value>
+  <data name="fdType" xml:space="preserve">
+    <value>タイプ</value>
+  </data>
+  <data name="fdWrongFileTypeFeedback" xml:space="preserve">
+    <value>ファイルタイプが間違っでいます</value>
+  </data>
+  <data name="fdAnyFiles" xml:space="preserve">
+    <value>任意ファイル</value>
+  </data>
+  <data name="fdDeleteBody" xml:space="preserve">
+    <value>“{0}”を削除もよろしいですか?この操作は元に戻りません</value>
+  </data>
+  <data name="fdDeleteFailedTitle" xml:space="preserve">
+    <value>削除失敗</value>
   </data>
   </data>
   <data name="fdDeleteTitle" xml:space="preserve">
   <data name="fdDeleteTitle" xml:space="preserve">
     <value>{0} を削除</value>
     <value>{0} を削除</value>
@@ -216,35 +219,26 @@
   <data name="fdNewFailed" xml:space="preserve">
   <data name="fdNewFailed" xml:space="preserve">
     <value>新規失敗</value>
     <value>新規失敗</value>
   </data>
   </data>
-  <data name="fdExisting" xml:space="preserve">
-    <value>既存</value>
+  <data name="fdNewTitle" xml:space="preserve">
+    <value>新規ディレクトリ</value>
   </data>
   </data>
-  <data name="fdRenameTitle" xml:space="preserve">
-    <value>名前を変更</value>
+  <data name="btnNo" xml:space="preserve">
+    <value>いいえ (_N)</value>
   </data>
   </data>
   <data name="fdRenameFailedTitle" xml:space="preserve">
   <data name="fdRenameFailedTitle" xml:space="preserve">
     <value>変更失敗</value>
     <value>変更失敗</value>
   </data>
   </data>
-  <data name="fdDeleteFailedTitle" xml:space="preserve">
-    <value>削除失敗</value>
-  </data>
-  <data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
-    <value>同じ名前のファイルはすでに存在しました</value>
-  </data>
-  <data name="fdSearchCaption" xml:space="preserve">
-    <value>検索を入力</value>
-  </data>
-  <data name="fdWrongFileTypeFeedback" xml:space="preserve">
-    <value>ファイルタイプが間違っでいます</value>
+  <data name="fdRenamePrompt" xml:space="preserve">
+    <value>名前:</value>
   </data>
   </data>
-  <data name="fdAnyFiles" xml:space="preserve">
-    <value>任意ファイル</value>
+  <data name="fdRenameTitle" xml:space="preserve">
+    <value>名前を変更</value>
   </data>
   </data>
-  <data name="btnCancel" xml:space="preserve">
-    <value>キャンセル (_C)</value>
+  <data name="btnYes" xml:space="preserve">
+    <value>はい (_Y)</value>
   </data>
   </data>
-  <data name="btnOk" xml:space="preserve">
-    <value>OK (_O)</value>
+  <data name="fdExisting" xml:space="preserve">
+    <value>既存</value>
   </data>
   </data>
   <data name="btnOpen" xml:space="preserve">
   <data name="btnOpen" xml:space="preserve">
     <value>開く (_O)</value>
     <value>開く (_O)</value>
@@ -255,6 +249,12 @@
   <data name="btnSaveAs" xml:space="preserve">
   <data name="btnSaveAs" xml:space="preserve">
     <value>名前を付けて保存 (_S)</value>
     <value>名前を付けて保存 (_S)</value>
   </data>
   </data>
+  <data name="btnOk" xml:space="preserve">
+    <value>OK (_O)</value>
+  </data>
+  <data name="btnCancel" xml:space="preserve">
+    <value>キャンセル (_C)</value>
+  </data>
   <data name="fdCtxDelete" xml:space="preserve">
   <data name="fdCtxDelete" xml:space="preserve">
     <value>削除 (_D)</value>
     <value>削除 (_D)</value>
   </data>
   </data>
@@ -276,4 +276,7 @@
   <data name="dpTitle" xml:space="preserve">
   <data name="dpTitle" xml:space="preserve">
     <value>日付ピッカー</value>
     <value>日付ピッカー</value>
   </data>
   </data>
+  <data name="ctxColors" xml:space="preserve">
+    <value>絵の具 (_L)</value>
+  </data>
 </root>
 </root>

+ 16 - 13
Terminal.Gui/Resources/Strings.pt-PT.resx

@@ -117,27 +117,27 @@
   <resheader name="writer">
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   </resheader>
+  <data name="ctxSelectAll" xml:space="preserve">
+    <value>_Selecionar Tudo</value>
+  </data>
+  <data name="ctxDeleteAll" xml:space="preserve">
+    <value>_Apagar Tudo</value>
+  </data>
   <data name="ctxCopy" xml:space="preserve">
   <data name="ctxCopy" xml:space="preserve">
     <value>_Copiar</value>
     <value>_Copiar</value>
   </data>
   </data>
   <data name="ctxCut" xml:space="preserve">
   <data name="ctxCut" xml:space="preserve">
     <value>Cor_tar</value>
     <value>Cor_tar</value>
   </data>
   </data>
-  <data name="ctxDeleteAll" xml:space="preserve">
-    <value>_Apagar Tudo</value>
-  </data>
   <data name="ctxPaste" xml:space="preserve">
   <data name="ctxPaste" xml:space="preserve">
     <value>Co_lar</value>
     <value>Co_lar</value>
   </data>
   </data>
-  <data name="ctxRedo" xml:space="preserve">
-    <value>_Refazer</value>
-  </data>
-  <data name="ctxSelectAll" xml:space="preserve">
-    <value>_Selecionar Tudo</value>
-  </data>
   <data name="ctxUndo" xml:space="preserve">
   <data name="ctxUndo" xml:space="preserve">
     <value>_Desfazer</value>
     <value>_Desfazer</value>
   </data>
   </data>
+  <data name="ctxRedo" xml:space="preserve">
+    <value>_Refazer</value>
+  </data>
   <data name="fdDirectory" xml:space="preserve">
   <data name="fdDirectory" xml:space="preserve">
     <value>Diretório</value>
     <value>Diretório</value>
   </data>
   </data>
@@ -168,16 +168,19 @@
   <data name="wzNext" xml:space="preserve">
   <data name="wzNext" xml:space="preserve">
     <value>S_eguir...</value>
     <value>S_eguir...</value>
   </data>
   </data>
-  <data name="btnSaveAs" xml:space="preserve">
-    <value>Guardar como</value>
+  <data name="btnOpen" xml:space="preserve">
+    <value>Abrir</value>
   </data>
   </data>
   <data name="btnSave" xml:space="preserve">
   <data name="btnSave" xml:space="preserve">
     <value>Guardar</value>
     <value>Guardar</value>
   </data>
   </data>
-  <data name="btnOpen" xml:space="preserve">
-    <value>Abrir</value>
+  <data name="btnSaveAs" xml:space="preserve">
+    <value>Guardar como</value>
   </data>
   </data>
   <data name="dpTitle" xml:space="preserve">
   <data name="dpTitle" xml:space="preserve">
     <value>Seletor de Data</value>
     <value>Seletor de Data</value>
   </data>
   </data>
+  <data name="ctxColors" xml:space="preserve">
+    <value>Co_res</value>
+  </data>
 </root>
 </root>

+ 264 - 261
Terminal.Gui/Resources/Strings.resx

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <root>
 <root>
-    <!-- 
+  <!-- 
     Microsoft ResX Schema 
     Microsoft ResX Schema 
     
     
     Version 2.0
     Version 2.0
@@ -59,663 +59,666 @@
             : using a System.ComponentModel.TypeConverter
             : using a System.ComponentModel.TypeConverter
             : and then encoded with base64 encoding.
             : and then encoded with base64 encoding.
     -->
     -->
-    <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-        <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-        <xsd:element name="root" msdata:IsDataSet="true">
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
             <xsd:complexType>
             <xsd:complexType>
-                <xsd:choice maxOccurs="unbounded">
-                    <xsd:element name="metadata">
-                        <xsd:complexType>
-                            <xsd:sequence>
-                                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-                            </xsd:sequence>
-                            <xsd:attribute name="name" use="required" type="xsd:string" />
-                            <xsd:attribute name="type" type="xsd:string" />
-                            <xsd:attribute name="mimetype" type="xsd:string" />
-                            <xsd:attribute ref="xml:space" />
-                        </xsd:complexType>
-                    </xsd:element>
-                    <xsd:element name="assembly">
-                        <xsd:complexType>
-                            <xsd:attribute name="alias" type="xsd:string" />
-                            <xsd:attribute name="name" type="xsd:string" />
-                        </xsd:complexType>
-                    </xsd:element>
-                    <xsd:element name="data">
-                        <xsd:complexType>
-                            <xsd:sequence>
-                                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-                            </xsd:sequence>
-                            <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-                            <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-                            <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-                            <xsd:attribute ref="xml:space" />
-                        </xsd:complexType>
-                    </xsd:element>
-                    <xsd:element name="resheader">
-                        <xsd:complexType>
-                            <xsd:sequence>
-                                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                            </xsd:sequence>
-                            <xsd:attribute name="name" type="xsd:string" use="required" />
-                        </xsd:complexType>
-                    </xsd:element>
-                </xsd:choice>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
             </xsd:complexType>
             </xsd:complexType>
-        </xsd:element>
-    </xsd:schema>
-    <resheader name="resmimetype">
-        <value>text/microsoft-resx</value>
-    </resheader>
-    <resheader name="version">
-        <value>2.0</value>
-    </resheader>
-    <resheader name="reader">
-        <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-    </resheader>
-    <resheader name="writer">
-        <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-    </resheader>
-    <data name="ctxSelectAll" xml:space="preserve">
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="ctxSelectAll" xml:space="preserve">
     <value>_Select All</value>
     <value>_Select All</value>
   </data>
   </data>
-    <data name="ctxDeleteAll" xml:space="preserve">
+  <data name="ctxDeleteAll" xml:space="preserve">
     <value>_Delete All</value>
     <value>_Delete All</value>
   </data>
   </data>
-    <data name="ctxCopy" xml:space="preserve">
+  <data name="ctxCopy" xml:space="preserve">
     <value>_Copy</value>
     <value>_Copy</value>
   </data>
   </data>
-    <data name="ctxCut" xml:space="preserve">
+  <data name="ctxCut" xml:space="preserve">
     <value>Cu_t</value>
     <value>Cu_t</value>
   </data>
   </data>
-    <data name="ctxPaste" xml:space="preserve">
+  <data name="ctxPaste" xml:space="preserve">
     <value>_Paste</value>
     <value>_Paste</value>
   </data>
   </data>
-    <data name="ctxUndo" xml:space="preserve">
+  <data name="ctxUndo" xml:space="preserve">
     <value>_Undo</value>
     <value>_Undo</value>
   </data>
   </data>
-    <data name="ctxRedo" xml:space="preserve">
+  <data name="ctxRedo" xml:space="preserve">
     <value>_Redo</value>
     <value>_Redo</value>
   </data>
   </data>
-    <data name="fdDirectory" xml:space="preserve">
+  <data name="fdDirectory" xml:space="preserve">
     <value>Directory</value>
     <value>Directory</value>
   </data>
   </data>
-    <data name="fdFile" xml:space="preserve">
+  <data name="fdFile" xml:space="preserve">
     <value>File</value>
     <value>File</value>
   </data>
   </data>
-    <data name="fdSave" xml:space="preserve">
+  <data name="fdSave" xml:space="preserve">
     <value>Save</value>
     <value>Save</value>
   </data>
   </data>
-    <data name="fdSaveAs" xml:space="preserve">
+  <data name="fdSaveAs" xml:space="preserve">
     <value>Save as</value>
     <value>Save as</value>
   </data>
   </data>
-    <data name="fdOpen" xml:space="preserve">
+  <data name="fdOpen" xml:space="preserve">
     <value>Open</value>
     <value>Open</value>
   </data>
   </data>
-    <data name="fdSelectFolder" xml:space="preserve">
+  <data name="fdSelectFolder" xml:space="preserve">
     <value>Select folder</value>
     <value>Select folder</value>
   </data>
   </data>
-    <data name="fdSelectMixed" xml:space="preserve">
+  <data name="fdSelectMixed" xml:space="preserve">
     <value>Select Mixed</value>
     <value>Select Mixed</value>
   </data>
   </data>
-    <data name="wzBack" xml:space="preserve">
+  <data name="wzBack" xml:space="preserve">
     <value>_Back</value>
     <value>_Back</value>
   </data>
   </data>
-    <data name="wzFinish" xml:space="preserve">
+  <data name="wzFinish" xml:space="preserve">
     <value>Fi_nish</value>
     <value>Fi_nish</value>
   </data>
   </data>
-    <data name="wzNext" xml:space="preserve">
+  <data name="wzNext" xml:space="preserve">
     <value>_Next...</value>
     <value>_Next...</value>
   </data>
   </data>
-    <data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
+  <data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
     <value>Directory already exists with that name</value>
     <value>Directory already exists with that name</value>
     <comment>When trying to save a file with a name already taken by a directory</comment>
     <comment>When trying to save a file with a name already taken by a directory</comment>
   </data>
   </data>
-    <data name="fdDirectoryMustExistFeedback" xml:space="preserve">
+  <data name="fdDirectoryMustExistFeedback" xml:space="preserve">
     <value>Must select an existing directory</value>
     <value>Must select an existing directory</value>
   </data>
   </data>
-    <data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
+  <data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
     <value>File already exists with that name</value>
     <value>File already exists with that name</value>
   </data>
   </data>
-    <data name="fdFileMustExistFeedback" xml:space="preserve">
+  <data name="fdFileMustExistFeedback" xml:space="preserve">
     <value>Must select an existing file</value>
     <value>Must select an existing file</value>
     <comment>When trying to save a directory with a name already used by a file</comment>
     <comment>When trying to save a directory with a name already used by a file</comment>
   </data>
   </data>
-    <data name="fdFilename" xml:space="preserve">
+  <data name="fdFilename" xml:space="preserve">
     <value>Filename</value>
     <value>Filename</value>
   </data>
   </data>
-    <data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
+  <data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
     <value>Must select an existing file or directory</value>
     <value>Must select an existing file or directory</value>
   </data>
   </data>
-    <data name="fdModified" xml:space="preserve">
+  <data name="fdModified" xml:space="preserve">
     <value>Modified</value>
     <value>Modified</value>
   </data>
   </data>
-    <data name="fdPathCaption" xml:space="preserve">
+  <data name="fdPathCaption" xml:space="preserve">
     <value>Enter Path</value>
     <value>Enter Path</value>
   </data>
   </data>
-    <data name="fdSearchCaption" xml:space="preserve">
+  <data name="fdSearchCaption" xml:space="preserve">
     <value>Enter Search</value>
     <value>Enter Search</value>
   </data>
   </data>
-    <data name="fdSize" xml:space="preserve">
+  <data name="fdSize" xml:space="preserve">
     <value>Size</value>
     <value>Size</value>
   </data>
   </data>
-    <data name="fdType" xml:space="preserve">
+  <data name="fdType" xml:space="preserve">
     <value>Type</value>
     <value>Type</value>
   </data>
   </data>
-    <data name="fdWrongFileTypeFeedback" xml:space="preserve">
+  <data name="fdWrongFileTypeFeedback" xml:space="preserve">
     <value>Wrong file type</value>
     <value>Wrong file type</value>
     <comment>When trying to open/save a file that does not match the provided filter (e.g. csv)</comment>
     <comment>When trying to open/save a file that does not match the provided filter (e.g. csv)</comment>
   </data>
   </data>
-    <data name="fdAnyFiles" xml:space="preserve">
+  <data name="fdAnyFiles" xml:space="preserve">
     <value>Any Files</value>
     <value>Any Files</value>
     <comment>Describes an AllowedType that matches anything</comment>
     <comment>Describes an AllowedType that matches anything</comment>
   </data>
   </data>
-    <data name="fdDeleteBody" xml:space="preserve">
+  <data name="fdDeleteBody" xml:space="preserve">
     <value>Are you sure you want to delete '{0}'? This operation is permanent</value>
     <value>Are you sure you want to delete '{0}'? This operation is permanent</value>
   </data>
   </data>
-    <data name="fdDeleteFailedTitle" xml:space="preserve">
+  <data name="fdDeleteFailedTitle" xml:space="preserve">
     <value>Delete Failed</value>
     <value>Delete Failed</value>
   </data>
   </data>
-    <data name="fdDeleteTitle" xml:space="preserve">
+  <data name="fdDeleteTitle" xml:space="preserve">
     <value>Delete {0}</value>
     <value>Delete {0}</value>
   </data>
   </data>
-    <data name="fdNewFailed" xml:space="preserve">
+  <data name="fdNewFailed" xml:space="preserve">
     <value>New Failed</value>
     <value>New Failed</value>
   </data>
   </data>
-    <data name="fdNewTitle" xml:space="preserve">
+  <data name="fdNewTitle" xml:space="preserve">
     <value>New Folder</value>
     <value>New Folder</value>
   </data>
   </data>
-    <data name="btnNo" xml:space="preserve">
+  <data name="btnNo" xml:space="preserve">
     <value>_No</value>
     <value>_No</value>
   </data>
   </data>
-    <data name="fdRenameFailedTitle" xml:space="preserve">
+  <data name="fdRenameFailedTitle" xml:space="preserve">
     <value>Rename Failed</value>
     <value>Rename Failed</value>
   </data>
   </data>
-    <data name="fdRenamePrompt" xml:space="preserve">
+  <data name="fdRenamePrompt" xml:space="preserve">
     <value>Name:</value>
     <value>Name:</value>
   </data>
   </data>
-    <data name="fdRenameTitle" xml:space="preserve">
+  <data name="fdRenameTitle" xml:space="preserve">
     <value>Rename</value>
     <value>Rename</value>
   </data>
   </data>
-    <data name="btnYes" xml:space="preserve">
+  <data name="btnYes" xml:space="preserve">
     <value>_Yes</value>
     <value>_Yes</value>
   </data>
   </data>
-    <data name="fdExisting" xml:space="preserve">
+  <data name="fdExisting" xml:space="preserve">
     <value>Existing</value>
     <value>Existing</value>
   </data>
   </data>
-    <data name="btnOpen" xml:space="preserve">
+  <data name="btnOpen" xml:space="preserve">
     <value>O_pen</value>
     <value>O_pen</value>
   </data>
   </data>
-    <data name="btnSave" xml:space="preserve">
+  <data name="btnSave" xml:space="preserve">
     <value>_Save</value>
     <value>_Save</value>
   </data>
   </data>
-    <data name="btnSaveAs" xml:space="preserve">
+  <data name="btnSaveAs" xml:space="preserve">
     <value>Save _as</value>
     <value>Save _as</value>
   </data>
   </data>
-    <data name="btnOk" xml:space="preserve">
+  <data name="btnOk" xml:space="preserve">
     <value>_OK</value>
     <value>_OK</value>
   </data>
   </data>
-    <data name="btnCancel" xml:space="preserve">
+  <data name="btnCancel" xml:space="preserve">
     <value>_Cancel</value>
     <value>_Cancel</value>
   </data>
   </data>
-    <data name="fdCtxDelete" xml:space="preserve">
+  <data name="fdCtxDelete" xml:space="preserve">
     <value>_Delete</value>
     <value>_Delete</value>
   </data>
   </data>
-    <data name="fdCtxHide" xml:space="preserve">
+  <data name="fdCtxHide" xml:space="preserve">
     <value>_Hide {0}</value>
     <value>_Hide {0}</value>
   </data>
   </data>
-    <data name="fdCtxNew" xml:space="preserve">
+  <data name="fdCtxNew" xml:space="preserve">
     <value>_New</value>
     <value>_New</value>
   </data>
   </data>
-    <data name="fdCtxRename" xml:space="preserve">
+  <data name="fdCtxRename" xml:space="preserve">
     <value>_Rename</value>
     <value>_Rename</value>
   </data>
   </data>
-    <data name="fdCtxSortAsc" xml:space="preserve">
+  <data name="fdCtxSortAsc" xml:space="preserve">
     <value>_Sort {0} ASC</value>
     <value>_Sort {0} ASC</value>
   </data>
   </data>
-    <data name="fdCtxSortDesc" xml:space="preserve">
+  <data name="fdCtxSortDesc" xml:space="preserve">
     <value>_Sort {0} DESC</value>
     <value>_Sort {0} DESC</value>
   </data>
   </data>
-    <data name="dpTitle" xml:space="preserve">
+  <data name="dpTitle" xml:space="preserve">
     <value>Date Picker</value>
     <value>Date Picker</value>
   </data>
   </data>
-    <data name="#F0F8FF" xml:space="preserve">
+  <data name="#F0F8FF" xml:space="preserve">
     <value>AliceBlue</value>
     <value>AliceBlue</value>
   </data>
   </data>
-    <data name="#FAEBD7" xml:space="preserve">
+  <data name="#FAEBD7" xml:space="preserve">
     <value>AntiqueWhite</value>
     <value>AntiqueWhite</value>
   </data>
   </data>
-    <data name="#7FFFD4" xml:space="preserve">
+  <data name="#7FFFD4" xml:space="preserve">
     <value>Aquamarine</value>
     <value>Aquamarine</value>
   </data>
   </data>
-    <data name="#F0FFFF" xml:space="preserve">
+  <data name="#F0FFFF" xml:space="preserve">
     <value>Azure</value>
     <value>Azure</value>
   </data>
   </data>
-    <data name="#F5F5DC" xml:space="preserve">
+  <data name="#F5F5DC" xml:space="preserve">
     <value>Beige</value>
     <value>Beige</value>
   </data>
   </data>
-    <data name="#FFE4C4" xml:space="preserve">
+  <data name="#FFE4C4" xml:space="preserve">
     <value>Bisque</value>
     <value>Bisque</value>
   </data>
   </data>
-    <data name="#000000" xml:space="preserve">
+  <data name="#000000" xml:space="preserve">
     <value>Black</value>
     <value>Black</value>
   </data>
   </data>
-    <data name="#FFEBCD" xml:space="preserve">
+  <data name="#FFEBCD" xml:space="preserve">
     <value>BlanchedAlmond</value>
     <value>BlanchedAlmond</value>
   </data>
   </data>
-    <data name="#0000FF" xml:space="preserve">
+  <data name="#0000FF" xml:space="preserve">
     <value>Blue</value>
     <value>Blue</value>
   </data>
   </data>
-    <data name="#8A2BE2" xml:space="preserve">
+  <data name="#8A2BE2" xml:space="preserve">
     <value>BlueViolet</value>
     <value>BlueViolet</value>
   </data>
   </data>
-    <data name="#A52A2A" xml:space="preserve">
+  <data name="#A52A2A" xml:space="preserve">
     <value>Brown</value>
     <value>Brown</value>
   </data>
   </data>
-    <data name="#DEB887" xml:space="preserve">
+  <data name="#DEB887" xml:space="preserve">
     <value>BurlyWood</value>
     <value>BurlyWood</value>
   </data>
   </data>
-    <data name="#5F9EA0" xml:space="preserve">
+  <data name="#5F9EA0" xml:space="preserve">
     <value>CadetBlue</value>
     <value>CadetBlue</value>
   </data>
   </data>
-    <data name="#7FFF00" xml:space="preserve">
+  <data name="#7FFF00" xml:space="preserve">
     <value>Chartreuse</value>
     <value>Chartreuse</value>
   </data>
   </data>
-    <data name="#D2691E" xml:space="preserve">
+  <data name="#D2691E" xml:space="preserve">
     <value>Chocolate</value>
     <value>Chocolate</value>
   </data>
   </data>
-    <data name="#FF7F50" xml:space="preserve">
+  <data name="#FF7F50" xml:space="preserve">
     <value>Coral</value>
     <value>Coral</value>
   </data>
   </data>
-    <data name="#6495ED" xml:space="preserve">
+  <data name="#6495ED" xml:space="preserve">
     <value>CornflowerBlue</value>
     <value>CornflowerBlue</value>
   </data>
   </data>
-    <data name="#FFF8DC" xml:space="preserve">
+  <data name="#FFF8DC" xml:space="preserve">
     <value>Cornsilk</value>
     <value>Cornsilk</value>
   </data>
   </data>
-    <data name="#DC143C" xml:space="preserve">
+  <data name="#DC143C" xml:space="preserve">
     <value>Crimson</value>
     <value>Crimson</value>
   </data>
   </data>
-    <data name="#00FFFF" xml:space="preserve">
+  <data name="#00FFFF" xml:space="preserve">
     <value>Cyan</value>
     <value>Cyan</value>
   </data>
   </data>
-    <data name="#00008B" xml:space="preserve">
+  <data name="#00008B" xml:space="preserve">
     <value>DarkBlue</value>
     <value>DarkBlue</value>
   </data>
   </data>
-    <data name="#008B8B" xml:space="preserve">
+  <data name="#008B8B" xml:space="preserve">
     <value>DarkCyan</value>
     <value>DarkCyan</value>
   </data>
   </data>
-    <data name="#B8860B" xml:space="preserve">
+  <data name="#B8860B" xml:space="preserve">
     <value>DarkGoldenRod</value>
     <value>DarkGoldenRod</value>
   </data>
   </data>
-    <data name="#A9A9A9" xml:space="preserve">
+  <data name="#A9A9A9" xml:space="preserve">
     <value>DarkGrey</value>
     <value>DarkGrey</value>
   </data>
   </data>
-    <data name="#006400" xml:space="preserve">
+  <data name="#006400" xml:space="preserve">
     <value>DarkGreen</value>
     <value>DarkGreen</value>
   </data>
   </data>
-    <data name="#BDB76B" xml:space="preserve">
+  <data name="#BDB76B" xml:space="preserve">
     <value>DarkKhaki</value>
     <value>DarkKhaki</value>
   </data>
   </data>
-    <data name="#8B008B" xml:space="preserve">
+  <data name="#8B008B" xml:space="preserve">
     <value>DarkMagenta</value>
     <value>DarkMagenta</value>
   </data>
   </data>
-    <data name="#556B2F" xml:space="preserve">
+  <data name="#556B2F" xml:space="preserve">
     <value>DarkOliveGreen</value>
     <value>DarkOliveGreen</value>
   </data>
   </data>
-    <data name="#FF8C00" xml:space="preserve">
+  <data name="#FF8C00" xml:space="preserve">
     <value>DarkOrange</value>
     <value>DarkOrange</value>
   </data>
   </data>
-    <data name="#9932CC" xml:space="preserve">
+  <data name="#9932CC" xml:space="preserve">
     <value>DarkOrchid</value>
     <value>DarkOrchid</value>
   </data>
   </data>
-    <data name="#8B0000" xml:space="preserve">
+  <data name="#8B0000" xml:space="preserve">
     <value>DarkRed</value>
     <value>DarkRed</value>
   </data>
   </data>
-    <data name="#E9967A" xml:space="preserve">
+  <data name="#E9967A" xml:space="preserve">
     <value>DarkSalmon</value>
     <value>DarkSalmon</value>
   </data>
   </data>
-    <data name="#8FBC8F" xml:space="preserve">
+  <data name="#8FBC8F" xml:space="preserve">
     <value>DarkSeaGreen</value>
     <value>DarkSeaGreen</value>
   </data>
   </data>
-    <data name="#483D8B" xml:space="preserve">
+  <data name="#483D8B" xml:space="preserve">
     <value>DarkSlateBlue</value>
     <value>DarkSlateBlue</value>
   </data>
   </data>
-    <data name="#2F4F4F" xml:space="preserve">
+  <data name="#2F4F4F" xml:space="preserve">
     <value>DarkSlateGrey</value>
     <value>DarkSlateGrey</value>
   </data>
   </data>
-    <data name="#00CED1" xml:space="preserve">
+  <data name="#00CED1" xml:space="preserve">
     <value>DarkTurquoise</value>
     <value>DarkTurquoise</value>
   </data>
   </data>
-    <data name="#9400D3" xml:space="preserve">
+  <data name="#9400D3" xml:space="preserve">
     <value>DarkViolet</value>
     <value>DarkViolet</value>
   </data>
   </data>
-    <data name="#FF1493" xml:space="preserve">
+  <data name="#FF1493" xml:space="preserve">
     <value>DeepPink</value>
     <value>DeepPink</value>
   </data>
   </data>
-    <data name="#00BFFF" xml:space="preserve">
+  <data name="#00BFFF" xml:space="preserve">
     <value>DeepSkyBlue</value>
     <value>DeepSkyBlue</value>
   </data>
   </data>
-    <data name="#696969" xml:space="preserve">
+  <data name="#696969" xml:space="preserve">
     <value>DimGray</value>
     <value>DimGray</value>
   </data>
   </data>
-    <data name="#1E90FF" xml:space="preserve">
+  <data name="#1E90FF" xml:space="preserve">
     <value>DodgerBlue</value>
     <value>DodgerBlue</value>
   </data>
   </data>
-    <data name="#B22222" xml:space="preserve">
+  <data name="#B22222" xml:space="preserve">
     <value>FireBrick</value>
     <value>FireBrick</value>
   </data>
   </data>
-    <data name="#FFFAF0" xml:space="preserve">
+  <data name="#FFFAF0" xml:space="preserve">
     <value>FloralWhite</value>
     <value>FloralWhite</value>
   </data>
   </data>
-    <data name="#228B22" xml:space="preserve">
+  <data name="#228B22" xml:space="preserve">
     <value>ForestGreen</value>
     <value>ForestGreen</value>
   </data>
   </data>
-    <data name="#DCDCDC" xml:space="preserve">
+  <data name="#DCDCDC" xml:space="preserve">
     <value>Gainsboro</value>
     <value>Gainsboro</value>
   </data>
   </data>
-    <data name="#F8F8FF" xml:space="preserve">
+  <data name="#F8F8FF" xml:space="preserve">
     <value>GhostWhite</value>
     <value>GhostWhite</value>
   </data>
   </data>
-    <data name="#FFD700" xml:space="preserve">
+  <data name="#FFD700" xml:space="preserve">
     <value>Gold</value>
     <value>Gold</value>
   </data>
   </data>
-    <data name="#DAA520" xml:space="preserve">
+  <data name="#DAA520" xml:space="preserve">
     <value>GoldenRod</value>
     <value>GoldenRod</value>
   </data>
   </data>
-    <data name="#808080" xml:space="preserve">
+  <data name="#808080" xml:space="preserve">
     <value>Gray</value>
     <value>Gray</value>
   </data>
   </data>
-    <data name="#008000" xml:space="preserve">
+  <data name="#008000" xml:space="preserve">
     <value>Green</value>
     <value>Green</value>
   </data>
   </data>
-    <data name="#ADFF2F" xml:space="preserve">
+  <data name="#ADFF2F" xml:space="preserve">
     <value>GreenYellow</value>
     <value>GreenYellow</value>
   </data>
   </data>
-    <data name="#F0FFF0" xml:space="preserve">
+  <data name="#F0FFF0" xml:space="preserve">
     <value>HoneyDew</value>
     <value>HoneyDew</value>
   </data>
   </data>
-    <data name="#FF69B4" xml:space="preserve">
+  <data name="#FF69B4" xml:space="preserve">
     <value>HotPink</value>
     <value>HotPink</value>
   </data>
   </data>
-    <data name="#CD5C5C" xml:space="preserve">
+  <data name="#CD5C5C" xml:space="preserve">
     <value>IndianRed</value>
     <value>IndianRed</value>
   </data>
   </data>
-    <data name="#4B0082" xml:space="preserve">
+  <data name="#4B0082" xml:space="preserve">
     <value>Indigo</value>
     <value>Indigo</value>
   </data>
   </data>
-    <data name="#FFFFF0" xml:space="preserve">
+  <data name="#FFFFF0" xml:space="preserve">
     <value>Ivory</value>
     <value>Ivory</value>
   </data>
   </data>
-    <data name="#F0E68C" xml:space="preserve">
+  <data name="#F0E68C" xml:space="preserve">
     <value>Khaki</value>
     <value>Khaki</value>
   </data>
   </data>
-    <data name="#E6E6FA" xml:space="preserve">
+  <data name="#E6E6FA" xml:space="preserve">
     <value>Lavender</value>
     <value>Lavender</value>
   </data>
   </data>
-    <data name="#FFF0F5" xml:space="preserve">
+  <data name="#FFF0F5" xml:space="preserve">
     <value>LavenderBlush</value>
     <value>LavenderBlush</value>
   </data>
   </data>
-    <data name="#7CFC00" xml:space="preserve">
+  <data name="#7CFC00" xml:space="preserve">
     <value>LawnGreen</value>
     <value>LawnGreen</value>
   </data>
   </data>
-    <data name="#FFFACD" xml:space="preserve">
+  <data name="#FFFACD" xml:space="preserve">
     <value>LemonChiffon</value>
     <value>LemonChiffon</value>
   </data>
   </data>
-    <data name="#ADD8E6" xml:space="preserve">
+  <data name="#ADD8E6" xml:space="preserve">
     <value>LightBlue</value>
     <value>LightBlue</value>
   </data>
   </data>
-    <data name="#F08080" xml:space="preserve">
+  <data name="#F08080" xml:space="preserve">
     <value>LightCoral</value>
     <value>LightCoral</value>
   </data>
   </data>
-    <data name="#E0FFFF" xml:space="preserve">
+  <data name="#E0FFFF" xml:space="preserve">
     <value>LightCyan</value>
     <value>LightCyan</value>
   </data>
   </data>
-    <data name="#FAFAD2" xml:space="preserve">
+  <data name="#FAFAD2" xml:space="preserve">
     <value>LightGoldenRodYellow</value>
     <value>LightGoldenRodYellow</value>
   </data>
   </data>
-    <data name="#D3D3D3" xml:space="preserve">
+  <data name="#D3D3D3" xml:space="preserve">
     <value>LightGray</value>
     <value>LightGray</value>
   </data>
   </data>
-    <data name="#90EE90" xml:space="preserve">
+  <data name="#90EE90" xml:space="preserve">
     <value>LightGreen</value>
     <value>LightGreen</value>
   </data>
   </data>
-    <data name="#FFB6C1" xml:space="preserve">
+  <data name="#FFB6C1" xml:space="preserve">
     <value>LightPink</value>
     <value>LightPink</value>
   </data>
   </data>
-    <data name="#FFA07A" xml:space="preserve">
+  <data name="#FFA07A" xml:space="preserve">
     <value>LightSalmon</value>
     <value>LightSalmon</value>
   </data>
   </data>
-    <data name="#20B2AA" xml:space="preserve">
+  <data name="#20B2AA" xml:space="preserve">
     <value>LightSeaGreen</value>
     <value>LightSeaGreen</value>
   </data>
   </data>
-    <data name="#87CEFA" xml:space="preserve">
+  <data name="#87CEFA" xml:space="preserve">
     <value>LightSkyBlue</value>
     <value>LightSkyBlue</value>
   </data>
   </data>
-    <data name="#778899" xml:space="preserve">
+  <data name="#778899" xml:space="preserve">
     <value>LightSlateGrey</value>
     <value>LightSlateGrey</value>
   </data>
   </data>
-    <data name="#B0C4DE" xml:space="preserve">
+  <data name="#B0C4DE" xml:space="preserve">
     <value>LightSteelBlue</value>
     <value>LightSteelBlue</value>
   </data>
   </data>
-    <data name="#FFFFE0" xml:space="preserve">
+  <data name="#FFFFE0" xml:space="preserve">
     <value>LightYellow</value>
     <value>LightYellow</value>
   </data>
   </data>
-    <data name="#00FF00" xml:space="preserve">
+  <data name="#00FF00" xml:space="preserve">
     <value>Lime</value>
     <value>Lime</value>
   </data>
   </data>
-    <data name="#32CD32" xml:space="preserve">
+  <data name="#32CD32" xml:space="preserve">
     <value>LimeGreen</value>
     <value>LimeGreen</value>
   </data>
   </data>
-    <data name="#FAF0E6" xml:space="preserve">
+  <data name="#FAF0E6" xml:space="preserve">
     <value>Linen</value>
     <value>Linen</value>
   </data>
   </data>
-    <data name="#FF00FF" xml:space="preserve">
+  <data name="#FF00FF" xml:space="preserve">
     <value>Magenta</value>
     <value>Magenta</value>
   </data>
   </data>
-    <data name="#800000" xml:space="preserve">
+  <data name="#800000" xml:space="preserve">
     <value>Maroon</value>
     <value>Maroon</value>
   </data>
   </data>
-    <data name="#66CDAA" xml:space="preserve">
+  <data name="#66CDAA" xml:space="preserve">
     <value>MediumAquaMarine</value>
     <value>MediumAquaMarine</value>
   </data>
   </data>
-    <data name="#0000CD" xml:space="preserve">
+  <data name="#0000CD" xml:space="preserve">
     <value>MediumBlue</value>
     <value>MediumBlue</value>
   </data>
   </data>
-    <data name="#BA55D3" xml:space="preserve">
+  <data name="#BA55D3" xml:space="preserve">
     <value>MediumOrchid</value>
     <value>MediumOrchid</value>
   </data>
   </data>
-    <data name="#9370DB" xml:space="preserve">
+  <data name="#9370DB" xml:space="preserve">
     <value>MediumPurple</value>
     <value>MediumPurple</value>
   </data>
   </data>
-    <data name="#3CB371" xml:space="preserve">
+  <data name="#3CB371" xml:space="preserve">
     <value>MediumSeaGreen</value>
     <value>MediumSeaGreen</value>
   </data>
   </data>
-    <data name="#7B68EE" xml:space="preserve">
+  <data name="#7B68EE" xml:space="preserve">
     <value>MediumSlateBlue</value>
     <value>MediumSlateBlue</value>
   </data>
   </data>
-    <data name="#00FA9A" xml:space="preserve">
+  <data name="#00FA9A" xml:space="preserve">
     <value>MediumSpringGreen</value>
     <value>MediumSpringGreen</value>
   </data>
   </data>
-    <data name="#48D1CC" xml:space="preserve">
+  <data name="#48D1CC" xml:space="preserve">
     <value>MediumTurquoise</value>
     <value>MediumTurquoise</value>
   </data>
   </data>
-    <data name="#C71585" xml:space="preserve">
+  <data name="#C71585" xml:space="preserve">
     <value>MediumVioletRed</value>
     <value>MediumVioletRed</value>
   </data>
   </data>
-    <data name="#191970" xml:space="preserve">
+  <data name="#191970" xml:space="preserve">
     <value>MidnightBlue</value>
     <value>MidnightBlue</value>
   </data>
   </data>
-    <data name="#F5FFFA" xml:space="preserve">
+  <data name="#F5FFFA" xml:space="preserve">
     <value>MintCream</value>
     <value>MintCream</value>
   </data>
   </data>
-    <data name="#FFE4E1" xml:space="preserve">
+  <data name="#FFE4E1" xml:space="preserve">
     <value>MistyRose</value>
     <value>MistyRose</value>
   </data>
   </data>
-    <data name="#FFE4B5" xml:space="preserve">
+  <data name="#FFE4B5" xml:space="preserve">
     <value>Moccasin</value>
     <value>Moccasin</value>
   </data>
   </data>
-    <data name="#FFDEAD" xml:space="preserve">
+  <data name="#FFDEAD" xml:space="preserve">
     <value>NavajoWhite</value>
     <value>NavajoWhite</value>
   </data>
   </data>
-    <data name="#000080" xml:space="preserve">
+  <data name="#000080" xml:space="preserve">
     <value>Navy</value>
     <value>Navy</value>
   </data>
   </data>
-    <data name="#FDF5E6" xml:space="preserve">
+  <data name="#FDF5E6" xml:space="preserve">
     <value>OldLace</value>
     <value>OldLace</value>
   </data>
   </data>
-    <data name="#808000" xml:space="preserve">
+  <data name="#808000" xml:space="preserve">
     <value>Olive</value>
     <value>Olive</value>
   </data>
   </data>
-    <data name="#6B8E23" xml:space="preserve">
+  <data name="#6B8E23" xml:space="preserve">
     <value>OliveDrab</value>
     <value>OliveDrab</value>
   </data>
   </data>
-    <data name="#FFA500" xml:space="preserve">
+  <data name="#FFA500" xml:space="preserve">
     <value>Orange</value>
     <value>Orange</value>
   </data>
   </data>
-    <data name="#FF4500" xml:space="preserve">
+  <data name="#FF4500" xml:space="preserve">
     <value>OrangeRed</value>
     <value>OrangeRed</value>
   </data>
   </data>
-    <data name="#DA70D6" xml:space="preserve">
+  <data name="#DA70D6" xml:space="preserve">
     <value>Orchid</value>
     <value>Orchid</value>
   </data>
   </data>
-    <data name="#EEE8AA" xml:space="preserve">
+  <data name="#EEE8AA" xml:space="preserve">
     <value>PaleGoldenRod</value>
     <value>PaleGoldenRod</value>
   </data>
   </data>
-    <data name="#98FB98" xml:space="preserve">
+  <data name="#98FB98" xml:space="preserve">
     <value>PaleGreen</value>
     <value>PaleGreen</value>
   </data>
   </data>
-    <data name="#AFEEEE" xml:space="preserve">
+  <data name="#AFEEEE" xml:space="preserve">
     <value>PaleTurquoise</value>
     <value>PaleTurquoise</value>
   </data>
   </data>
-    <data name="#DB7093" xml:space="preserve">
+  <data name="#DB7093" xml:space="preserve">
     <value>PaleVioletRed</value>
     <value>PaleVioletRed</value>
   </data>
   </data>
-    <data name="#FFEFD5" xml:space="preserve">
+  <data name="#FFEFD5" xml:space="preserve">
     <value>PapayaWhip</value>
     <value>PapayaWhip</value>
   </data>
   </data>
-    <data name="#FFDAB9" xml:space="preserve">
+  <data name="#FFDAB9" xml:space="preserve">
     <value>PeachPuff</value>
     <value>PeachPuff</value>
   </data>
   </data>
-    <data name="#CD853F" xml:space="preserve">
+  <data name="#CD853F" xml:space="preserve">
     <value>Peru</value>
     <value>Peru</value>
   </data>
   </data>
-    <data name="#FFC0CB" xml:space="preserve">
+  <data name="#FFC0CB" xml:space="preserve">
     <value>Pink</value>
     <value>Pink</value>
   </data>
   </data>
-    <data name="#DDA0DD" xml:space="preserve">
+  <data name="#DDA0DD" xml:space="preserve">
     <value>Plum</value>
     <value>Plum</value>
   </data>
   </data>
-    <data name="#B0E0E6" xml:space="preserve">
+  <data name="#B0E0E6" xml:space="preserve">
     <value>PowderBlue</value>
     <value>PowderBlue</value>
   </data>
   </data>
-    <data name="#800080" xml:space="preserve">
+  <data name="#800080" xml:space="preserve">
     <value>Purple</value>
     <value>Purple</value>
   </data>
   </data>
-    <data name="#663399" xml:space="preserve">
+  <data name="#663399" xml:space="preserve">
     <value>RebeccaPurple</value>
     <value>RebeccaPurple</value>
   </data>
   </data>
-    <data name="#FF0000" xml:space="preserve">
+  <data name="#FF0000" xml:space="preserve">
     <value>Red</value>
     <value>Red</value>
   </data>
   </data>
-    <data name="#BC8F8F" xml:space="preserve">
+  <data name="#BC8F8F" xml:space="preserve">
     <value>RosyBrown</value>
     <value>RosyBrown</value>
   </data>
   </data>
-    <data name="#4169E1" xml:space="preserve">
+  <data name="#4169E1" xml:space="preserve">
     <value>RoyalBlue</value>
     <value>RoyalBlue</value>
   </data>
   </data>
-    <data name="#8B4513" xml:space="preserve">
+  <data name="#8B4513" xml:space="preserve">
     <value>SaddleBrown</value>
     <value>SaddleBrown</value>
   </data>
   </data>
-    <data name="#FA8072" xml:space="preserve">
+  <data name="#FA8072" xml:space="preserve">
     <value>Salmon</value>
     <value>Salmon</value>
   </data>
   </data>
-    <data name="#F4A460" xml:space="preserve">
+  <data name="#F4A460" xml:space="preserve">
     <value>SandyBrown</value>
     <value>SandyBrown</value>
   </data>
   </data>
-    <data name="#2E8B57" xml:space="preserve">
+  <data name="#2E8B57" xml:space="preserve">
     <value>SeaGreen</value>
     <value>SeaGreen</value>
   </data>
   </data>
-    <data name="#FFF5EE" xml:space="preserve">
+  <data name="#FFF5EE" xml:space="preserve">
     <value>SeaShell</value>
     <value>SeaShell</value>
   </data>
   </data>
-    <data name="#A0522D" xml:space="preserve">
+  <data name="#A0522D" xml:space="preserve">
     <value>Sienna</value>
     <value>Sienna</value>
   </data>
   </data>
-    <data name="#C0C0C0" xml:space="preserve">
+  <data name="#C0C0C0" xml:space="preserve">
     <value>Silver</value>
     <value>Silver</value>
   </data>
   </data>
-    <data name="#87CEEB" xml:space="preserve">
+  <data name="#87CEEB" xml:space="preserve">
     <value>SkyBlue</value>
     <value>SkyBlue</value>
   </data>
   </data>
-    <data name="#6A5ACD" xml:space="preserve">
+  <data name="#6A5ACD" xml:space="preserve">
     <value>SlateBlue</value>
     <value>SlateBlue</value>
   </data>
   </data>
-    <data name="#708090" xml:space="preserve">
+  <data name="#708090" xml:space="preserve">
     <value>SlateGray</value>
     <value>SlateGray</value>
   </data>
   </data>
-    <data name="#FFFAFA" xml:space="preserve">
+  <data name="#FFFAFA" xml:space="preserve">
     <value>Snow</value>
     <value>Snow</value>
   </data>
   </data>
-    <data name="#00FF7F" xml:space="preserve">
+  <data name="#00FF7F" xml:space="preserve">
     <value>SpringGreen</value>
     <value>SpringGreen</value>
   </data>
   </data>
-    <data name="#4682B4" xml:space="preserve">
+  <data name="#4682B4" xml:space="preserve">
     <value>SteelBlue</value>
     <value>SteelBlue</value>
   </data>
   </data>
-    <data name="#D2B48C" xml:space="preserve">
+  <data name="#D2B48C" xml:space="preserve">
     <value>Tan</value>
     <value>Tan</value>
   </data>
   </data>
-    <data name="#008080" xml:space="preserve">
+  <data name="#008080" xml:space="preserve">
     <value>Teal</value>
     <value>Teal</value>
   </data>
   </data>
-    <data name="#D8BFD8" xml:space="preserve">
+  <data name="#D8BFD8" xml:space="preserve">
     <value>Thistle</value>
     <value>Thistle</value>
   </data>
   </data>
-    <data name="#FF6347" xml:space="preserve">
+  <data name="#FF6347" xml:space="preserve">
     <value>Tomato</value>
     <value>Tomato</value>
   </data>
   </data>
-    <data name="#40E0D0" xml:space="preserve">
+  <data name="#40E0D0" xml:space="preserve">
     <value>Turquoise</value>
     <value>Turquoise</value>
   </data>
   </data>
-    <data name="#EE82EE" xml:space="preserve">
+  <data name="#EE82EE" xml:space="preserve">
     <value>Violet</value>
     <value>Violet</value>
   </data>
   </data>
-    <data name="#F5DEB3" xml:space="preserve">
+  <data name="#F5DEB3" xml:space="preserve">
     <value>Wheat</value>
     <value>Wheat</value>
   </data>
   </data>
-    <data name="#FFFFFF" xml:space="preserve">
+  <data name="#FFFFFF" xml:space="preserve">
     <value>White</value>
     <value>White</value>
   </data>
   </data>
-    <data name="#F5F5F5" xml:space="preserve">
+  <data name="#F5F5F5" xml:space="preserve">
     <value>WhiteSmoke</value>
     <value>WhiteSmoke</value>
   </data>
   </data>
-    <data name="#FFFF00" xml:space="preserve">
+  <data name="#FFFF00" xml:space="preserve">
     <value>Yellow</value>
     <value>Yellow</value>
   </data>
   </data>
-    <data name="#9ACD32" xml:space="preserve">
+  <data name="#9ACD32" xml:space="preserve">
     <value>YellowGreen</value>
     <value>YellowGreen</value>
   </data>
   </data>
-    <data name="#3B78FF" xml:space="preserve">
+  <data name="#3B78FF" xml:space="preserve">
     <value>BrightBlue</value>
     <value>BrightBlue</value>
   </data>
   </data>
-    <data name="#61D6D6" xml:space="preserve">
+  <data name="#61D6D6" xml:space="preserve">
     <value>BrightCyan</value>
     <value>BrightCyan</value>
   </data>
   </data>
-    <data name="#E74856" xml:space="preserve">
+  <data name="#E74856" xml:space="preserve">
     <value>BrightRed</value>
     <value>BrightRed</value>
-</data>
-    <data name="#16C60C" xml:space="preserve">
+  </data>
+  <data name="#16C60C" xml:space="preserve">
     <value>BrightGreen</value>
     <value>BrightGreen</value>
-</data>
-    <data name="#B4009E" xml:space="preserve">
+  </data>
+  <data name="#B4009E" xml:space="preserve">
     <value>BrightMagenta</value>
     <value>BrightMagenta</value>
-</data>
-    <data name="#F9F1A5" xml:space="preserve">
+  </data>
+  <data name="#F9F1A5" xml:space="preserve">
     <value>BrightYellow</value>
     <value>BrightYellow</value>
-</data>
-    <data name="#767676" xml:space="preserve">
+  </data>
+  <data name="#767676" xml:space="preserve">
     <value>DarkGray</value>
     <value>DarkGray</value>
-</data>
+  </data>
+  <data name="ctxColors" xml:space="preserve">
+    <value>Co_lors</value>
+  </data>
 </root>
 </root>

+ 9 - 6
Terminal.Gui/Resources/Strings.zh-Hans.resx

@@ -153,9 +153,6 @@
   <data name="fdOpen" xml:space="preserve">
   <data name="fdOpen" xml:space="preserve">
     <value>打开</value>
     <value>打开</value>
   </data>
   </data>
-  <data name="wzNext" xml:space="preserve">
-    <value>下一步 (_N)...</value>
-  </data>
   <data name="fdSelectFolder" xml:space="preserve">
   <data name="fdSelectFolder" xml:space="preserve">
     <value>选择文件夹 (_S)</value>
     <value>选择文件夹 (_S)</value>
   </data>
   </data>
@@ -168,6 +165,9 @@
   <data name="wzFinish" xml:space="preserve">
   <data name="wzFinish" xml:space="preserve">
     <value>结束 (_N)</value>
     <value>结束 (_N)</value>
   </data>
   </data>
+  <data name="wzNext" xml:space="preserve">
+    <value>下一步 (_N)...</value>
+  </data>
   <data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
   <data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
     <value>已存在相同名称的目录</value>
     <value>已存在相同名称的目录</value>
   </data>
   </data>
@@ -240,9 +240,6 @@
   <data name="fdExisting" xml:space="preserve">
   <data name="fdExisting" xml:space="preserve">
     <value>已有</value>
     <value>已有</value>
   </data>
   </data>
-  <data name="btnOk" xml:space="preserve">
-    <value>确定 (_O)</value>
-  </data>
   <data name="btnOpen" xml:space="preserve">
   <data name="btnOpen" xml:space="preserve">
     <value>打开 (_O)</value>
     <value>打开 (_O)</value>
   </data>
   </data>
@@ -252,6 +249,9 @@
   <data name="btnSaveAs" xml:space="preserve">
   <data name="btnSaveAs" xml:space="preserve">
     <value>另存为 (_S)</value>
     <value>另存为 (_S)</value>
   </data>
   </data>
+  <data name="btnOk" xml:space="preserve">
+    <value>确定 (_O)</value>
+  </data>
   <data name="btnCancel" xml:space="preserve">
   <data name="btnCancel" xml:space="preserve">
     <value>取消 (_C)</value>
     <value>取消 (_C)</value>
   </data>
   </data>
@@ -276,4 +276,7 @@
   <data name="dpTitle" xml:space="preserve">
   <data name="dpTitle" xml:space="preserve">
     <value>日期选择器</value>
     <value>日期选择器</value>
   </data>
   </data>
+  <data name="ctxColors" xml:space="preserve">
+    <value>旗帜 (_L)</value>
+  </data>
 </root>
 </root>

+ 1 - 1
Terminal.Gui/Terminal.Gui.csproj

@@ -60,7 +60,7 @@
     <!-- Enable Nuget Source Link for github -->
     <!-- Enable Nuget Source Link for github -->
     <PackageReference Include="Microsoft.SourceLink.GitHub" Version="[8,9)" PrivateAssets="all" />
     <PackageReference Include="Microsoft.SourceLink.GitHub" Version="[8,9)" PrivateAssets="all" />
     <PackageReference Include="System.IO.Abstractions" Version="[21.0.22,22)" />
     <PackageReference Include="System.IO.Abstractions" Version="[21.0.22,22)" />
-    <PackageReference Include="System.Text.Json" Version="[8.0.4,9)" />
+    <PackageReference Include="System.Text.Json" Version="[8.0.5,9)" />
     <PackageReference Include="Wcwidth" Version="[2,3)" />
     <PackageReference Include="Wcwidth" Version="[2,3)" />
   </ItemGroup>
   </ItemGroup>
   <!-- =================================================================== -->
   <!-- =================================================================== -->

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

@@ -59,7 +59,7 @@ public class AppendAutocomplete : AutocompleteBase
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnMouseEvent (MouseEvent me, bool fromHost = false) { return false; }
+    public override bool OnMouseEvent (MouseEventArgs me, bool fromHost = false) { return false; }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public override bool ProcessKey (Key a)
     public override bool ProcessKey (Key a)

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

@@ -49,7 +49,7 @@ public abstract class AutocompleteBase : IAutocomplete
     public virtual AutocompleteContext Context { get; set; }
     public virtual AutocompleteContext Context { get; set; }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public abstract bool OnMouseEvent (MouseEvent me, bool fromHost = false);
+    public abstract bool OnMouseEvent (MouseEventArgs me, bool fromHost = false);
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public abstract bool ProcessKey (Key a);
     public abstract bool ProcessKey (Key a);

+ 2 - 2
Terminal.Gui/Text/Autocomplete/AutocompleteContext.cs

@@ -7,7 +7,7 @@ namespace Terminal.Gui;
 public class AutocompleteContext
 public class AutocompleteContext
 {
 {
     /// <summary>Creates a new instance of the <see cref="AutocompleteContext"/> class</summary>
     /// <summary>Creates a new instance of the <see cref="AutocompleteContext"/> class</summary>
-    public AutocompleteContext (List<RuneCell> currentLine, int cursorPosition, bool canceled = false)
+    public AutocompleteContext (List<Cell> currentLine, int cursorPosition, bool canceled = false)
     {
     {
         CurrentLine = currentLine;
         CurrentLine = currentLine;
         CursorPosition = cursorPosition;
         CursorPosition = cursorPosition;
@@ -18,7 +18,7 @@ public class AutocompleteContext
     public bool Canceled { get; set; }
     public bool Canceled { get; set; }
 
 
     /// <summary>The text on the current line.</summary>
     /// <summary>The text on the current line.</summary>
-    public List<RuneCell> CurrentLine { get; set; }
+    public List<Cell> CurrentLine { get; set; }
 
 
     /// <summary>The position of the input cursor within the <see cref="CurrentLine"/>.</summary>
     /// <summary>The position of the input cursor within the <see cref="CurrentLine"/>.</summary>
     public int CursorPosition { get; set; }
     public int CursorPosition { get; set; }

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

@@ -45,7 +45,7 @@ public interface IAutocomplete
     /// <param name="me">The mouse event.</param>
     /// <param name="me">The mouse event.</param>
     /// <param name="fromHost">If was called from the popup or from the host.</param>
     /// <param name="fromHost">If was called from the popup or from the host.</param>
     /// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
     /// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
-    bool OnMouseEvent (MouseEvent me, bool fromHost = false);
+    bool OnMouseEvent (MouseEventArgs me, bool fromHost = false);
 
 
     /// <summary>Gets or sets where the popup will be displayed.</summary>
     /// <summary>Gets or sets where the popup will be displayed.</summary>
     bool PopupInsideContainer { get; set; }
     bool PopupInsideContainer { get; set; }

+ 1 - 1
Terminal.Gui/Text/Autocomplete/PopupAutocomplete.PopUp.cs

@@ -25,6 +25,6 @@ public abstract partial class PopupAutocomplete
             _autoComplete.RenderOverlay (_autoComplete.LastPopupPos.Value);
             _autoComplete.RenderOverlay (_autoComplete.LastPopupPos.Value);
         }
         }
 
 
-        protected internal override bool OnMouseEvent (MouseEvent mouseEvent) { return _autoComplete.OnMouseEvent (mouseEvent); }
+        protected override bool OnMouseEvent (MouseEventArgs mouseEvent) { return _autoComplete.OnMouseEvent (mouseEvent); }
     }
     }
 }
 }

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

@@ -105,7 +105,7 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
     /// <param name="me">The mouse event.</param>
     /// <param name="me">The mouse event.</param>
     /// <param name="fromHost">If was called from the popup or from the host.</param>
     /// <param name="fromHost">If was called from the popup or from the host.</param>
     /// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
     /// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
-    public override bool OnMouseEvent (MouseEvent me, bool fromHost = false)
+    public override bool OnMouseEvent (MouseEventArgs me, bool fromHost = false)
     {
     {
         if (fromHost)
         if (fromHost)
         {
         {
@@ -488,7 +488,7 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
 
 
     /// <summary>Render the current selection in the Autocomplete context menu by the mouse reporting.</summary>
     /// <summary>Render the current selection in the Autocomplete context menu by the mouse reporting.</summary>
     /// <param name="me"></param>
     /// <param name="me"></param>
-    protected void RenderSelectedIdxByMouse (MouseEvent me)
+    protected void RenderSelectedIdxByMouse (MouseEventArgs me)
     {
     {
         if (SelectedIdx != me.Position.Y - ScrollOffset)
         if (SelectedIdx != me.Position.Y - ScrollOffset)
         {
         {

+ 2 - 7
Terminal.Gui/View/Adornment/Border.cs

@@ -262,13 +262,8 @@ public class Border : Adornment
     private Point _startGrabPoint;
     private Point _startGrabPoint;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
-        if (base.OnMouseEvent (mouseEvent))
-        {
-            return true;
-        }
-
         // BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/3312
         // BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/3312
         if (!_dragPosition.HasValue && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)
         if (!_dragPosition.HasValue && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)
                                     // HACK: Prevents Window from being draggable if it's Top
                                     // HACK: Prevents Window from being draggable if it's Top
@@ -1370,7 +1365,7 @@ public class Border : Adornment
         KeyBindings.Add (Key.Tab.WithShift, KeyBindingScope.HotKey, Command.BackTab);
         KeyBindings.Add (Key.Tab.WithShift, KeyBindingScope.HotKey, Command.BackTab);
     }
     }
 
 
-    private void ApplicationOnMouseEvent (object? sender, MouseEvent e)
+    private void ApplicationOnMouseEvent (object? sender, MouseEventArgs e)
     {
     {
         if (e.Flags != MouseFlags.Button1Clicked)
         if (e.Flags != MouseFlags.Button1Clicked)
         {
         {

+ 1 - 1
Terminal.Gui/View/Adornment/Padding.cs

@@ -50,7 +50,7 @@ public class Padding : Adornment
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         if (Parent is null)
         if (Parent is null)
         {
         {

+ 1 - 1
Terminal.Gui/View/Adornment/ShadowView.cs

@@ -109,7 +109,7 @@ internal class ShadowView : View
         Rectangle screen = ViewportToScreen (viewport);
         Rectangle screen = ViewportToScreen (viewport);
 
 
         // Fill the rest of the rectangle - note we skip the last since vertical will draw it
         // Fill the rest of the rectangle - note we skip the last since vertical will draw it
-        for (int i = screen.X + 1; i < screen.X + screen.Width - 1; i++)
+        for (int i = Math.Max(0, screen.X + 1); i < screen.X + screen.Width - 1; i++)
         {
         {
             Driver.Move (i, screen.Y);
             Driver.Move (i, screen.Y);
 
 

+ 10 - 1
Terminal.Gui/View/CancelEventArgs.cs

@@ -27,7 +27,16 @@ public class CancelEventArgs<T> : CancelEventArgs where T : notnull
         NewValue = newValue;
         NewValue = newValue;
     }
     }
 
 
-    protected CancelEventArgs () { }
+    /// <summary>
+    ///     Initializes a new instance of the <see cref="CancelEventArgs{T}"/> class.
+    /// </summary>
+    /// <param name="currentValue">The current (old) value of the property.</param>
+    /// <param name="newValue">The value the property will be set to if the event is not cancelled.</param>
+    protected CancelEventArgs (T currentValue, T newValue)
+    {
+        CurrentValue = currentValue;
+        NewValue = newValue;
+    }
 
 
     /// <summary>The current value of the property.</summary>
     /// <summary>The current value of the property.</summary>
     public T CurrentValue { get; }
     public T CurrentValue { get; }

+ 1 - 1
Terminal.Gui/View/Navigation/AdvanceFocusEventArgs.cs

@@ -4,7 +4,7 @@
 public class AdvanceFocusEventArgs : CancelEventArgs<bool>
 public class AdvanceFocusEventArgs : CancelEventArgs<bool>
 {
 {
     /// <summary>Initializes a new instance.</summary>
     /// <summary>Initializes a new instance.</summary>
-    public AdvanceFocusEventArgs (NavigationDirection direction, TabBehavior? behavior)
+    public AdvanceFocusEventArgs (NavigationDirection direction, TabBehavior? behavior) : base (false, false)
     {
     {
         Direction = direction;
         Direction = direction;
         Behavior = behavior;
         Behavior = behavior;

+ 2 - 4
Terminal.Gui/View/Orientation/OrientationHelper.cs

@@ -69,7 +69,7 @@ public class OrientationHelper
                 return;
                 return;
             }
             }
 
 
-            // Best practice is to invoke the virtual method first.
+            // Best practice is to call the virtual method first.
             // This allows derived classes to handle the event and potentially cancel it.
             // This allows derived classes to handle the event and potentially cancel it.
             if (_owner?.OnOrientationChanging (value, _orientation) ?? false)
             if (_owner?.OnOrientationChanging (value, _orientation) ?? false)
             {
             {
@@ -98,10 +98,8 @@ public class OrientationHelper
                 }
                 }
             }
             }
 
 
-            // Best practice is to invoke the virtual method first.
+            // Best practice is to call the virtual method first, then raise the event.
             _owner?.OnOrientationChanged (_orientation);
             _owner?.OnOrientationChanged (_orientation);
-
-            // Even though Changed is not cancelable, it is still a good practice to raise the event after.
             OrientationChanged?.Invoke (_owner, new (in _orientation));
             OrientationChanged?.Invoke (_owner, new (in _orientation));
         }
         }
     }
     }

+ 141 - 182
Terminal.Gui/View/View.Keyboard.cs

@@ -26,7 +26,7 @@ public partial class View // Keyboard APIs
 
 
     #region HotKey Support
     #region HotKey Support
 
 
-    /// <summary>Invoked when the <see cref="HotKey"/> is changed.</summary>
+    /// <summary>Raised when the <see cref="HotKey"/> is changed.</summary>
     public event EventHandler<KeyChangedEventArgs>? HotKeyChanged;
     public event EventHandler<KeyChangedEventArgs>? HotKeyChanged;
 
 
     private Key _hotKey = new ();
     private Key _hotKey = new ();
@@ -73,7 +73,7 @@ public partial class View // Keyboard APIs
     ///     <para>If the hot key is changed, the <see cref="HotKeyChanged"/> event is fired.</para>
     ///     <para>If the hot key is changed, the <see cref="HotKeyChanged"/> event is fired.</para>
     ///     <para>Set to <see cref="Key.Empty"/> to disable the hot key.</para>
     ///     <para>Set to <see cref="Key.Empty"/> to disable the hot key.</para>
     /// </remarks>
     /// </remarks>
-    public virtual Key HotKey
+    public Key HotKey
     {
     {
         get => _hotKey;
         get => _hotKey;
         set
         set
@@ -218,7 +218,7 @@ public partial class View // Keyboard APIs
 
 
     private void SetHotKeyFromTitle ()
     private void SetHotKeyFromTitle ()
     {
     {
-        if (TitleTextFormatter == null || HotKeySpecifier == new Rune ('\xFFFF'))
+        if (HotKeySpecifier == new Rune ('\xFFFF'))
         {
         {
             return; // throw new InvalidOperationException ("Can't set HotKey unless a TextFormatter has been created");
             return; // throw new InvalidOperationException ("Can't set HotKey unless a TextFormatter has been created");
         }
         }
@@ -243,7 +243,8 @@ public partial class View // Keyboard APIs
     #region Key Down Event
     #region Key Down Event
 
 
     /// <summary>
     /// <summary>
-    ///     If the view is enabled, processes a new key down event and returns <see langword="true"/> if the event was
+    ///     If the view is enabled, raises the related key down events on the view, and returns <see langword="true"/> if the
+    ///     event was
     ///     handled.
     ///     handled.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
@@ -252,74 +253,95 @@ public partial class View // Keyboard APIs
     ///         first.
     ///         first.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         If the focused sub view does not handle the key press, this method calls <see cref="OnKeyDown"/> to allow the
-    ///         view to pre-process the key press. If <see cref="OnKeyDown"/> returns <see langword="false"/>, this method then
-    ///         calls <see cref="OnInvokingKeyBindings"/> to invoke any key bindings. Then, only if no key bindings are
-    ///         handled, <see cref="OnProcessKeyDown"/> will be called allowing the view to process the key press.
+    ///         If a more focused subview does not handle the key press, this method raises <see cref="OnKeyDown"/>/
+    ///         <see cref="KeyDown"/> to allow the
+    ///         view to pre-process the key press. If <see cref="OnKeyDown"/>/<see cref="KeyDown"/> is not handled any commands bound to the key will be invoked.
+    ///         Then, only if no key bindings are
+    ///         handled, <see cref="OnKeyDownNotHandled"/>/<see cref="KeyDownNotHandled"/> will be raised allowing the view to
+    ///         process the key press.
+    ///     </para>
+    ///     <para>
+    ///         Calling this method for a key bound to the view via an Application-scoped keybinding will have no effect.
+    ///         Instead,
+    ///         use <see cref="Application.RaiseKeyDownEvent"/>.
     ///     </para>
     ///     </para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </remarks>
     /// </remarks>
-    /// <param name="keyEvent"></param>
+    /// <param name="key"></param>
     /// <returns><see langword="true"/> if the event was handled.</returns>
     /// <returns><see langword="true"/> if the event was handled.</returns>
-    public bool NewKeyDownEvent (Key keyEvent)
+    public bool NewKeyDownEvent (Key key)
     {
     {
         if (!Enabled)
         if (!Enabled)
         {
         {
             return false;
             return false;
         }
         }
 
 
-        // By default the KeyBindingScope is View
-
-        if (Focused?.NewKeyDownEvent (keyEvent) == true)
+        // If there's a Focused subview, give it a chance (this recurses down the hierarchy)
+        if (Focused?.NewKeyDownEvent (key) == true)
         {
         {
             return true;
             return true;
         }
         }
 
 
         // Before (fire the cancellable event)
         // Before (fire the cancellable event)
-        if (OnKeyDown (keyEvent))
+        if (RaiseKeyDown (key) || key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
         // During (this is what can be cancelled)
         // During (this is what can be cancelled)
-        InvokingKeyBindings?.Invoke (this, keyEvent);
 
 
-        if (keyEvent.Handled)
+        // TODO: NewKeyDownEvent returns bool. It should be bool? so state of InvokeCommands can be reflected up stack
+        if (InvokeCommandsBoundToKey (key) is true || key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
-        // TODO: NewKeyDownEvent returns bool. It should be bool? so state of InvokeCommand can be reflected up stack
-
-        bool? handled = OnInvokingKeyBindings (keyEvent, KeyBindingScope.HotKey | KeyBindingScope.Focused);
-
-        if (handled is { } && (bool)handled)
+        // After
+        if (RaiseKeyDownNotHandled (key) || key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
-        // TODO: The below is not right. OnXXX handlers are supposed to fire the events.
-        // TODO: But I've moved it outside of the v-function to test something.
-        // After (fire the cancellable event)
-        // fire event
-        ProcessKeyDown?.Invoke (this, keyEvent);
+        return key.Handled;
 
 
-        if (!keyEvent.Handled && OnProcessKeyDown (keyEvent))
+        bool RaiseKeyDown (Key k)
         {
         {
-            return true;
+            // Before (fire the cancellable event)
+            if (OnKeyDown (k) || k.Handled)
+            {
+                return true;
+            }
+
+            // fire event
+            KeyDown?.Invoke (this, k);
+
+            return k.Handled;
         }
         }
 
 
-        return keyEvent.Handled;
+        bool RaiseKeyDownNotHandled (Key k)
+        {
+            if (OnKeyDownNotHandled (k) || k.Handled)
+            {
+                return true;
+            }
+
+            KeyDownNotHandled?.Invoke (this, k);
+
+            return false;
+        }
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Low-level API called when the user presses a key, allowing a view to pre-process the key down event. This is
-    ///     called from <see cref="NewKeyDownEvent"/> before <see cref="OnInvokingKeyBindings"/>.
+    ///     Called when the user presses a key, allowing subscribers to pre-process the key down event. Called
+    ///     before key bindings are invoked and <see cref="KeyDownNotHandled"/> is raised. Set
+    ///     <see cref="Key.Handled"/>
+    ///     to true to
+    ///     stop the key from being processed further.
     /// </summary>
     /// </summary>
-    /// <param name="keyEvent">Contains the details about the key that produced the event.</param>
+    /// <param name="key">The key that produced the event.</param>
     /// <returns>
     /// <returns>
-    ///     <see langword="false"/> if the key press was not handled. <see langword="true"/> if the keypress was handled
-    ///     and no other view should see it.
+    ///     <see langword="false"/> if the key down event was not handled. <see langword="true"/> if the event was handled
+    ///     and processing should stop.
     /// </returns>
     /// </returns>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
@@ -328,18 +350,14 @@ public partial class View // Keyboard APIs
     ///     </para>
     ///     </para>
     ///     <para>Fires the <see cref="KeyDown"/> event.</para>
     ///     <para>Fires the <see cref="KeyDown"/> event.</para>
     /// </remarks>
     /// </remarks>
-    public virtual bool OnKeyDown (Key keyEvent)
-    {
-        // fire event
-        KeyDown?.Invoke (this, keyEvent);
-
-        return keyEvent.Handled;
-    }
+    protected virtual bool OnKeyDown (Key key) { return false; }
 
 
     /// <summary>
     /// <summary>
-    ///     Invoked when the user presses a key, allowing subscribers to pre-process the key down event. This is fired
-    ///     from <see cref="OnKeyDown"/> before <see cref="OnInvokingKeyBindings"/>. Set <see cref="Key.Handled"/> to true to
-    ///     stop the key from being processed by other views.
+    ///     Raised when the user presses a key, allowing subscribers to pre-process the key down event. Called
+    ///     before key bindings are invoked and <see cref="KeyDownNotHandled"/> is raised. Set
+    ///     <see cref="Key.Handled"/>
+    ///     to true to
+    ///     stop the key from being processed further.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
@@ -351,60 +369,49 @@ public partial class View // Keyboard APIs
     public event EventHandler<Key>? KeyDown;
     public event EventHandler<Key>? KeyDown;
 
 
     /// <summary>
     /// <summary>
-    ///     Low-level API called when the user presses a key, allowing views do things during key down events. This is
-    ///     called from <see cref="NewKeyDownEvent"/> after <see cref="OnInvokingKeyBindings"/>.
+    ///     Called when the user has pressed key it wasn't handled by <see cref="KeyDown"/> and was not bound to a key binding.
     /// </summary>
     /// </summary>
-    /// <param name="keyEvent">Contains the details about the key that produced the event.</param>
-    /// <returns>
-    ///     <see langword="false"/> if the key press was not handled. <see langword="true"/> if the keypress was handled
-    ///     and no other view should see it.
-    /// </returns>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         Override <see cref="OnProcessKeyDown"/> to override the behavior of how the base class processes key down
-    ///         events.
-    ///     </para>
-    ///     <para>
     ///         For processing <see cref="HotKey"/>s and commands, use <see cref="Command"/> and
     ///         For processing <see cref="HotKey"/>s and commands, use <see cref="Command"/> and
     ///         <see cref="KeyBindings.Add(Key, Command[])"/>instead.
     ///         <see cref="KeyBindings.Add(Key, Command[])"/>instead.
     ///     </para>
     ///     </para>
-    ///     <para>Fires the <see cref="ProcessKeyDown"/> event.</para>
     ///     <para>
     ///     <para>
     ///         Not all terminals support distinct key up notifications; applications should avoid depending on distinct
     ///         Not all terminals support distinct key up notifications; applications should avoid depending on distinct
     ///         KeyUp events.
     ///         KeyUp events.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
-    public virtual bool OnProcessKeyDown (Key keyEvent)
-    {
-        //ProcessKeyDown?.Invoke (this, keyEvent);
-        return keyEvent.Handled;
-    }
+    /// <param name="key">Contains the details about the key that produced the event.</param>
+    /// <returns>
+    ///     <see langword="false"/> if the key press was not handled. <see langword="true"/> if the keypress was handled
+    ///     and no other view should see it.
+    /// </returns>
+    protected virtual bool OnKeyDownNotHandled (Key key) { return key.Handled; }
 
 
     /// <summary>
     /// <summary>
-    ///     Invoked when the user presses a key, allowing subscribers to do things during key down events. Set
-    ///     <see cref="Key.Handled"/> to true to stop the key from being processed by other views. Invoked after
-    ///     <see cref="KeyDown"/> and before <see cref="InvokingKeyBindings"/>.
+    ///     Raised when the user has pressed key it wasn't handled by <see cref="KeyDown"/> and was not bound to a key binding.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         SubViews can use the <see cref="ProcessKeyDown"/> of their super view override the default behavior of when
-    ///         key bindings are invoked.
+    ///         For processing <see cref="HotKey"/>s and commands, use <see cref="Command"/> and
+    ///         <see cref="KeyBindings.Add(Key, Command[])"/>instead.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         Not all terminals support distinct key up notifications; applications should avoid depending on distinct
-    ///         KeyUp events.
+    ///         SubViews can use the <see cref="KeyDownNotHandled"/> of their super view override the default behavior of when
+    ///         key bindings are invoked.
     ///     </para>
     ///     </para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </remarks>
     /// </remarks>
-    public event EventHandler<Key>? ProcessKeyDown;
+    public event EventHandler<Key>? KeyDownNotHandled;
 
 
     #endregion KeyDown Event
     #endregion KeyDown Event
 
 
     #region KeyUp Event
     #region KeyUp Event
 
 
     /// <summary>
     /// <summary>
-    ///     If the view is enabled, processes a new key up event and returns <see langword="true"/> if the event was
-    ///     handled. Called before <see cref="NewKeyDownEvent"/>.
+    ///     If the view is enabled, raises the related key up events on the view, and returns <see langword="true"/> if the
+    ///     event was
+    ///     handled.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
@@ -416,44 +423,52 @@ public partial class View // Keyboard APIs
     ///         first.
     ///         first.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         If the focused sub view does not handle the key press, this method calls <see cref="OnKeyUp"/>, which is
-    ///         cancellable.
+    ///         If the focused sub view does not handle the key press, this method raises <see cref="OnKeyUp"/>/
+    ///         <see cref="KeyUp"/> to allow the
+    ///         view to pre-process the key press.
     ///     </para>
     ///     </para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </remarks>
     /// </remarks>
-    /// <param name="keyEvent"></param>
+    /// <param name="key"></param>
     /// <returns><see langword="true"/> if the event was handled.</returns>
     /// <returns><see langword="true"/> if the event was handled.</returns>
-    public bool NewKeyUpEvent (Key keyEvent)
+    public bool NewKeyUpEvent (Key key)
     {
     {
         if (!Enabled)
         if (!Enabled)
         {
         {
             return false;
             return false;
         }
         }
 
 
-        if (Focused?.NewKeyUpEvent (keyEvent) == true)
+        // Before
+        if (RaiseKeyUp (key) || key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
-        // Before (fire the cancellable event)
-        if (OnKeyUp (keyEvent))
-        {
-            return true;
-        }
-
-        // During (this is what can be cancelled)
-        // TODO: Until there's a clear use-case, we will not define 'during' event (e.g. OnDuringKeyUp). 
+        // During
 
 
-        // After (fire the cancellable event InvokingKeyBindings)
-        // TODO: Until there's a clear use-case, we will not define an 'after' event (e.g. OnAfterKeyUp). 
+        // After
 
 
         return false;
         return false;
+
+        bool RaiseKeyUp (Key k)
+        {
+            // Before (fire the cancellable event)
+            if (OnKeyUp (k) || k.Handled)
+            {
+                return true;
+            }
+
+            // fire event
+            KeyUp?.Invoke (this, k);
+
+            return k.Handled;
+        }
     }
     }
 
 
-    /// <summary>Method invoked when a key is released. This method is called from <see cref="NewKeyUpEvent"/>.</summary>
-    /// <param name="keyEvent">Contains the details about the key that produced the event.</param>
+    /// <summary>Called when a key is released. This method is called from <see cref="NewKeyUpEvent"/>.</summary>
+    /// <param name="key">Contains the details about the key that produced the event.</param>
     /// <returns>
     /// <returns>
-    ///     <see langword="false"/> if the key stroke was not handled. <see langword="true"/> if no other view should see
+    ///     <see langword="false"/> if the keys up event was not handled. <see langword="true"/> if no other view should see
     ///     it.
     ///     it.
     /// </returns>
     /// </returns>
     /// <remarks>
     /// <remarks>
@@ -465,21 +480,10 @@ public partial class View // Keyboard APIs
     ///     </para>
     ///     </para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </remarks>
     /// </remarks>
-    public virtual bool OnKeyUp (Key keyEvent)
-    {
-        // fire event
-        KeyUp?.Invoke (this, keyEvent);
-
-        if (keyEvent.Handled)
-        {
-            return true;
-        }
-
-        return false;
-    }
+    public virtual bool OnKeyUp (Key key) { return false; }
 
 
     /// <summary>
     /// <summary>
-    ///     Invoked when a key is released. Set <see cref="Key.Handled"/> to true to stop the key up event from being processed
+    ///     Raised when a key is released. Set <see cref="Key.Handled"/> to true to stop the key up event from being processed
     ///     by other views.
     ///     by other views.
     ///     <remarks>
     ///     <remarks>
     ///         Not all terminals support key distinct down/up notifications, Applications should avoid depending on
     ///         Not all terminals support key distinct down/up notifications, Applications should avoid depending on
@@ -501,32 +505,20 @@ public partial class View // Keyboard APIs
     private Dictionary<Command, CommandImplementation> CommandImplementations { get; } = new ();
     private Dictionary<Command, CommandImplementation> CommandImplementations { get; } = new ();
 
 
     /// <summary>
     /// <summary>
-    ///     Low-level API called when a user presses a key; invokes any key bindings set on the view. This is called
-    ///     during <see cref="NewKeyDownEvent"/> after <see cref="OnKeyDown"/> has returned.
+    ///     INTERNAL API: Invokes any commands bound to <paramref name="key"/> on this view, adornments, and subviews.
     /// </summary>
     /// </summary>
-    /// <remarks>
-    ///     <para>Fires the <see cref="InvokingKeyBindings"/> event.</para>
-    ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
-    /// </remarks>
-    /// <param name="keyEvent">Contains the details about the key that produced the event.</param>
-    /// <param name="scope">The scope.</param>
+    /// <param name="key"></param>
     /// <returns>
     /// <returns>
-    ///     <see langword="null"/> if no event was raised; input proessing should continue.
-    ///     <see langword="false"/> if the event was raised and was not handled (or cancelled); input proessing should continue.
-    ///     <see langword="true"/> if the event was raised and handled (or cancelled); input proessing should stop.
+    ///     <see langword="null"/> if no command was invoked or there was no matching key binding; input processing should
+    ///     continue.
+    ///     <see langword="false"/> if a command was invoked and was not handled (or cancelled); input processing should
+    ///     continue.
+    ///     <see langword="true"/> if at least one command was invoked and handled (or
+    ///     cancelled); input processing should stop.
     /// </returns>
     /// </returns>
-    public virtual bool? OnInvokingKeyBindings (Key keyEvent, KeyBindingScope scope)
+    internal bool? InvokeCommandsBoundToKey (Key key)
     {
     {
-        // fire event only if there's a hotkey binding for the key
-        if (KeyBindings.TryGet (keyEvent, scope, out KeyBinding kb))
-        {
-            InvokingKeyBindings?.Invoke (this, keyEvent);
-
-            if (keyEvent.Handled)
-            {
-                return true;
-            }
-        }
+        KeyBindingScope scope = KeyBindingScope.Focused | KeyBindingScope.HotKey;
 
 
         // * If no key binding was found, `InvokeKeyBindings` returns `null`.
         // * If no key binding was found, `InvokeKeyBindings` returns `null`.
         //   Continue passing the event (return `false` from `OnInvokeKeyBindings`).
         //   Continue passing the event (return `false` from `OnInvokeKeyBindings`).
@@ -534,31 +526,31 @@ public partial class View // Keyboard APIs
         //   `InvokeKeyBindings` returns `false`. Continue passing the event (return `false` from `OnInvokeKeyBindings`)..
         //   `InvokeKeyBindings` returns `false`. Continue passing the event (return `false` from `OnInvokeKeyBindings`)..
         // * If key bindings were found, and any handled the key (at least one `Command` returned `true`),
         // * If key bindings were found, and any handled the key (at least one `Command` returned `true`),
         //   `InvokeKeyBindings` returns `true`. Continue passing the event (return `false` from `OnInvokeKeyBindings`).
         //   `InvokeKeyBindings` returns `true`. Continue passing the event (return `false` from `OnInvokeKeyBindings`).
-        bool? handled = InvokeKeyBindings (keyEvent, scope);
+        bool?  handled = InvokeCommands (key, scope);
 
 
-        if (handled is { } && (bool)handled)
+        if (handled is true)
         {
         {
             // Stop processing if any key binding handled the key.
             // Stop processing if any key binding handled the key.
             // DO NOT stop processing if there are no matching key bindings or none of the key bindings handled the key
             // DO NOT stop processing if there are no matching key bindings or none of the key bindings handled the key
-            return true;
+            return handled;
         }
         }
 
 
-        if (Margin is { } && ProcessAdornmentKeyBindings (Margin, keyEvent, scope, ref handled))
+        if (Margin is { } && InvokeCommandsBoundToKeyOnAdornment (Margin, key, scope, ref handled))
         {
         {
             return true;
             return true;
         }
         }
 
 
-        if (Padding is { } && ProcessAdornmentKeyBindings (Padding, keyEvent, scope, ref handled))
+        if (Padding is { } && InvokeCommandsBoundToKeyOnAdornment (Padding, key, scope, ref handled))
         {
         {
             return true;
             return true;
         }
         }
 
 
-        if (Border is { } && ProcessAdornmentKeyBindings (Border, keyEvent, scope, ref handled))
+        if (Border is { } && InvokeCommandsBoundToKeyOnAdornment (Border, key, scope, ref handled))
         {
         {
             return true;
             return true;
         }
         }
 
 
-        if (ProcessSubViewKeyBindings (keyEvent, scope, ref handled))
+        if (InvokeCommandsBoundToKeyOnSubviews (key, scope, ref handled))
         {
         {
             return true;
             return true;
         }
         }
@@ -566,9 +558,9 @@ public partial class View // Keyboard APIs
         return handled;
         return handled;
     }
     }
 
 
-    private bool ProcessAdornmentKeyBindings (Adornment adornment, Key keyEvent, KeyBindingScope scope, ref bool? handled)
+    private static bool InvokeCommandsBoundToKeyOnAdornment (Adornment adornment, Key key, KeyBindingScope scope, ref bool? handled)
     {
     {
-        bool? adornmentHandled = adornment.OnInvokingKeyBindings (keyEvent, scope);
+        bool? adornmentHandled = adornment.InvokeCommandsBoundToKey (key);
 
 
         if (adornmentHandled is true)
         if (adornmentHandled is true)
         {
         {
@@ -582,7 +574,7 @@ public partial class View // Keyboard APIs
 
 
         foreach (View subview in adornment.Subviews)
         foreach (View subview in adornment.Subviews)
         {
         {
-            bool? subViewHandled = subview.OnInvokingKeyBindings (keyEvent, scope);
+            bool? subViewHandled = subview.InvokeCommandsBoundToKey (key);
 
 
             if (subViewHandled is { })
             if (subViewHandled is { })
             {
             {
@@ -598,7 +590,7 @@ public partial class View // Keyboard APIs
         return false;
         return false;
     }
     }
 
 
-    private bool ProcessSubViewKeyBindings (Key keyEvent, KeyBindingScope scope, ref bool? handled, bool invoke = true)
+    private bool InvokeCommandsBoundToKeyOnSubviews (Key key, KeyBindingScope scope, ref bool? handled, bool invoke = true)
     {
     {
         // Now, process any key bindings in the subviews that are tagged to KeyBindingScope.HotKey.
         // Now, process any key bindings in the subviews that are tagged to KeyBindingScope.HotKey.
         foreach (View subview in Subviews)
         foreach (View subview in Subviews)
@@ -608,7 +600,7 @@ public partial class View // Keyboard APIs
                 continue;
                 continue;
             }
             }
 
 
-            if (subview.KeyBindings.TryGet (keyEvent, scope, out KeyBinding binding))
+            if (subview.KeyBindings.TryGet (key, scope, out KeyBinding binding))
             {
             {
                 if (binding.Scope == KeyBindingScope.Focused && !subview.HasFocus)
                 if (binding.Scope == KeyBindingScope.Focused && !subview.HasFocus)
                 {
                 {
@@ -620,7 +612,7 @@ public partial class View // Keyboard APIs
                     return true;
                     return true;
                 }
                 }
 
 
-                bool? subViewHandled = subview.OnInvokingKeyBindings (keyEvent, scope);
+                bool? subViewHandled = subview.InvokeCommandsBoundToKey (key);
 
 
                 if (subViewHandled is { })
                 if (subViewHandled is { })
                 {
                 {
@@ -633,7 +625,7 @@ public partial class View // Keyboard APIs
                 }
                 }
             }
             }
 
 
-            bool recurse = subview.ProcessSubViewKeyBindings (keyEvent, scope, ref handled, invoke);
+            bool recurse = subview.InvokeCommandsBoundToKeyOnSubviews (key, scope, ref handled, invoke);
 
 
             if (recurse || (handled is { } && (bool)handled))
             if (recurse || (handled is { } && (bool)handled))
             {
             {
@@ -653,7 +645,7 @@ public partial class View // Keyboard APIs
     /// <param name="key">The key to test.</param>
     /// <param name="key">The key to test.</param>
     /// <param name="boundView">Returns the view the key is bound to.</param>
     /// <param name="boundView">Returns the view the key is bound to.</param>
     /// <returns></returns>
     /// <returns></returns>
-    public bool IsHotKeyKeyBound (Key key, out View? boundView)
+    public bool IsHotKeyBound (Key key, out View? boundView)
     {
     {
         // recurse through the subviews to find the views that has the key bound
         // recurse through the subviews to find the views that has the key bound
         boundView = null;
         boundView = null;
@@ -667,7 +659,7 @@ public partial class View // Keyboard APIs
                 return true;
                 return true;
             }
             }
 
 
-            if (subview.IsHotKeyKeyBound (key, out boundView))
+            if (subview.IsHotKeyBound (key, out boundView))
             {
             {
                 return true;
                 return true;
             }
             }
@@ -677,26 +669,20 @@ public partial class View // Keyboard APIs
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Raised when a key is pressed that may be mapped to a key binding. Set <see cref="Key.Handled"/> to true to
-    ///     stop the key from being processed by other views.
-    /// </summary>
-    public event EventHandler<Key>? InvokingKeyBindings;
-
-    /// <summary>
-    ///     Invokes any binding that is registered on this <see cref="View"/> and matches the <paramref name="key"/>
+    ///     Invokes the Commands bound to <paramref name="key"/>.
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </summary>
     /// </summary>
     /// <param name="key">The key event passed.</param>
     /// <param name="key">The key event passed.</param>
     /// <param name="scope">The scope.</param>
     /// <param name="scope">The scope.</param>
     /// <returns>
     /// <returns>
-    ///     <see langword="null"/> if no command was invoked; input proessing should continue.
-    ///     <see langword="false"/> if at least one command was invoked and was not handled (or cancelled); input proessing should continue.
-    ///     <see langword="true"/> if at least one command was invoked and handled (or cancelled); input proessing should stop.
+    ///     <see langword="null"/> if no command was invoked; input processing should continue.
+    ///     <see langword="false"/> if at least one command was invoked and was not handled (or cancelled); input processing
+    ///     should continue.
+    ///     <see langword="true"/> if at least one command was invoked and handled (or cancelled); input processing should
+    ///     stop.
     /// </returns>
     /// </returns>
-    protected bool? InvokeKeyBindings (Key key, KeyBindingScope scope)
+    protected bool? InvokeCommands (Key key, KeyBindingScope scope)
     {
     {
-        bool? toReturn = null;
-
         if (!KeyBindings.TryGet (key, scope, out KeyBinding binding))
         if (!KeyBindings.TryGet (key, scope, out KeyBinding binding))
         {
         {
             return null;
             return null;
@@ -704,49 +690,22 @@ public partial class View // Keyboard APIs
 
 
 #if DEBUG
 #if DEBUG
 
 
-        // TODO: Determine if App scope bindings should be fired first or last (currently last).
         if (Application.KeyBindings.TryGet (key, KeyBindingScope.Focused | KeyBindingScope.HotKey, out KeyBinding b))
         if (Application.KeyBindings.TryGet (key, KeyBindingScope.Focused | KeyBindingScope.HotKey, out KeyBinding b))
         {
         {
-            //var boundView = views [0];
-            //var commandBinding = boundView.KeyBindings.Get (key);
             Debug.WriteLine (
             Debug.WriteLine (
-                             $"WARNING: InvokeKeyBindings ({key}) - An Application scope binding exists for this key. The registered view will not invoke Command."); //{commandBinding.Commands [0]}: {boundView}.");
+                             $"WARNING: InvokeKeyBindings ({key}) - An Application scope binding exists for this key. The registered view will not invoke Command.");
         }
         }
 
 
         // TODO: This is a "prototype" debug check. It may be too annoying vs. useful.
         // TODO: This is a "prototype" debug check. It may be too annoying vs. useful.
         // Scour the bindings up our View hierarchy
         // Scour the bindings up our View hierarchy
         // to ensure that the key is not already bound to a different set of commands.
         // to ensure that the key is not already bound to a different set of commands.
-        if (SuperView?.IsHotKeyKeyBound (key, out View? previouslyBoundView) ?? false)
+        if (SuperView?.IsHotKeyBound (key, out View? previouslyBoundView) ?? false)
         {
         {
             Debug.WriteLine ($"WARNING: InvokeKeyBindings ({key}) - A subview or peer has bound this Key and will not see it: {previouslyBoundView}.");
             Debug.WriteLine ($"WARNING: InvokeKeyBindings ({key}) - A subview or peer has bound this Key and will not see it: {previouslyBoundView}.");
         }
         }
 
 
 #endif
 #endif
         return InvokeCommands (binding.Commands, key, binding);
         return InvokeCommands (binding.Commands, key, binding);
-
-        foreach (Command command in binding.Commands)
-        {
-            if (!CommandImplementations.ContainsKey (command))
-            {
-                throw new NotSupportedException (
-                                                 @$"A KeyBinding was set up for the command {command} ({key}) but that command is not supported by this View ({GetType ().Name})"
-                                                );
-            }
-
-            // each command has its own return value
-            bool? thisReturn = InvokeCommand (command, key, binding);
-
-            // 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;
     }
     }
 
 
     #endregion Key Bindings
     #endregion Key Bindings

+ 0 - 1
Terminal.Gui/View/View.Layout.cs

@@ -28,7 +28,6 @@ public partial class View // Layout APIs
     /// <param name="targetY">The target y location.</param>
     /// <param name="targetY">The target y location.</param>
     /// <param name="nx">The new x location that will ensure <paramref name="viewToMove"/> will be fully visible.</param>
     /// <param name="nx">The new x location that will ensure <paramref name="viewToMove"/> will be fully visible.</param>
     /// <param name="ny">The new y location that will ensure <paramref name="viewToMove"/> will be fully visible.</param>
     /// <param name="ny">The new y location that will ensure <paramref name="viewToMove"/> will be fully visible.</param>
-    /// <param name="statusBar">The new top most statusBar</param>
     /// <returns>
     /// <returns>
     ///     Either <see cref="Application.Top"/> (if <paramref name="viewToMove"/> does not have a Super View) or
     ///     Either <see cref="Application.Top"/> (if <paramref name="viewToMove"/> does not have a Super View) or
     ///     <paramref name="viewToMove"/>'s SuperView. This can be used to ensure LayoutSubviews is called on the correct View.
     ///     <paramref name="viewToMove"/>'s SuperView. This can be used to ensure LayoutSubviews is called on the correct View.

+ 96 - 85
Terminal.Gui/View/View.Mouse.cs

@@ -11,7 +11,7 @@ public partial class View // Mouse APIs
     private ColorScheme? _savedNonHoverColorScheme;
     private ColorScheme? _savedNonHoverColorScheme;
 
 
     /// <summary>
     /// <summary>
-    ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse moves over the View's <see cref="Frame"/>.
+    ///     INTERNAL Called by <see cref="Application.RaiseMouseEvent"/> when the mouse moves over the View's <see cref="Frame"/>.
     ///     <see cref="MouseLeave"/> will
     ///     <see cref="MouseLeave"/> will
     ///     be raised when the mouse is no longer over the <see cref="Frame"/>. If another View occludes this View, the
     ///     be raised when the mouse is no longer over the <see cref="Frame"/>. If another View occludes this View, the
     ///     that View will also receive MouseEnter/Leave events.
     ///     that View will also receive MouseEnter/Leave events.
@@ -126,7 +126,7 @@ public partial class View // Mouse APIs
     public event EventHandler<CancelEventArgs>? MouseEnter;
     public event EventHandler<CancelEventArgs>? MouseEnter;
 
 
     /// <summary>
     /// <summary>
-    ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse leaves <see cref="Frame"/>, or is occluded
+    ///     INTERNAL Called by <see cref="Application.RaiseMouseEvent"/> when the mouse leaves <see cref="Frame"/>, or is occluded
     ///     by another non-SubView.
     ///     by another non-SubView.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
@@ -196,16 +196,15 @@ public partial class View // Mouse APIs
 
 
     #region Low Level Mouse Events
     #region Low Level Mouse Events
 
 
-    /// <summary>Event fired when a mouse event occurs.</summary>
-    /// <remarks>
-    ///     <para>
-    ///         The coordinates are relative to <see cref="View.Viewport"/>.
-    ///     </para>
-    /// </remarks>
-    public event EventHandler<MouseEventEventArgs>? MouseEvent;
+    /// <summary>Gets or sets whether the <see cref="View"/> wants continuous button pressed events.</summary>
+    public virtual bool WantContinuousButtonPressed { get; set; }
+
+    /// <summary>Gets or sets whether the <see cref="View"/> wants mouse position reports.</summary>
+    /// <value><see langword="true"/> if mouse position reports are wanted; otherwise, <see langword="false"/>.</value>
+    public bool WantMousePositionReports { get; set; }
 
 
     /// <summary>
     /// <summary>
-    ///     Processes a <see cref="MouseEvent"/>. This method is called by <see cref="Application.OnMouseEvent"/> when a mouse
+    ///     Processes a new <see cref="MouseEvent"/>. This method is called by <see cref="Application.RaiseMouseEvent"/> when a mouse
     ///     event occurs.
     ///     event occurs.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
@@ -213,20 +212,20 @@ public partial class View // Mouse APIs
     ///         A view must be both enabled and visible to receive mouse events.
     ///         A view must be both enabled and visible to receive mouse events.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         This method calls <see cref="OnMouseEvent"/> to process the event. If the event is not handled, and one of the
-    ///         mouse buttons was clicked, it calls <see cref="OnMouseClick"/> to process the click.
+    ///         This method raises <see cref="RaiseMouseEvent"/>/<see cref="MouseEvent"/>; if not handled, and one of the
+    ///         mouse buttons was clicked, the <see cref="RaiseMouseClickEvent"/>/<see cref="MouseClick"/> event will be raised
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
     ///         See <see cref="SetPressedHighlight"/> for more information.
     ///         See <see cref="SetPressedHighlight"/> for more information.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, the <see cref="OnMouseClick"/> event
-    ///         will be invoked repeatedly while the button is pressed.
+    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, the <see cref="RaiseMouseEvent"/>/<see cref="MouseEvent"/> event
+    ///         will be raised on any new mouse event where <see cref="Terminal.Gui.MouseEventArgs.Flags"/> indicates a button is pressed.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/> if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/> if the event was handled, <see langword="false"/> otherwise.</returns>
-    public bool? NewMouseEvent (MouseEvent mouseEvent)
+    public bool? NewMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         // Pre-conditions
         // Pre-conditions
         if (!Enabled)
         if (!Enabled)
@@ -246,17 +245,13 @@ public partial class View // Mouse APIs
         }
         }
 
 
         // Cancellable event
         // Cancellable event
-        if (OnMouseEvent (mouseEvent))
+        if (RaiseMouseEvent (mouseEvent) || mouseEvent.Handled)
         {
         {
-            // Technically mouseEvent.Handled should already be true if implementers of OnMouseEvent
-            // follow the rules. But we'll update it just in case.
-            return mouseEvent.Handled = true;
+            return true;
         }
         }
 
 
-        // BUGBUG: MouseEvent should be fired from here. Fix this in https://github.com/gui-cs/Terminal.Gui/issues/3029
-
         // Post-Conditions
         // Post-Conditions
-        if (HighlightStyle != HighlightStyle.None || (WantContinuousButtonPressed && WantMousePositionReports))
+        if (HighlightStyle != HighlightStyle.None || WantContinuousButtonPressed)
         {
         {
             if (WhenGrabbedHandlePressed (mouseEvent))
             if (WhenGrabbedHandlePressed (mouseEvent))
             {
             {
@@ -274,35 +269,33 @@ public partial class View // Mouse APIs
             }
             }
         }
         }
 
 
-        if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2DoubleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3DoubleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4DoubleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button1TripleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2TripleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3TripleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4TripleClicked)
-           )
+        if (mouseEvent.IsSingleDoubleOrTripleClicked)
         {
         {
             // If it's a click, and we didn't handle it, then we need to generate a click event
             // If it's a click, and we didn't handle it, then we need to generate a click event
             // We get here if the view did not handle the mouse event via OnMouseEvent/MouseEvent and
             // We get here if the view did not handle the mouse event via OnMouseEvent/MouseEvent and
             // it did not handle the press/release/clicked events via HandlePress/HandleRelease/HandleClicked
             // it did not handle the press/release/clicked events via HandlePress/HandleRelease/HandleClicked
-            return OnMouseClick (new (mouseEvent));
+            return RaiseMouseClickEvent (mouseEvent);
         }
         }
 
 
         return false;
         return false;
     }
     }
 
 
-    /// <summary>Gets or sets whether the <see cref="View"/> wants continuous button pressed events.</summary>
-    public virtual bool WantContinuousButtonPressed { get; set; }
+    /// <summary>
+    ///     Raises the <see cref="RaiseMouseEvent"/>/<see cref="MouseEvent"/> event.
+    /// </summary>
+    /// <param name="mouseEvent"></param>
+    /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
+    public bool RaiseMouseEvent (MouseEventArgs mouseEvent)
+    {
+        if (OnMouseEvent (mouseEvent) || mouseEvent.Handled == true)
+        {
+            return true;
+        }
 
 
-    /// <summary>Gets or sets whether the <see cref="View"/> wants mouse position reports.</summary>
-    /// <value><see langword="true"/> if mouse position reports are wanted; otherwise, <see langword="false"/>.</value>
-    public virtual bool WantMousePositionReports { get; set; }
+        MouseEvent?.Invoke (this, mouseEvent);
+
+        return mouseEvent.Handled;
+    }
 
 
     /// <summary>Called when a mouse event occurs within the view's <see cref="Viewport"/>.</summary>
     /// <summary>Called when a mouse event occurs within the view's <see cref="Viewport"/>.</summary>
     /// <remarks>
     /// <remarks>
@@ -312,44 +305,36 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent)
+    protected virtual bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
-        var args = new MouseEventEventArgs (mouseEvent);
-
-        MouseEvent?.Invoke (this, args);
-
-        return args.Handled;
+        return false;
     }
     }
 
 
-    #endregion Low Level Mouse Events
-
-    #region Mouse Click Events
-
-    /// <summary>Event fired when a mouse click occurs.</summary>
-    /// 
+    /// <summary>Raised when a mouse event occurs.</summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         Fired when the mouse is either clicked or double-clicked. Check
-    ///         <see cref="MouseEvent.Flags"/> to see which button was clicked.
-    ///     </para>
-    ///     <para>
     ///         The coordinates are relative to <see cref="View.Viewport"/>.
     ///         The coordinates are relative to <see cref="View.Viewport"/>.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
-    public event EventHandler<MouseEventEventArgs>? MouseClick;
+    public event EventHandler<MouseEventArgs>? MouseEvent;
+
+    #endregion Low Level Mouse Events
 
 
-    /// <summary>Invokes the MouseClick event.</summary>
+    #region Mouse Click Events
+
+    /// <summary>Raises the <see cref="OnMouseClick"/>/<see cref="MouseClick"/> event.</summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         Called when the mouse is either clicked or double-clicked. Check
-    ///         <see cref="MouseEvent.Flags"/> to see which button was clicked.
+    ///         Called when the mouse is either clicked or double-clicked.
+    ///     </para>
+    ///     <para>
+    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, will be invoked on every mouse event where
+    ///         the mouse button is pressed.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected bool OnMouseClick (MouseEventEventArgs args)
+    protected bool RaiseMouseClickEvent (MouseEventArgs args)
     {
     {
-        // BUGBUG: This should be named NewMouseClickEvent. Fix this in https://github.com/gui-cs/Terminal.Gui/issues/3029
-
         // Pre-conditions
         // Pre-conditions
         if (!Enabled)
         if (!Enabled)
         {
         {
@@ -359,7 +344,10 @@ public partial class View // Mouse APIs
 
 
         // Cancellable event
         // Cancellable event
 
 
-        // BUGBUG: There should be a call to a protected virtual OnMouseClick here. Fix this in https://github.com/gui-cs/Terminal.Gui/issues/3029
+        if (OnMouseClick (args) || args.Handled)
+        {
+            return args.Handled;
+        }
 
 
         MouseClick?.Invoke (this, args);
         MouseClick?.Invoke (this, args);
 
 
@@ -372,11 +360,39 @@ public partial class View // Mouse APIs
 
 
         // Always invoke Select command on MouseClick
         // Always invoke Select command on MouseClick
         // By default, this will raise Selecting/OnSelecting - Subclasses can override this via AddCommand (Command.Select ...).
         // By default, this will raise Selecting/OnSelecting - Subclasses can override this via AddCommand (Command.Select ...).
-        args.Handled = InvokeCommand (Command.Select, ctx: new (Command.Select, key: null, data: args.MouseEvent)) == true;
+        args.Handled = InvokeCommand (Command.Select, ctx: new (Command.Select, key: null, data: args)) == true;
 
 
         return args.Handled;
         return args.Handled;
     }
     }
 
 
+    /// <summary>
+    ///     Called when a mouse click occurs. Check <see cref="MouseEventArgs.Flags"/> to see which button was clicked.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Called when the mouse is either clicked or double-clicked.
+    ///     </para>
+    ///     <para>
+    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, will be called on every mouse event where
+    ///         the mouse button is pressed.
+    ///     </para>
+    /// </remarks>
+    /// <param name="args"></param>
+    /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
+    protected virtual bool OnMouseClick (MouseEventArgs args) { return false; }
+
+    /// <summary>Raised when a mouse click occurs.</summary>
+    /// <remarks>
+    ///     <para>
+    ///         Raised when the mouse is either clicked or double-clicked.
+    ///     </para>
+    ///     <para>
+    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, will be raised on every mouse event where
+    ///         the mouse button is pressed.
+    ///     </para>
+    /// </remarks>
+    public event EventHandler<MouseEventArgs>? MouseClick;
+
     /// <summary>
     /// <summary>
     ///     INTERNAL For cases where the view is grabbed and the mouse is clicked, this method handles the click event (typically
     ///     INTERNAL For cases where the view is grabbed and the mouse is clicked, this method handles the click event (typically
     ///     when <see cref="WantContinuousButtonPressed"/> or <see cref="HighlightStyle"/> are set).
     ///     when <see cref="WantContinuousButtonPressed"/> or <see cref="HighlightStyle"/> are set).
@@ -386,13 +402,11 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    internal bool WhenGrabbedHandleClicked (MouseEvent mouseEvent)
+    internal bool WhenGrabbedHandleClicked (MouseEventArgs mouseEvent)
     {
     {
-        if (Application.MouseGrabView == this
-            && (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)
-                || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked)
-                || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked)
-                || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked)))
+        mouseEvent.Handled = false;
+
+        if (Application.MouseGrabView == this && mouseEvent.IsSingleClicked)
         {
         {
             // We're grabbed. Clicked event comes after the last Release. This is our signal to ungrab
             // We're grabbed. Clicked event comes after the last Release. This is our signal to ungrab
             Application.UngrabMouse ();
             Application.UngrabMouse ();
@@ -405,7 +419,7 @@ public partial class View // Mouse APIs
             // If mouse is still in bounds, generate a click
             // If mouse is still in bounds, generate a click
             if (!WantMousePositionReports && Viewport.Contains (mouseEvent.Position))
             if (!WantMousePositionReports && Viewport.Contains (mouseEvent.Position))
             {
             {
-                return OnMouseClick (new (mouseEvent));
+                return RaiseMouseClickEvent (mouseEvent);
             }
             }
 
 
             return mouseEvent.Handled = true;
             return mouseEvent.Handled = true;
@@ -423,12 +437,11 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    internal bool WhenGrabbedHandleReleased (MouseEvent mouseEvent)
+    internal bool WhenGrabbedHandleReleased (MouseEventArgs mouseEvent)
     {
     {
-        if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2Released)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3Released)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4Released))
+        mouseEvent.Handled = false;
+
+        if (mouseEvent.IsReleased)
         {
         {
             if (Application.MouseGrabView == this)
             if (Application.MouseGrabView == this)
             {
             {
@@ -452,12 +465,11 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    private bool WhenGrabbedHandlePressed (MouseEvent mouseEvent)
+    private bool WhenGrabbedHandlePressed (MouseEventArgs mouseEvent)
     {
     {
-        if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2Pressed)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3Pressed)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4Pressed))
+        mouseEvent.Handled = false;
+
+        if (mouseEvent.IsPressed)
         {
         {
             // The first time we get pressed event, grab the mouse and set focus
             // The first time we get pressed event, grab the mouse and set focus
             if (Application.MouseGrabView != this)
             if (Application.MouseGrabView != this)
@@ -493,8 +505,7 @@ public partial class View // Mouse APIs
 
 
             if (WantContinuousButtonPressed && Application.MouseGrabView == this)
             if (WantContinuousButtonPressed && Application.MouseGrabView == this)
             {
             {
-                // If this is not the first pressed event, generate a click
-                return OnMouseClick (new (mouseEvent));
+                return RaiseMouseClickEvent (mouseEvent);
             }
             }
 
 
             return mouseEvent.Handled = true;
             return mouseEvent.Handled = true;

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

@@ -6,7 +6,7 @@ namespace Terminal.Gui;
 internal class AutocompleteFilepathContext : AutocompleteContext
 internal class AutocompleteFilepathContext : AutocompleteContext
 {
 {
     public AutocompleteFilepathContext (string currentLine, int cursorPosition, FileDialogState state)
     public AutocompleteFilepathContext (string currentLine, int cursorPosition, FileDialogState state)
-        : base (TextModel.ToRuneCellList (currentLine), cursorPosition)
+        : base (Cell.ToCellList (currentLine), cursorPosition)
     {
     {
         State = state;
         State = state;
     }
     }
@@ -30,7 +30,7 @@ internal class FilepathSuggestionGenerator : ISuggestionGenerator
             return Enumerable.Empty<Suggestion> ();
             return Enumerable.Empty<Suggestion> ();
         }
         }
 
 
-        var path = TextModel.ToString (context.CurrentLine);
+        var path = Cell.ToString (context.CurrentLine);
         int last = path.LastIndexOfAny (FileDialog.Separators);
         int last = path.LastIndexOfAny (FileDialog.Separators);
 
 
         if (string.IsNullOrWhiteSpace (path) || !Path.IsPathRooted (path))
         if (string.IsNullOrWhiteSpace (path) || !Path.IsPathRooted (path))

+ 5 - 5
Terminal.Gui/Views/Bar.cs

@@ -45,27 +45,27 @@ public class Bar : View, IOrientation, IDesignable
         }
         }
     }
     }
 
 
-    private void OnMouseEvent (object? sender, MouseEventEventArgs e)
+    private void OnMouseEvent (object? sender, MouseEventArgs e)
     {
     {
         NavigationDirection direction = NavigationDirection.Backward;
         NavigationDirection direction = NavigationDirection.Backward;
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledDown)
+        if (e.Flags == MouseFlags.WheeledDown)
         {
         {
             e.Handled = true;
             e.Handled = true;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledUp)
+        if (e.Flags == MouseFlags.WheeledUp)
         {
         {
             direction = NavigationDirection.Forward;
             direction = NavigationDirection.Forward;
             e.Handled = true;
             e.Handled = true;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledRight)
+        if (e.Flags == MouseFlags.WheeledRight)
         {
         {
             e.Handled = true;
             e.Handled = true;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledLeft)
+        if (e.Flags == MouseFlags.WheeledLeft)
         {
         {
             direction = NavigationDirection.Forward;
             direction = NavigationDirection.Forward;
             e.Handled = true;
             e.Handled = true;

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

@@ -125,7 +125,7 @@ public class Button : View, IDesignable
         }
         }
     }
     }
 
 
-    private void Button_MouseClick (object sender, MouseEventEventArgs e)
+    private void Button_MouseClick (object sender, MouseEventArgs e)
     {
     {
         if (e.Handled)
         if (e.Handled)
         {
         {

+ 2 - 3
Terminal.Gui/Views/ColorBar.cs

@@ -110,7 +110,7 @@ internal abstract class ColorBar : View, IColorBar
     public event EventHandler<EventArgs<int>>? ValueChanged;
     public event EventHandler<EventArgs<int>>? ValueChanged;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
         {
         {
@@ -123,10 +123,9 @@ internal abstract class ColorBar : View, IColorBar
             mouseEvent.Handled = true;
             mouseEvent.Handled = true;
             SetFocus ();
             SetFocus ();
 
 
-            return true;
         }
         }
 
 
-        return base.OnMouseEvent (mouseEvent);
+        return mouseEvent.Handled;
     }
     }
 
 
     /// <summary>
     /// <summary>

+ 2 - 2
Terminal.Gui/Views/ColorPicker16.cs → Terminal.Gui/Views/ColorPicker.16.cs

@@ -181,11 +181,11 @@ public class ColorPicker16 : View
 
 
     // TODO: Decouple Cursor from SelectedColor so that mouse press-and-hold can show the color under the cursor.
     // TODO: Decouple Cursor from SelectedColor so that mouse press-and-hold can show the color under the cursor.
 
 
-    private void ColorPicker_MouseClick (object sender, MouseEventEventArgs me)
+    private void ColorPicker_MouseClick (object sender, MouseEventArgs me)
     {
     {
         // if (CanFocus)
         // if (CanFocus)
         {
         {
-            Cursor = new (me.MouseEvent.Position.X / _boxWidth, me.MouseEvent.Position.Y / _boxHeight);
+            Cursor = new (me.Position.X / _boxWidth, me.Position.Y / _boxHeight);
             SetFocus ();
             SetFocus ();
             me.Handled = true;
             me.Handled = true;
         }
         }

+ 123 - 0
Terminal.Gui/Views/ColorPicker.Prompt.cs

@@ -0,0 +1,123 @@
+namespace Terminal.Gui;
+
+public partial class ColorPicker
+{
+    /// <summary>
+    ///     Open a <see cref="Dialog"/> with two <see cref="ColorPicker"/> or <see cref="ColorPicker16"/>, based on the
+    ///     <see cref="ConsoleDriver.Force16Colors"/> is false or true, respectively, for <see cref="Attribute.Foreground"/>
+    ///     and <see cref="Attribute.Background"/> colors.
+    /// </summary>
+    /// <param name="title">The title to show in the dialog.</param>
+    /// <param name="currentAttribute">The current attribute used.</param>
+    /// <param name="newAttribute">The new attribute.</param>
+    /// <returns><see langword="true"/> if a new color was accepted, otherwise <see langword="false"/>.</returns>
+    public static bool Prompt (string title, Attribute? currentAttribute, out Attribute newAttribute)
+    {
+        var accept = false;
+
+        var d = new Dialog
+        {
+            Title = title,
+            Width = Application.Force16Colors ? 37 : Dim.Auto (DimAutoStyle.Auto, Dim.Percent (80), Dim.Percent (90)),
+            Height = 20
+        };
+
+        var btnOk = new Button
+        {
+            X = Pos.Center () - 5,
+            Y = Application.Force16Colors ? 6 : 4,
+            Text = "Ok",
+            Width = Dim.Auto (),
+            IsDefault = true
+        };
+
+        btnOk.Accepting += (s, e) =>
+                        {
+                            accept = true;
+                            e.Cancel = true;
+                            Application.RequestStop ();
+                        };
+
+        var btnCancel = new Button
+        {
+            X = Pos.Center () + 5,
+            Y = 4,
+            Text = "Cancel",
+            Width = Dim.Auto ()
+        };
+
+        btnCancel.Accepting += (s, e) =>
+                            {
+                                e.Cancel = true;
+                                Application.RequestStop ();
+                            };
+
+        d.Add (btnOk);
+        d.Add (btnCancel);
+
+        d.AddButton (btnOk);
+        d.AddButton (btnCancel);
+
+        View cpForeground;
+
+        if (Application.Force16Colors)
+        {
+            cpForeground = new ColorPicker16
+            {
+                SelectedColor = currentAttribute!.Value.Foreground.GetClosestNamedColor16 (),
+                Width = Dim.Fill (),
+                BorderStyle = LineStyle.Single,
+                Title = "Foreground"
+            };
+        }
+        else
+        {
+            cpForeground = new ColorPicker
+            {
+                SelectedColor = currentAttribute!.Value.Foreground,
+                Width = Dim.Fill (),
+                Style = new () { ShowColorName = true, ShowTextFields = true },
+                BorderStyle = LineStyle.Single,
+                Title = "Foreground"
+            };
+            ((ColorPicker)cpForeground).ApplyStyleChanges ();
+        }
+
+        View cpBackground;
+
+        if (Application.Force16Colors)
+        {
+            cpBackground = new ColorPicker16
+            {
+                SelectedColor = currentAttribute!.Value.Background.GetClosestNamedColor16 (),
+                Y = Pos.Bottom (cpForeground) + 1,
+                Width = Dim.Fill (),
+                BorderStyle = LineStyle.Single,
+                Title = "Background"
+            };
+        }
+        else
+        {
+            cpBackground = new ColorPicker
+            {
+                SelectedColor = currentAttribute!.Value.Background,
+                Width = Dim.Fill (),
+                Y = Pos.Bottom (cpForeground) + 1,
+                Style = new () { ShowColorName = true, ShowTextFields = true },
+                BorderStyle = LineStyle.Single,
+                Title = "Background"
+            };
+            ((ColorPicker)cpBackground).ApplyStyleChanges ();
+        }
+
+        d.Add (cpForeground, cpBackground);
+
+        Application.Run (d);
+        d.Dispose ();
+        Color newForeColor = Application.Force16Colors ? ((ColorPicker16)cpForeground).SelectedColor : ((ColorPicker)cpForeground).SelectedColor;
+        Color newBackColor = Application.Force16Colors ? ((ColorPicker16)cpBackground).SelectedColor : ((ColorPicker)cpBackground).SelectedColor;
+        newAttribute = new (newForeColor, newBackColor);
+
+        return accept;
+    }
+}

+ 0 - 0
Terminal.Gui/Views/ColorPickerStyle.cs → Terminal.Gui/Views/ColorPicker.Style.cs


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

@@ -7,7 +7,7 @@ namespace Terminal.Gui;
 /// <summary>
 /// <summary>
 ///     True color picker using HSL
 ///     True color picker using HSL
 /// </summary>
 /// </summary>
-public class ColorPicker : View
+public partial class ColorPicker : View
 {
 {
     /// <summary>
     /// <summary>
     ///     Creates a new instance of <see cref="ColorPicker"/>. Use
     ///     Creates a new instance of <see cref="ColorPicker"/>. Use

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

@@ -253,7 +253,7 @@ public class ComboBox : View, IDesignable
     public event EventHandler Expanded;
     public event EventHandler Expanded;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (me.Position.X == Viewport.Right - 1
         if (me.Position.X == Viewport.Right - 1
             && me.Position.Y == Viewport.Top
             && me.Position.Y == Viewport.Top
@@ -836,14 +836,15 @@ public class ComboBox : View, IDesignable
             set => _hideDropdownListOnClick = WantContinuousButtonPressed = value;
             set => _hideDropdownListOnClick = WantContinuousButtonPressed = value;
         }
         }
 
 
-        // BUGBUG: OnMouseEvent is internal!
-        protected internal override bool OnMouseEvent (MouseEvent me)
+        protected override bool OnMouseEvent (MouseEventArgs me)
         {
         {
-            var res = false;
             bool isMousePositionValid = IsMousePositionValid (me);
             bool isMousePositionValid = IsMousePositionValid (me);
 
 
+            var res = false;
+
             if (isMousePositionValid)
             if (isMousePositionValid)
             {
             {
+                // We're derived from ListView and it overrides OnMouseEvent, so we need to call it
                 res = base.OnMouseEvent (me);
                 res = base.OnMouseEvent (me);
             }
             }
 
 
@@ -984,7 +985,7 @@ public class ComboBox : View, IDesignable
             return res;
             return res;
         }
         }
 
 
-        private bool IsMousePositionValid (MouseEvent me)
+        private bool IsMousePositionValid (MouseEventArgs me)
         {
         {
             if (me.Position.X >= 0 && me.Position.X < Frame.Width && me.Position.Y >= 0 && me.Position.Y < Frame.Height)
             if (me.Position.X >= 0 && me.Position.X < Frame.Width && me.Position.Y >= 0 && me.Position.Y < Frame.Height)
             {
             {

+ 9 - 6
Terminal.Gui/Views/DateField.cs

@@ -114,16 +114,19 @@ public class DateField : TextField
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent  (MouseEvent ev)
+    protected override bool OnMouseEvent  (MouseEventArgs ev)
     {
     {
-        bool result = base.OnMouseEvent (ev);
+        if (base.OnMouseEvent (ev) || ev.Handled)
+        {
+            return true;
+        }
 
 
-        if (result && SelectedLength == 0 && ev.Flags.HasFlag (MouseFlags.Button1Pressed))
+        if (SelectedLength == 0 && ev.Flags.HasFlag (MouseFlags.Button1Pressed))
         {
         {
             AdjCursorPosition (ev.Position.X);
             AdjCursorPosition (ev.Position.X);
         }
         }
 
 
-        return result;
+        return ev.Handled;
     }
     }
 
 
     /// <summary>Event firing method for the <see cref="DateChanged"/> event.</summary>
     /// <summary>Event firing method for the <see cref="DateChanged"/> event.</summary>
@@ -131,7 +134,7 @@ public class DateField : TextField
     public virtual void OnDateChanged (DateTimeEventArgs<DateTime> args) { DateChanged?.Invoke (this, args); }
     public virtual void OnDateChanged (DateTimeEventArgs<DateTime> args) { DateChanged?.Invoke (this, args); }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key a)
+    protected override bool OnKeyDownNotHandled (Key a)
     {
     {
         // Ignore non-numeric characters.
         // Ignore non-numeric characters.
         if (a >= Key.D0 && a <= Key.D9)
         if (a >= Key.D0 && a <= Key.D9)
@@ -169,7 +172,7 @@ public class DateField : TextField
             CursorPosition = newPoint;
             CursorPosition = newPoint;
         }
         }
 
 
-        while (Text [CursorPosition].ToString () == _separator)
+        while (CursorPosition < Text.GetColumns () - 1 && Text [CursorPosition].ToString () == _separator)
         {
         {
             if (increment)
             if (increment)
             {
             {

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

@@ -233,7 +233,7 @@ public class FileDialog : Dialog
         _tbPath.TextChanged += (s, e) => PathChanged ();
         _tbPath.TextChanged += (s, e) => PathChanged ();
 
 
         _tableView.CellActivated += CellActivate;
         _tableView.CellActivated += CellActivate;
-        _tableView.KeyUp += (s, k) => k.Handled = TableView_KeyUp (k);
+        _tableView.KeyDown += (s, k) => k.Handled = TableView_KeyUp (k);
         _tableView.SelectedCellChanged += TableView_SelectedCellChanged;
         _tableView.SelectedCellChanged += TableView_SelectedCellChanged;
 
 
         _tableView.KeyBindings.ReplaceCommands (Key.Home, Command.Start);
         _tableView.KeyBindings.ReplaceCommands (Key.Home, Command.Start);
@@ -670,11 +670,11 @@ public class FileDialog : Dialog
         FinishAccept ();
         FinishAccept ();
     }
     }
 
 
-    private void AcceptIf (Key keyEvent, KeyCode isKey)
+    private void AcceptIf (Key key, KeyCode isKey)
     {
     {
-        if (!keyEvent.Handled && keyEvent.KeyCode == isKey)
+        if (!key.Handled && key.KeyCode == isKey)
         {
         {
-            keyEvent.Handled = true;
+            key.Handled = true;
 
 
             // User hit Enter in text box so probably wants the
             // User hit Enter in text box so probably wants the
             // contents of the text box as their selection not
             // contents of the text box as their selection not
@@ -1007,18 +1007,18 @@ public class FileDialog : Dialog
         }
         }
     }
     }
 
 
-    private void OnTableViewMouseClick (object sender, MouseEventEventArgs e)
+    private void OnTableViewMouseClick (object sender, MouseEventArgs e)
     {
     {
-        Point? clickedCell = _tableView.ScreenToCell (e.MouseEvent.Position.X, e.MouseEvent.Position.Y, out int? clickedCol);
+        Point? clickedCell = _tableView.ScreenToCell (e.Position.X, e.Position.Y, out int? clickedCol);
 
 
         if (clickedCol is { })
         if (clickedCol is { })
         {
         {
-            if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+            if (e.Flags.HasFlag (MouseFlags.Button1Clicked))
             {
             {
                 // left click in a header
                 // left click in a header
                 SortColumn (clickedCol.Value);
                 SortColumn (clickedCol.Value);
             }
             }
-            else if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked))
+            else if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
             {
             {
                 // right click in a header
                 // right click in a header
                 ShowHeaderContextMenu (clickedCol.Value, e);
                 ShowHeaderContextMenu (clickedCol.Value, e);
@@ -1026,7 +1026,7 @@ public class FileDialog : Dialog
         }
         }
         else
         else
         {
         {
-            if (clickedCell is { } && e.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked))
+            if (clickedCell is { } && e.Flags.HasFlag (MouseFlags.Button3Clicked))
             {
             {
                 // right click in rest of table
                 // right click in rest of table
                 ShowCellContextMenu (clickedCell, e);
                 ShowCellContextMenu (clickedCell, e);
@@ -1198,7 +1198,7 @@ public class FileDialog : Dialog
 
 
     private FileSystemInfoStats RowToStats (int rowIndex) { return State?.Children [rowIndex]; }
     private FileSystemInfoStats RowToStats (int rowIndex) { return State?.Children [rowIndex]; }
 
 
-    private void ShowCellContextMenu (Point? clickedCell, MouseEventEventArgs e)
+    private void ShowCellContextMenu (Point? clickedCell, MouseEventArgs e)
     {
     {
         if (clickedCell is null)
         if (clickedCell is null)
         {
         {
@@ -1207,7 +1207,7 @@ public class FileDialog : Dialog
 
 
         var contextMenu = new ContextMenu
         var contextMenu = new ContextMenu
         {
         {
-            Position = new Point (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1)
+            Position = new Point (e.Position.X + 1, e.Position.Y + 1)
         };
         };
 
 
         var menuItems = new MenuBarItem (
         var menuItems = new MenuBarItem (
@@ -1222,13 +1222,13 @@ public class FileDialog : Dialog
         contextMenu.Show (menuItems);
         contextMenu.Show (menuItems);
     }
     }
 
 
-    private void ShowHeaderContextMenu (int clickedCol, MouseEventEventArgs e)
+    private void ShowHeaderContextMenu (int clickedCol, MouseEventArgs e)
     {
     {
         string sort = GetProposedNewSortOrder (clickedCol, out bool isAsc);
         string sort = GetProposedNewSortOrder (clickedCol, out bool isAsc);
 
 
         var contextMenu = new ContextMenu
         var contextMenu = new ContextMenu
         {
         {
-            Position = new Point (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1)
+            Position = new Point (e.Position.X + 1, e.Position.Y + 1)
         };
         };
 
 
         var menuItems = new MenuBarItem (
         var menuItems = new MenuBarItem (

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

@@ -22,7 +22,7 @@ public class FrameView : View
         MouseClick += FrameView_MouseClick;
         MouseClick += FrameView_MouseClick;
     }
     }
 
 
-    private void FrameView_MouseClick (object sender, MouseEventEventArgs e)
+    private void FrameView_MouseClick (object sender, MouseEventArgs e)
     {
     {
         // base sets focus on HotKey
         // base sets focus on HotKey
         e.Handled = InvokeCommand (Command.HotKey, ctx: new (Command.HotKey, key: null, data: this)) == true;
         e.Handled = InvokeCommand (Command.HotKey, ctx: new (Command.HotKey, key: null, data: this)) == true;

+ 29 - 35
Terminal.Gui/Views/HexView.cs

@@ -327,7 +327,7 @@ public class HexView : View, IDesignable
     public void DiscardEdits () { _edits = new (); }
     public void DiscardEdits () { _edits = new (); }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (_source is null)
         if (_source is null)
         {
         {
@@ -349,7 +349,7 @@ public class HexView : View, IDesignable
 
 
         if (me.Flags == MouseFlags.WheeledDown)
         if (me.Flags == MouseFlags.WheeledDown)
         {
         {
-            DisplayStart = Math.Min (DisplayStart + BytesPerLine, GetEditedSize());
+            DisplayStart = Math.Min (DisplayStart + BytesPerLine, GetEditedSize ());
 
 
             return true;
             return true;
         }
         }
@@ -431,14 +431,14 @@ public class HexView : View, IDesignable
         Driver.SetAttribute (current);
         Driver.SetAttribute (current);
         Move (0, 0);
         Move (0, 0);
 
 
-        int nblocks = BytesPerLine / NUM_BYTES_PER_HEX_COLUMN;
-        var data = new byte [nblocks * NUM_BYTES_PER_HEX_COLUMN * viewport.Height];
+        int nBlocks = BytesPerLine / NUM_BYTES_PER_HEX_COLUMN;
+        var data = new byte [nBlocks * NUM_BYTES_PER_HEX_COLUMN * viewport.Height];
         Source.Position = _displayStart;
         Source.Position = _displayStart;
-        int n = _source.Read (data, 0, data.Length);
-
-        Attribute activeColor = GetHotNormalColor ();
-        Attribute trackingColor = GetHotFocusColor ();
+        int n = _source!.Read (data, 0, data.Length);
 
 
+        Attribute selectedAttribute = GetHotNormalColor ();
+        Attribute editedAttribute = new Attribute (GetNormalColor ().Foreground.GetHighlightColor (), GetNormalColor ().Background);
+        Attribute editingAttribute = new Attribute (GetFocusColor ().Background, GetFocusColor ().Foreground);
         for (var line = 0; line < viewport.Height; line++)
         for (var line = 0; line < viewport.Height; line++)
         {
         {
             Rectangle lineRect = new (0, line, viewport.Width, 1);
             Rectangle lineRect = new (0, line, viewport.Width, 1);
@@ -449,9 +449,9 @@ public class HexView : View, IDesignable
             }
             }
 
 
             Move (0, line);
             Move (0, line);
-            currentAttribute = GetHotNormalColor ();
+            currentAttribute = new Attribute (GetNormalColor ().Foreground.GetHighlightColor (), GetNormalColor ().Background);
             Driver.SetAttribute (currentAttribute);
             Driver.SetAttribute (currentAttribute);
-            var address = $"{_displayStart + line * nblocks * NUM_BYTES_PER_HEX_COLUMN:x8}";
+            var address = $"{_displayStart + line * nBlocks * NUM_BYTES_PER_HEX_COLUMN:x8}";
             Driver.AddStr ($"{address.Substring (8 - AddressWidth)}");
             Driver.AddStr ($"{address.Substring (8 - AddressWidth)}");
 
 
             if (AddressWidth > 0)
             if (AddressWidth > 0)
@@ -461,20 +461,21 @@ public class HexView : View, IDesignable
 
 
             SetAttribute (GetNormalColor ());
             SetAttribute (GetNormalColor ());
 
 
-            for (var block = 0; block < nblocks; block++)
+            for (var block = 0; block < nBlocks; block++)
             {
             {
                 for (var b = 0; b < NUM_BYTES_PER_HEX_COLUMN; b++)
                 for (var b = 0; b < NUM_BYTES_PER_HEX_COLUMN; b++)
                 {
                 {
-                    int offset = line * nblocks * NUM_BYTES_PER_HEX_COLUMN + block * NUM_BYTES_PER_HEX_COLUMN + b;
+                    int offset = line * nBlocks * NUM_BYTES_PER_HEX_COLUMN + block * NUM_BYTES_PER_HEX_COLUMN + b;
                     byte value = GetData (data, offset, out bool edited);
                     byte value = GetData (data, offset, out bool edited);
 
 
-                    if (offset + _displayStart == Address || edited)
+                    if (offset + _displayStart == Address)
                     {
                     {
-                        SetAttribute (_leftSideHasFocus ? activeColor : trackingColor);
+                        // Selected
+                        SetAttribute (_leftSideHasFocus ? editingAttribute : (edited ? editedAttribute : selectedAttribute));
                     }
                     }
                     else
                     else
                     {
                     {
-                        SetAttribute (GetNormalColor ());
+                        SetAttribute (edited ? editedAttribute : GetNormalColor ());
                     }
                     }
 
 
                     Driver.AddStr (offset >= n && !edited ? "  " : $"{value:x2}");
                     Driver.AddStr (offset >= n && !edited ? "  " : $"{value:x2}");
@@ -482,12 +483,12 @@ public class HexView : View, IDesignable
                     Driver.AddRune (_spaceCharRune);
                     Driver.AddRune (_spaceCharRune);
                 }
                 }
 
 
-                Driver.AddStr (block + 1 == nblocks ? " " : $"{_columnSeparatorRune} ");
+                Driver.AddStr (block + 1 == nBlocks ? " " : $"{_columnSeparatorRune} ");
             }
             }
 
 
-            for (var bitem = 0; bitem < nblocks * NUM_BYTES_PER_HEX_COLUMN; bitem++)
+            for (var byteIndex = 0; byteIndex < nBlocks * NUM_BYTES_PER_HEX_COLUMN; byteIndex++)
             {
             {
-                int offset = line * nblocks * NUM_BYTES_PER_HEX_COLUMN + bitem;
+                int offset = line * nBlocks * NUM_BYTES_PER_HEX_COLUMN + byteIndex;
                 byte b = GetData (data, offset, out bool edited);
                 byte b = GetData (data, offset, out bool edited);
                 Rune c;
                 Rune c;
 
 
@@ -525,20 +526,21 @@ public class HexView : View, IDesignable
                     }
                     }
                 }
                 }
 
 
-                if (offset + _displayStart == Address || edited)
+                if (offset + _displayStart == Address)
                 {
                 {
-                    SetAttribute (_leftSideHasFocus ? trackingColor : activeColor);
+                    // Selected
+                    SetAttribute (_leftSideHasFocus ? editingAttribute : (edited ? editedAttribute : selectedAttribute));
                 }
                 }
                 else
                 else
                 {
                 {
-                    SetAttribute (GetNormalColor ());
+                    SetAttribute (edited ? editedAttribute : GetNormalColor ());
                 }
                 }
 
 
                 Driver.AddRune (c);
                 Driver.AddRune (c);
 
 
                 for (var i = 1; i < utf8BytesConsumed; i++)
                 for (var i = 1; i < utf8BytesConsumed; i++)
                 {
                 {
-                    bitem++;
+                    byteIndex++;
                     Driver.AddRune (_periodCharRune);
                     Driver.AddRune (_periodCharRune);
                 }
                 }
             }
             }
@@ -589,7 +591,7 @@ public class HexView : View, IDesignable
     public event EventHandler<HexViewEventArgs>? PositionChanged;
     public event EventHandler<HexViewEventArgs>? PositionChanged;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key keyEvent)
+    protected override bool OnKeyDownNotHandled (Key keyEvent)
     {
     {
         if (!AllowEdits || _source is null)
         if (!AllowEdits || _source is null)
         {
         {
@@ -755,9 +757,9 @@ public class HexView : View, IDesignable
             // We can move down lines cleanly (without extending stream)
             // We can move down lines cleanly (without extending stream)
             Address += bytes;
             Address += bytes;
         }
         }
-        else if ((bytes == BytesPerLine * Viewport.Height && _source.Length >= DisplayStart + BytesPerLine * Viewport.Height)
+        else if ((bytes == BytesPerLine * Viewport.Height && _source!.Length >= DisplayStart + BytesPerLine * Viewport.Height)
                  || (bytes <= BytesPerLine * Viewport.Height - BytesPerLine
                  || (bytes <= BytesPerLine * Viewport.Height - BytesPerLine
-                     && _source.Length <= DisplayStart + BytesPerLine * Viewport.Height))
+                     && _source!.Length <= DisplayStart + BytesPerLine * Viewport.Height))
         {
         {
             long p = Address;
             long p = Address;
 
 
@@ -952,16 +954,8 @@ public class HexView : View, IDesignable
             return false;
             return false;
         }
         }
 
 
-        if (direction == NavigationDirection.Forward && _leftSideHasFocus)
-        {
-            _leftSideHasFocus = !_leftSideHasFocus;
-            RedisplayLine (Address);
-            _firstNibble = true;
-
-            return true;
-        }
-
-        if (direction == NavigationDirection.Backward && !_leftSideHasFocus)
+        if ((direction == NavigationDirection.Forward && _leftSideHasFocus)
+            || (direction == NavigationDirection.Backward && !_leftSideHasFocus))
         {
         {
             _leftSideHasFocus = !_leftSideHasFocus;
             _leftSideHasFocus = !_leftSideHasFocus;
             RedisplayLine (Address);
             RedisplayLine (Address);

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

@@ -9,11 +9,11 @@ internal partial class HistoryText
         public Point CursorPosition;
         public Point CursorPosition;
         public Point FinalCursorPosition;
         public Point FinalCursorPosition;
         public bool IsUndoing;
         public bool IsUndoing;
-        public List<List<RuneCell>> Lines;
+        public List<List<Cell>> Lines;
         public LineStatus LineStatus;
         public LineStatus LineStatus;
         public HistoryTextItemEventArgs RemovedOnAdded;
         public HistoryTextItemEventArgs RemovedOnAdded;
 
 
-        public HistoryTextItemEventArgs (List<List<RuneCell>> lines, Point curPos, LineStatus linesStatus)
+        public HistoryTextItemEventArgs (List<List<Cell>> lines, Point curPos, LineStatus linesStatus)
         {
         {
             Lines = lines;
             Lines = lines;
             CursorPosition = curPos;
             CursorPosition = curPos;
@@ -22,7 +22,7 @@ internal partial class HistoryText
 
 
         public HistoryTextItemEventArgs (HistoryTextItemEventArgs historyTextItem)
         public HistoryTextItemEventArgs (HistoryTextItemEventArgs historyTextItem)
         {
         {
-            Lines = new List<List<RuneCell>> (historyTextItem.Lines);
+            Lines = new List<List<Cell>> (historyTextItem.Lines);
             CursorPosition = new Point (historyTextItem.CursorPosition.X, historyTextItem.CursorPosition.Y);
             CursorPosition = new Point (historyTextItem.CursorPosition.X, historyTextItem.CursorPosition.Y);
             LineStatus = historyTextItem.LineStatus;
             LineStatus = historyTextItem.LineStatus;
         }
         }

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

@@ -32,7 +32,7 @@ public class Label : View, IDesignable
     }
     }
 
 
     // TODO: base raises Select, but we want to raise HotKey. This can be simplified?
     // TODO: base raises Select, but we want to raise HotKey. This can be simplified?
-    private void Label_MouseClick (object sender, MouseEventEventArgs e)
+    private void Label_MouseClick (object sender, MouseEventArgs e)
     {
     {
         if (!CanFocus)
         if (!CanFocus)
         {
         {

+ 56 - 4
Terminal.Gui/Views/ListView.cs

@@ -147,7 +147,7 @@ public class ListView : View, IDesignable
 
 
                                         if (OnOpenSelectedItem ())
                                         if (OnOpenSelectedItem ())
                                         {
                                         {
-                                                return true;
+                                            return true;
                                         }
                                         }
 
 
                                         return false;
                                         return false;
@@ -189,6 +189,7 @@ public class ListView : View, IDesignable
                                         return !SetFocus ();
                                         return !SetFocus ();
                                     });
                                     });
 
 
+        AddCommand (Command.SelectAll, (ctx) => MarkAll((bool)ctx.KeyBinding?.Context!));
 
 
         // Default keybindings for all ListViews
         // Default keybindings for all ListViews
         KeyBindings.Add (Key.CursorUp, Command.Up);
         KeyBindings.Add (Key.CursorUp, Command.Up);
@@ -205,6 +206,13 @@ public class ListView : View, IDesignable
         KeyBindings.Add (Key.Home, Command.Start);
         KeyBindings.Add (Key.Home, Command.Start);
 
 
         KeyBindings.Add (Key.End, Command.End);
         KeyBindings.Add (Key.End, Command.End);
+
+        // Key.Space is already bound to Command.Select; this gives us select then move down
+        KeyBindings.Add (Key.Space.WithShift, [Command.Select, Command.Down]);
+
+        // Use the form of Add that lets us pass context to the handler
+        KeyBindings.Add (Key.A.WithCtrl, new KeyBinding ([Command.SelectAll], KeyBindingScope.Focused, true));
+        KeyBindings.Add (Key.U.WithCtrl, new KeyBinding ([Command.SelectAll], KeyBindingScope.Focused, false));
     }
     }
 
 
     /// <summary>Gets or sets whether this <see cref="ListView"/> allows items to be marked.</summary>
     /// <summary>Gets or sets whether this <see cref="ListView"/> allows items to be marked.</summary>
@@ -370,6 +378,31 @@ public class ListView : View, IDesignable
         }
         }
     }
     }
 
 
+    /// <summary>
+    ///     If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
+    ///     marks all items.
+    /// </summary>
+    /// <param name="mark"><see langword="true"/> marks all items; otherwise unmarks all items.</param>
+    /// <returns><see langword="true"/> if marking was successful.</returns>
+    public bool MarkAll (bool mark)
+    {
+        if (!_allowsMarking)
+        {
+            return false;
+        }
+
+        if (AllowsMultipleSelection)
+        {
+            for (var i = 0; i < Source.Count; i++)
+            {
+                Source.SetMark (i, mark);
+            }
+            return true;
+        }
+
+        return false;
+    }
+
     /// <summary>
     /// <summary>
     ///     If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
     ///     If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
     ///     unmarks all marked items other than <see cref="SelectedItem"/>.
     ///     unmarks all marked items other than <see cref="SelectedItem"/>.
@@ -439,7 +472,7 @@ public class ListView : View, IDesignable
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
             && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
@@ -784,7 +817,6 @@ public class ListView : View, IDesignable
         }
         }
     }
     }
 
 
-    // TODO: This should be cancelable
     /// <summary>Invokes the <see cref="OpenSelectedItem"/> event if it is defined.</summary>
     /// <summary>Invokes the <see cref="OpenSelectedItem"/> event if it is defined.</summary>
     /// <returns><see langword="true"/> if the <see cref="OpenSelectedItem"/> event was fired.</returns>
     /// <returns><see langword="true"/> if the <see cref="OpenSelectedItem"/> event was fired.</returns>
     public bool OnOpenSelectedItem ()
     public bool OnOpenSelectedItem ()
@@ -803,8 +835,28 @@ public class ListView : View, IDesignable
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key a)
+    protected override bool OnKeyDown (Key a)
     {
     {
+        // If marking is enabled and the user presses the space key don't let CollectionNavigator
+        // at it
+        if (AllowsMarking)
+        {
+            var keys = KeyBindings.GetKeysFromCommands (Command.Select);
+
+            if (keys.Contains (a))
+            {
+                return false;
+            }
+
+            keys = KeyBindings.GetKeysFromCommands ([Command.Select, Command.Down]);
+
+            if (keys.Contains (a))
+            {
+                return false;
+            }
+
+        }
+
         // Enable user to find & select an item by typing text
         // Enable user to find & select an item by typing text
         if (CollectionNavigatorBase.IsCompatibleKey (a))
         if (CollectionNavigatorBase.IsCompatibleKey (a))
         {
         {

+ 9 - 15
Terminal.Gui/Views/Menu/Menu.cs

@@ -1,5 +1,7 @@
 #nullable enable
 #nullable enable
 
 
+using static System.Formats.Asn1.AsnWriter;
+
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
 /// <summary>
 /// <summary>
@@ -305,19 +307,11 @@ internal sealed class Menu : View
         return true;
         return true;
     }
     }
 
 
-    /// <inheritdoc/>
-    public override bool? OnInvokingKeyBindings (Key keyEvent, KeyBindingScope scope)
+    /// <inheritdoc />
+    protected override bool OnKeyDownNotHandled (Key keyEvent)
     {
     {
-        bool? handled = base.OnInvokingKeyBindings (keyEvent, scope);
-
-        if (handled is { } && (bool)handled)
-        {
-            return true;
-        }
-
-        // TODO: Determine if there's a cleaner way to handle this.
-        // This supports the case where the menu bar is a context menu
-        return _host.OnInvokingKeyBindings (keyEvent, scope);
+        // We didn't handle the key, pass it on to host
+        return _host.InvokeCommandsBoundToKey (keyEvent) == true;
     }
     }
 
 
     private void Current_TerminalResized (object? sender, SizeChangedEventArgs e)
     private void Current_TerminalResized (object? sender, SizeChangedEventArgs e)
@@ -343,7 +337,7 @@ internal sealed class Menu : View
         }
         }
     }
     }
 
 
-    private void Application_RootMouseEvent (object? sender, MouseEvent a)
+    private void Application_RootMouseEvent (object? sender, MouseEventArgs a)
     {
     {
         if (a.View is { } and (MenuBar or not Menu))
         if (a.View is { } and (MenuBar or not Menu))
         {
         {
@@ -359,7 +353,7 @@ internal sealed class Menu : View
 
 
         Point boundsPoint = view.ScreenToViewport (new (a.Position.X, a.Position.Y));
         Point boundsPoint = view.ScreenToViewport (new (a.Position.X, a.Position.Y));
 
 
-        var me = new MouseEvent
+        var me = new MouseEventArgs
         {
         {
             Position = boundsPoint,
             Position = boundsPoint,
             Flags = a.Flags,
             Flags = a.Flags,
@@ -814,7 +808,7 @@ internal sealed class Menu : View
         _host.SetNeedsDisplay ();
         _host.SetNeedsDisplay ();
     }
     }
 
 
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!_host._handled && !_host.HandleGrabView (me, this))
         if (!_host._handled && !_host.HandleGrabView (me, this))
         {
         {

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

@@ -137,7 +137,7 @@ public class MenuBar : View, IDesignable
                                                   });
                                                   });
         AddCommand (Command.Select, ctx =>
         AddCommand (Command.Select, ctx =>
                                     {
                                     {
-                                        if (ctx.Data is MouseEvent)
+                                        if (ctx.Data is MouseEventArgs)
                                         {
                                         {
                                             // HACK: Work around the fact that View.MouseClick always invokes Select
                                             // HACK: Work around the fact that View.MouseClick always invokes Select
                                             return false;
                                             return false;
@@ -1400,7 +1400,7 @@ public class MenuBar : View, IDesignable
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!_handled && !HandleGrabView (me, this))
         if (!_handled && !HandleGrabView (me, this))
         {
         {
@@ -1513,7 +1513,7 @@ public class MenuBar : View, IDesignable
     internal bool _isContextMenuLoading;
     internal bool _isContextMenuLoading;
     private MenuBarItem [] _menus = [];
     private MenuBarItem [] _menus = [];
 
 
-    internal bool HandleGrabView (MouseEvent me, View current)
+    internal bool HandleGrabView (MouseEventArgs me, View current)
     {
     {
         if (Application.MouseGrabView is { })
         if (Application.MouseGrabView is { })
         {
         {
@@ -1541,7 +1541,7 @@ public class MenuBar : View, IDesignable
                     Application.UngrabMouse ();
                     Application.UngrabMouse ();
                     View v = me.View;
                     View v = me.View;
                     Application.GrabMouse (v);
                     Application.GrabMouse (v);
-                    MouseEvent nme;
+                    MouseEventArgs nme;
 
 
                     if (me.Position.Y > -1)
                     if (me.Position.Y > -1)
                     {
                     {

+ 5 - 5
Terminal.Gui/Views/RadioGroup.cs

@@ -220,12 +220,12 @@ public class RadioGroup : View, IDesignable, IOrientation
     /// </remarks>
     /// </remarks>
     public bool DoubleClickAccepts { get; set; } = true;
     public bool DoubleClickAccepts { get; set; } = true;
 
 
-    private void RadioGroup_MouseClick (object? sender, MouseEventEventArgs e)
+    private void RadioGroup_MouseClick (object? sender, MouseEventArgs e)
     {
     {
-        if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+        if (e.Flags.HasFlag (MouseFlags.Button1Clicked))
         {
         {
-            int viewportX = e.MouseEvent.Position.X;
-            int viewportY = e.MouseEvent.Position.Y;
+            int viewportX = e.Position.X;
+            int viewportY = e.Position.Y;
 
 
             int pos = Orientation == Orientation.Horizontal ? viewportX : viewportY;
             int pos = Orientation == Orientation.Horizontal ? viewportX : viewportY;
 
 
@@ -249,7 +249,7 @@ public class RadioGroup : View, IDesignable, IOrientation
             return;
             return;
         }
         }
 
 
-        if (DoubleClickAccepts && e.MouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
+        if (DoubleClickAccepts && e.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
         {
         {
             // NOTE: Drivers ALWAYS generate a Button1Clicked event before Button1DoubleClicked
             // NOTE: Drivers ALWAYS generate a Button1Clicked event before Button1DoubleClicked
             // NOTE: So, we've already selected an item.
             // NOTE: So, we've already selected an item.

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

@@ -270,7 +270,7 @@ public class ScrollBarView : View
     public event EventHandler ChangedPosition;
     public event EventHandler ChangedPosition;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         if (mouseEvent.Flags != MouseFlags.Button1Pressed
         if (mouseEvent.Flags != MouseFlags.Button1Pressed
             && mouseEvent.Flags != MouseFlags.Button1DoubleClicked
             && mouseEvent.Flags != MouseFlags.Button1DoubleClicked
@@ -777,16 +777,16 @@ public class ScrollBarView : View
     //	}
     //	}
     //}
     //}
 
 
-    private void ContentBottomRightCorner_MouseClick (object sender, MouseEventEventArgs me)
+    private void ContentBottomRightCorner_MouseClick (object sender, MouseEventArgs me)
     {
     {
-        if (me.MouseEvent.Flags == MouseFlags.WheeledDown
-            || me.MouseEvent.Flags == MouseFlags.WheeledUp
-            || me.MouseEvent.Flags == MouseFlags.WheeledRight
-            || me.MouseEvent.Flags == MouseFlags.WheeledLeft)
+        if (me.Flags == MouseFlags.WheeledDown
+            || me.Flags == MouseFlags.WheeledUp
+            || me.Flags == MouseFlags.WheeledRight
+            || me.Flags == MouseFlags.WheeledLeft)
         {
         {
-            NewMouseEvent (me.MouseEvent);
+            NewMouseEvent (me);
         }
         }
-        else if (me.MouseEvent.Flags == MouseFlags.Button1Clicked)
+        else if (me.Flags == MouseFlags.Button1Clicked)
         {
         {
             Host.SetFocus ();
             Host.SetFocus ();
         }
         }

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

@@ -388,14 +388,14 @@ public class ScrollView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnKeyDown (Key a)
+    protected override bool OnKeyDown (Key a)
     {
     {
         if (base.OnKeyDown (a))
         if (base.OnKeyDown (a))
         {
         {
             return true;
             return true;
         }
         }
 
 
-        bool? result = InvokeKeyBindings (a, KeyBindingScope.HotKey | KeyBindingScope.Focused);
+        bool? result = InvokeCommands (a, KeyBindingScope.HotKey | KeyBindingScope.Focused);
 
 
         if (result is { })
         if (result is { })
         {
         {
@@ -406,7 +406,7 @@ public class ScrollView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!Enabled)
         if (!Enabled)
         {
         {
@@ -416,19 +416,19 @@ public class ScrollView : View
 
 
         if (me.Flags == MouseFlags.WheeledDown && ShowVerticalScrollIndicator)
         if (me.Flags == MouseFlags.WheeledDown && ShowVerticalScrollIndicator)
         {
         {
-            ScrollDown (1);
+            return ScrollDown (1);
         }
         }
         else if (me.Flags == MouseFlags.WheeledUp && ShowVerticalScrollIndicator)
         else if (me.Flags == MouseFlags.WheeledUp && ShowVerticalScrollIndicator)
         {
         {
-            ScrollUp (1);
+            return ScrollUp (1);
         }
         }
         else if (me.Flags == MouseFlags.WheeledRight && _showHorizontalScrollIndicator)
         else if (me.Flags == MouseFlags.WheeledRight && _showHorizontalScrollIndicator)
         {
         {
-            ScrollRight (1);
+            return ScrollRight (1);
         }
         }
         else if (me.Flags == MouseFlags.WheeledLeft && ShowVerticalScrollIndicator)
         else if (me.Flags == MouseFlags.WheeledLeft && ShowVerticalScrollIndicator)
         {
         {
-            ScrollLeft (1);
+            return ScrollLeft (1);
         }
         }
         else if (me.Position.X == _vertical.Frame.X && ShowVerticalScrollIndicator)
         else if (me.Position.X == _vertical.Frame.X && ShowVerticalScrollIndicator)
         {
         {
@@ -443,7 +443,7 @@ public class ScrollView : View
             Application.UngrabMouse ();
             Application.UngrabMouse ();
         }
         }
 
 
-        return base.OnMouseEvent (me);
+        return me.Handled;
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>

+ 2 - 4
Terminal.Gui/Views/Slider.cs

@@ -1282,7 +1282,7 @@ public class Slider<T> : View, IOrientation
     private Point? _moveRenderPosition;
     private Point? _moveRenderPosition;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         // Note(jmperricone): Maybe we click to focus the cursor, and on next click we set the option.
         // Note(jmperricone): Maybe we click to focus the cursor, and on next click we set the option.
         //                    That will make OptionFocused Event more relevant.
         //                    That will make OptionFocused Event more relevant.
@@ -1381,11 +1381,9 @@ public class Slider<T> : View, IOrientation
 
 
             mouseEvent.Handled = true;
             mouseEvent.Handled = true;
 
 
-            // BUGBUG: OnMouseClick is/should be internal. 
-            return OnMouseClick (new (mouseEvent));
         }
         }
 
 
-        return false;
+        return mouseEvent.Handled;
 
 
         Point ClampMovePosition (Point position)
         Point ClampMovePosition (Point position)
         {
         {

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

@@ -6,17 +6,17 @@ public class TabMouseEventArgs : EventArgs
     /// <summary>Creates a new instance of the <see cref="TabMouseEventArgs"/> class.</summary>
     /// <summary>Creates a new instance of the <see cref="TabMouseEventArgs"/> class.</summary>
     /// <param name="tab"><see cref="Tab"/> that the mouse was over when the event occurred.</param>
     /// <param name="tab"><see cref="Tab"/> that the mouse was over when the event occurred.</param>
     /// <param name="mouseEvent">The mouse activity being reported</param>
     /// <param name="mouseEvent">The mouse activity being reported</param>
-    public TabMouseEventArgs (Tab tab, MouseEvent mouseEvent)
+    public TabMouseEventArgs (Tab tab, MouseEventArgs mouseEvent)
     {
     {
         Tab = tab;
         Tab = tab;
         MouseEvent = mouseEvent;
         MouseEvent = mouseEvent;
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Gets the actual mouse event.  Use <see cref="MouseEvent.Handled"/> to cancel this event and perform custom
+    ///     Gets the actual mouse event.  Use <see cref="MouseEventArgs.Handled"/> to cancel this event and perform custom
     ///     behavior (e.g. show a context menu).
     ///     behavior (e.g. show a context menu).
     /// </summary>
     /// </summary>
-    public MouseEvent MouseEvent { get; }
+    public MouseEventArgs MouseEvent { get; }
 
 
     /// <summary>Gets the <see cref="Tab"/> (if any) that the mouse was over when the <see cref="MouseEvent"/> occurred.</summary>
     /// <summary>Gets the <see cref="Tab"/> (if any) that the mouse was over when the <see cref="MouseEvent"/> occurred.</summary>
     /// <remarks>This will be null if the click is after last tab or before first.</remarks>
     /// <remarks>This will be null if the click is after last tab or before first.</remarks>

+ 6 - 14
Terminal.Gui/Views/TabView.cs

@@ -508,9 +508,9 @@ public class TabView : View
         return Style.ShowTopLine ? 3 : 2;
         return Style.ShowTopLine ? 3 : 2;
     }
     }
 
 
-    private void Tab_MouseClick (object sender, MouseEventEventArgs e)
+    private void Tab_MouseClick (object sender, MouseEventArgs e)
     {
     {
-        e.Handled = _tabsBar.NewMouseEvent (e.MouseEvent) == true;
+        e.Handled = _tabsBar.NewMouseEvent (e) == true;
     }
     }
 
 
     private void UnSetCurrentTabs ()
     private void UnSetCurrentTabs ()
@@ -569,15 +569,11 @@ public class TabView : View
             Add (_rightScrollIndicator, _leftScrollIndicator);
             Add (_rightScrollIndicator, _leftScrollIndicator);
         }
         }
 
 
-        protected internal override bool OnMouseEvent (MouseEvent me)
+        protected override bool OnMouseEvent (MouseEventArgs me)
         {
         {
             Tab hit = me.View is Tab ? (Tab)me.View : null;
             Tab hit = me.View is Tab ? (Tab)me.View : null;
 
 
-            bool isClick = me.Flags.HasFlag (MouseFlags.Button1Clicked)
-                           || me.Flags.HasFlag (MouseFlags.Button2Clicked)
-                           || me.Flags.HasFlag (MouseFlags.Button3Clicked);
-
-            if (isClick)
+            if (me.IsSingleClicked)
             {
             {
                 _host.OnTabClicked (new TabMouseEventArgs (hit, me));
                 _host.OnTabClicked (new TabMouseEventArgs (hit, me));
 
 
@@ -588,9 +584,7 @@ public class TabView : View
                 }
                 }
             }
             }
 
 
-            if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
-                && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
-                && !me.Flags.HasFlag (MouseFlags.Button1TripleClicked))
+            if (!me.IsSingleDoubleOrTripleClicked)
             {
             {
                 return false;
                 return false;
             }
             }
@@ -600,9 +594,7 @@ public class TabView : View
                 SetFocus ();
                 SetFocus ();
             }
             }
 
 
-            if (me.Flags.HasFlag (MouseFlags.Button1Clicked)
-                || me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
-                || me.Flags.HasFlag (MouseFlags.Button1TripleClicked))
+            if (me.IsSingleDoubleOrTripleClicked)
             {
             {
                 var scrollIndicatorHit = 0;
                 var scrollIndicatorHit = 0;
 
 

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

@@ -150,15 +150,15 @@ public abstract class CheckBoxTableSourceWrapperBase : ITableSource
         tableView.SetNeedsDisplay ();
         tableView.SetNeedsDisplay ();
     }
     }
 
 
-    private void TableView_MouseClick (object sender, MouseEventEventArgs e)
+    private void TableView_MouseClick (object sender, MouseEventArgs e)
     {
     {
         // we only care about clicks (not movements)
         // we only care about clicks (not movements)
-        if (!e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+        if (!e.Flags.HasFlag (MouseFlags.Button1Clicked))
         {
         {
             return;
             return;
         }
         }
 
 
-        Point? hit = tableView.ScreenToCell (e.MouseEvent.Position.X, e.MouseEvent.Position.Y, out int? headerIfAny);
+        Point? hit = tableView.ScreenToCell (e.Position.X, e.Position.Y, out int? headerIfAny);
 
 
         if (headerIfAny.HasValue && headerIfAny.Value == 0)
         if (headerIfAny.HasValue && headerIfAny.Value == 0)
         {
         {

+ 14 - 12
Terminal.Gui/Views/TableView/TableView.cs

@@ -801,7 +801,7 @@ public class TableView : View
     }
     }
 
 
     ///<inheritdoc/>
     ///<inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
             && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
@@ -902,11 +902,11 @@ public class TableView : View
 
 
             if (hit is { })
             if (hit is { })
             {
             {
-                OnCellActivated (new CellActivatedEventArgs (Table, hit.Value.X, hit.Value.Y));
+                return OnCellActivated (new CellActivatedEventArgs (Table, hit.Value.X, hit.Value.Y));
             }
             }
         }
         }
 
 
-        return base.OnMouseEvent (me);
+        return me.Handled;
     }
     }
 
 
     ///<inheritdoc/>
     ///<inheritdoc/>
@@ -988,7 +988,7 @@ public class TableView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key keyEvent)
+    protected override bool OnKeyDown (Key key)
     {
     {
         if (TableIsNullOrInvisible ())
         if (TableIsNullOrInvisible ())
         {
         {
@@ -998,12 +998,14 @@ public class TableView : View
         if (CollectionNavigator != null
         if (CollectionNavigator != null
             && HasFocus
             && HasFocus
             && Table.Rows != 0
             && Table.Rows != 0
-            && CollectionNavigatorBase.IsCompatibleKey (keyEvent)
-            && !keyEvent.KeyCode.HasFlag (KeyCode.CtrlMask)
-            && !keyEvent.KeyCode.HasFlag (KeyCode.AltMask)
-            && Rune.IsLetterOrDigit ((Rune)keyEvent))
+            && key != KeyBindings.GetKeyFromCommands (Command.Accept)
+            && key != CellActivationKey
+            && CollectionNavigatorBase.IsCompatibleKey (key)
+            && !key.KeyCode.HasFlag (KeyCode.CtrlMask)
+            && !key.KeyCode.HasFlag (KeyCode.AltMask)
+            && Rune.IsLetterOrDigit ((Rune)key))
         {
         {
-            return CycleToNextTableEntryBeginningWith (keyEvent);
+            return CycleToNextTableEntryBeginningWith (key);
         }
         }
 
 
         return false;
         return false;
@@ -1561,7 +1563,7 @@ public class TableView : View
     /// <returns></returns>
     /// <returns></returns>
     private TableSelection CreateTableSelection (int x, int y) { return CreateTableSelection (x, y, x, y); }
     private TableSelection CreateTableSelection (int x, int y) { return CreateTableSelection (x, y, x, y); }
 
 
-    private bool CycleToNextTableEntryBeginningWith (Key keyEvent)
+    private bool CycleToNextTableEntryBeginningWith (Key key)
     {
     {
         int row = SelectedRow;
         int row = SelectedRow;
 
 
@@ -1571,7 +1573,7 @@ public class TableView : View
             return false;
             return false;
         }
         }
 
 
-        int match = CollectionNavigator.GetNextMatchingItem (row, (char)keyEvent);
+        int match = CollectionNavigator.GetNextMatchingItem (row, (char)key);
 
 
         if (match != -1)
         if (match != -1)
         {
         {
@@ -1644,7 +1646,7 @@ public class TableView : View
         return colStyle is { } ? colStyle.GetRepresentation (value) : value.ToString ();
         return colStyle is { } ? colStyle.GetRepresentation (value) : value.ToString ();
     }
     }
 
 
-    private bool HasControlOrAlt (MouseEvent me) { return me.Flags.HasFlag (MouseFlags.ButtonAlt) || me.Flags.HasFlag (MouseFlags.ButtonCtrl); }
+    private bool HasControlOrAlt (MouseEventArgs me) { return me.Flags.HasFlag (MouseFlags.ButtonAlt) || me.Flags.HasFlag (MouseFlags.ButtonCtrl); }
 
 
     /// <summary>
     /// <summary>
     ///     Returns true if the given <paramref name="columnIndex"/> indexes a visible column otherwise false.  Returns
     ///     Returns true if the given <paramref name="columnIndex"/> indexes a visible column otherwise false.  Returns

+ 2 - 2
Terminal.Gui/Views/TableView/TreeTableSource.cs

@@ -166,9 +166,9 @@ public class TreeTableSource<T> : IEnumerableTableSource<T>, IDisposable where T
         }
         }
     }
     }
 
 
-    private void Table_MouseClick (object sender, MouseEventEventArgs e)
+    private void Table_MouseClick (object sender, MouseEventArgs e)
     {
     {
-        Point? hit = _tableView.ScreenToCell (e.MouseEvent.Position.X, e.MouseEvent.Position.Y, out int? headerIfAny, out int? offsetX);
+        Point? hit = _tableView.ScreenToCell (e.Position.X, e.Position.Y, out int? headerIfAny, out int? offsetX);
 
 
         if (hit is null || headerIfAny is { } || !IsInTreeColumn (hit.Value.X, false) || offsetX is null)
         if (hit is null || headerIfAny is { } || !IsInTreeColumn (hit.Value.X, false) || offsetX is null)
         {
         {

+ 52 - 70
Terminal.Gui/Views/TextField.cs

@@ -459,7 +459,7 @@ public class TextField : View
     ///     Indicates whatever the text was changed or not. <see langword="true"/> if the text was changed
     ///     Indicates whatever the text was changed or not. <see langword="true"/> if the text was changed
     ///     <see langword="false"/> otherwise.
     ///     <see langword="false"/> otherwise.
     /// </summary>
     /// </summary>
-    public bool IsDirty => _historyText.IsDirty (Text);
+    public bool IsDirty => _historyText.IsDirty ([Cell.StringToCells (Text)]);
 
 
     /// <summary>If set to true its not allow any changes in the text.</summary>
     /// <summary>If set to true its not allow any changes in the text.</summary>
     public bool ReadOnly { get; set; }
     public bool ReadOnly { get; set; }
@@ -541,12 +541,12 @@ public class TextField : View
             if (!Secret && !_historyText.IsFromHistory)
             if (!Secret && !_historyText.IsFromHistory)
             {
             {
                 _historyText.Add (
                 _historyText.Add (
-                                  new() { TextModel.ToRuneCellList (oldText) },
+                                  new () { Cell.ToCellList (oldText) },
                                   new (_cursorPosition, 0)
                                   new (_cursorPosition, 0)
                                  );
                                  );
 
 
                 _historyText.Add (
                 _historyText.Add (
-                                  new() { TextModel.ToRuneCells (_text) },
+                                  new () { Cell.ToCells (_text) },
                                   new (_cursorPosition, 0),
                                   new (_cursorPosition, 0),
                                   HistoryText.LineStatus.Replaced
                                   HistoryText.LineStatus.Replaced
                                  );
                                  );
@@ -589,7 +589,7 @@ public class TextField : View
     }
     }
 
 
     /// <summary>Allows clearing the <see cref="HistoryText.HistoryTextItemEventArgs"/> items updating the original text.</summary>
     /// <summary>Allows clearing the <see cref="HistoryText.HistoryTextItemEventArgs"/> items updating the original text.</summary>
-    public void ClearHistoryChanges () { _historyText.Clear (Text); }
+    public void ClearHistoryChanges () { _historyText.Clear ([Cell.StringToCells (Text)]); }
 
 
     /// <summary>Copy the selected text to the clipboard.</summary>
     /// <summary>Copy the selected text to the clipboard.</summary>
     public virtual void Copy ()
     public virtual void Copy ()
@@ -643,7 +643,7 @@ public class TextField : View
         }
         }
 
 
         _historyText.Add (
         _historyText.Add (
-                          new() { TextModel.ToRuneCells (_text) },
+                          new () { Cell.ToCells (_text) },
                           new (_cursorPosition, 0)
                           new (_cursorPosition, 0)
                          );
                          );
 
 
@@ -697,7 +697,7 @@ public class TextField : View
         }
         }
 
 
         _historyText.Add (
         _historyText.Add (
-                          new() { TextModel.ToRuneCells (_text) },
+                          new () { Cell.ToCells (_text) },
                           new (_cursorPosition, 0)
                           new (_cursorPosition, 0)
                          );
                          );
 
 
@@ -798,16 +798,15 @@ public class TextField : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent ev)
+    protected override bool OnMouseEvent (MouseEventArgs ev)
     {
     {
-        if (!ev.Flags.HasFlag (MouseFlags.Button1Pressed)
+        if (ev is { IsPressed: false, IsReleased: false }
             && !ev.Flags.HasFlag (MouseFlags.ReportMousePosition)
             && !ev.Flags.HasFlag (MouseFlags.ReportMousePosition)
-            && !ev.Flags.HasFlag (MouseFlags.Button1Released)
             && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1TripleClicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1TripleClicked)
             && !ev.Flags.HasFlag (ContextMenu.MouseFlags))
             && !ev.Flags.HasFlag (ContextMenu.MouseFlags))
         {
         {
-            return base.OnMouseEvent (ev);
+            return false;
         }
         }
 
 
         if (!CanFocus)
         if (!CanFocus)
@@ -944,7 +943,7 @@ public class TextField : View
 
 
         int p = ScrollOffset;
         int p = ScrollOffset;
         var col = 0;
         var col = 0;
-        int width = Frame.Width + OffSetBackground ();
+        int width = Viewport.Width + OffSetBackground ();
         int tcount = _text.Count;
         int tcount = _text.Count;
         Attribute roc = GetReadOnlyColor ();
         Attribute roc = GetReadOnlyColor ();
 
 
@@ -1014,48 +1013,31 @@ public class TextField : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool? OnInvokingKeyBindings (Key a, KeyBindingScope scope)
+    protected override void OnHasFocusChanged (bool newHasFocus, View previousFocusedView, View view)
     {
     {
-        // Give autocomplete first opportunity to respond to key presses
-        if (SelectedLength == 0 && Autocomplete.Suggestions.Count > 0 && Autocomplete.ProcessKey (a))
+        if (Application.MouseGrabView is { } && Application.MouseGrabView == this)
         {
         {
-            return true;
+            Application.UngrabMouse ();
         }
         }
 
 
-        return base.OnInvokingKeyBindings (a, scope);
+        //if (SelectedLength != 0 && !(Application.MouseGrabView is MenuBar))
+        //	ClearAllSelection ();
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected override void OnHasFocusChanged (bool newHasFocus, View previousFocusedView, View view)
+    protected override bool OnKeyDown (Key key)
     {
     {
-        if (Application.MouseGrabView is { } && Application.MouseGrabView == this)
+        // Give autocomplete first opportunity to respond to key presses
+        if (SelectedLength == 0 && Autocomplete.Suggestions.Count > 0 && Autocomplete.ProcessKey (key))
         {
         {
-            Application.UngrabMouse ();
+            return true;
         }
         }
 
 
-        //if (SelectedLength != 0 && !(Application.MouseGrabView is MenuBar))
-        //	ClearAllSelection ();
+        return false;
     }
     }
 
 
-    /// TODO: Flush out these docs
-    /// <summary>
-    ///     Processes key presses for the <see cref="TextField"/>.
-    ///     <remarks>
-    ///         The <see cref="TextField"/> control responds to the following keys:
-    ///         <list type="table">
-    ///             <listheader>
-    ///                 <term>Keys</term> <description>Function</description>
-    ///             </listheader>
-    ///             <item>
-    ///                 <term><see cref="Key.Delete"/>, <see cref="Key.Backspace"/></term>
-    ///                 <description>Deletes the character before cursor.</description>
-    ///             </item>
-    ///         </list>
-    ///     </remarks>
-    /// </summary>
-    /// <param name="a"></param>
-    /// <returns></returns>
-    public override bool OnProcessKeyDown (Key a)
+    /// <inheritdoc />
+    protected override bool OnKeyDownNotHandled (Key a)
     {
     {
         // Remember the cursor position because the new calculated cursor position is needed
         // Remember the cursor position because the new calculated cursor position is needed
         // to be set BEFORE the TextChanged event is triggered.
         // to be set BEFORE the TextChanged event is triggered.
@@ -1130,10 +1112,10 @@ public class TextField : View
             }
             }
 
 
             int cols = _text [idx].GetColumns ();
             int cols = _text [idx].GetColumns ();
-            TextModel.SetCol (ref col, Frame.Width - 1, cols);
+            TextModel.SetCol (ref col, Viewport.Width - 1, cols);
         }
         }
 
 
-        int pos = _cursorPosition - ScrollOffset + Math.Min (Frame.X, 0);
+        int pos = _cursorPosition - ScrollOffset + Math.Min (Viewport.X, 0);
         Move (pos, 0);
         Move (pos, 0);
 
 
         return new Point (pos, 0);
         return new Point (pos, 0);
@@ -1216,16 +1198,16 @@ public class TextField : View
             ScrollOffset = _cursorPosition;
             ScrollOffset = _cursorPosition;
             need = true;
             need = true;
         }
         }
-        else if (Frame.Width > 0
-                 && (ScrollOffset + _cursorPosition - (Frame.Width + offB) == 0
-                     || TextModel.DisplaySize (_text, ScrollOffset, _cursorPosition).size >= Frame.Width + offB))
+        else if (Viewport.Width > 0
+                 && (ScrollOffset + _cursorPosition - (Viewport.Width + offB) == 0
+                     || TextModel.DisplaySize (_text, ScrollOffset, _cursorPosition).size >= Viewport.Width + offB))
         {
         {
             ScrollOffset = Math.Max (
             ScrollOffset = Math.Max (
                                      TextModel.CalculateLeftColumn (
                                      TextModel.CalculateLeftColumn (
                                                                     _text,
                                                                     _text,
                                                                     ScrollOffset,
                                                                     ScrollOffset,
                                                                     _cursorPosition,
                                                                     _cursorPosition,
-                                                                    Frame.Width + offB
+                                                                    Viewport.Width + offB
                                                                    ),
                                                                    ),
                                      0
                                      0
                                     );
                                     );
@@ -1330,7 +1312,7 @@ public class TextField : View
 
 
     private void GenerateSuggestions ()
     private void GenerateSuggestions ()
     {
     {
-        List<RuneCell> currentLine = TextModel.ToRuneCellList (Text);
+        List<Cell> currentLine = Cell.ToCellList (Text);
         int cursorPosition = Math.Min (CursorPosition, currentLine.Count);
         int cursorPosition = Math.Min (CursorPosition, currentLine.Count);
 
 
         Autocomplete.Context = new (
         Autocomplete.Context = new (
@@ -1378,7 +1360,7 @@ public class TextField : View
             return;
             return;
         }
         }
 
 
-        Text = TextModel.ToString (obj?.Lines [obj.CursorPosition.Y]);
+        Text = Cell.ToString (obj?.Lines [obj.CursorPosition.Y]);
         CursorPosition = obj.CursorPosition.X;
         CursorPosition = obj.CursorPosition.X;
         Adjust ();
         Adjust ();
     }
     }
@@ -1386,7 +1368,7 @@ public class TextField : View
     private void InsertText (Key a, bool usePreTextChangedCursorPos)
     private void InsertText (Key a, bool usePreTextChangedCursorPos)
     {
     {
         _historyText.Add (
         _historyText.Add (
-                          new() { TextModel.ToRuneCells (_text) },
+                          new () { Cell.ToCells (_text) },
                           new (_cursorPosition, 0)
                           new (_cursorPosition, 0)
                          );
                          );
 
 
@@ -1519,18 +1501,28 @@ public class TextField : View
         }
         }
     }
     }
 
 
-    private bool MoveLeft ()
+    /// <summary>
+    /// Moves the cursor +/- the given <paramref name="distance"/>, clearing
+    /// any selection and returning true if any meaningful changes were made.
+    /// </summary>
+    /// <param name="distance">Distance to move the cursor, will be clamped to
+    /// text length. Positive for right, Negative for left.</param>
+    /// <returns></returns>
+    private bool Move (int distance)
     {
     {
-        if (_cursorPosition > 0)
-        {
-            ClearAllSelection ();
-            _cursorPosition--;
-            Adjust ();
+        var oldCursorPosition = _cursorPosition;
+        var hadSelection = _selectedText != null && _selectedText.Length > 0;
 
 
-            return true;
-        }
+        _cursorPosition = Math.Min (_text.Count, Math.Max (0, _cursorPosition + distance));
+        ClearAllSelection ();
+        Adjust ();
 
 
-        return false;
+        return _cursorPosition != oldCursorPosition || hadSelection;
+    }
+
+    private bool MoveLeft ()
+    {
+        return Move (-1);
     }
     }
 
 
     private void MoveLeftExtend ()
     private void MoveLeftExtend ()
@@ -1543,17 +1535,7 @@ public class TextField : View
 
 
     private bool MoveRight ()
     private bool MoveRight ()
     {
     {
-        if (_cursorPosition == _text.Count)
-        {
-            return false;
-        }
-
-        ClearAllSelection ();
-
-        _cursorPosition++;
-        Adjust ();
-
-        return true;
+        return Move (1);
     }
     }
 
 
     private void MoveRightExtend ()
     private void MoveRightExtend ()
@@ -1662,7 +1644,7 @@ public class TextField : View
         return 0; //offB;
         return 0; //offB;
     }
     }
 
 
-    private int PositionCursor (MouseEvent ev) { return PositionCursor (TextModel.GetColFromX (_text, ScrollOffset, ev.Position.X), false); }
+    private int PositionCursor (MouseEventArgs ev) { return PositionCursor (TextModel.GetColFromX (_text, ScrollOffset, ev.Position.X), false); }
 
 
     private int PositionCursor (int x, bool getX = true)
     private int PositionCursor (int x, bool getX = true)
     {
     {

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

@@ -531,7 +531,7 @@ namespace Terminal.Gui
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+        protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
         {
         {
             if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
             if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
             {
             {
@@ -597,7 +597,7 @@ namespace Terminal.Gui
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        public override bool OnProcessKeyDown (Key a)
+        protected override bool OnKeyDownNotHandled (Key a)
         {
         {
             if (_provider is null)
             if (_provider is null)
             {
             {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 270 - 254
Terminal.Gui/Views/TextView.cs


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

@@ -286,11 +286,11 @@ public class TileView : View
 
 
     //// BUGBUG: Why is this not handled by a key binding???
     //// BUGBUG: Why is this not handled by a key binding???
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key keyEvent)
+    protected override bool OnKeyDownNotHandled (Key key)
     {
     {
         var focusMoved = false;
         var focusMoved = false;
 
 
-        if (keyEvent.KeyCode == ToggleResizable)
+        if (key.KeyCode == ToggleResizable)
         {
         {
             foreach (TileViewLineView l in _splitterLines)
             foreach (TileViewLineView l in _splitterLines)
             {
             {
@@ -910,7 +910,7 @@ public class TileView : View
             }
             }
         }
         }
 
 
-        protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+        protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
         {
         {
             if (!dragPosition.HasValue && mouseEvent.Flags == MouseFlags.Button1Pressed)
             if (!dragPosition.HasValue && mouseEvent.Flags == MouseFlags.Button1Pressed)
             {
             {

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

@@ -163,21 +163,24 @@ public class TimeField : TextField
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent  (MouseEvent ev)
+    protected override bool OnMouseEvent  (MouseEventArgs ev)
     {
     {
-        bool result = base.OnMouseEvent (ev);
+        if (base.OnMouseEvent (ev) || ev.Handled)
+        {
+            return true;
+        }
 
 
-        if (result && SelectedLength == 0 && ev.Flags.HasFlag (MouseFlags.Button1Pressed))
+        if (SelectedLength == 0 && ev.Flags.HasFlag (MouseFlags.Button1Pressed))
         {
         {
             int point = ev.Position.X;
             int point = ev.Position.X;
             AdjCursorPosition (point);
             AdjCursorPosition (point);
         }
         }
 
 
-        return result;
+        return ev.Handled;
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key a)
+    protected override bool OnKeyDownNotHandled (Key a)
     {
     {
         // Ignore non-numeric characters.
         // Ignore non-numeric characters.
         if (a.KeyCode is >= (KeyCode)(int)KeyCode.D0 and <= (KeyCode)(int)KeyCode.D9)
         if (a.KeyCode is >= (KeyCode)(int)KeyCode.D0 and <= (KeyCode)(int)KeyCode.D9)
@@ -227,7 +230,7 @@ public class TimeField : TextField
             CursorPosition = newPoint;
             CursorPosition = newPoint;
         }
         }
 
 
-        while (Text [CursorPosition] == _sepChar [0])
+        while (CursorPosition < Text.GetColumns() -1 && Text [CursorPosition] == _sepChar [0])
         {
         {
             if (increment)
             if (increment)
             {
             {

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

@@ -62,7 +62,7 @@ public partial class Toplevel : View
     /// </summary>
     /// </summary>
     public bool Modal { get; set; }
     public bool Modal { get; set; }
 
 
-    private void Toplevel_MouseClick (object? sender, MouseEventEventArgs e) { e.Handled = InvokeCommand (Command.HotKey) == true; }
+    private void Toplevel_MouseClick (object? sender, MouseEventArgs e) { e.Handled = InvokeCommand (Command.HotKey) == true; }
 
 
     #endregion
     #endregion
 
 

+ 9 - 9
Terminal.Gui/Views/TreeView/Branch.cs

@@ -75,7 +75,7 @@ internal class Branch<T> where T : class
     /// <param name="availableWidth"></param>
     /// <param name="availableWidth"></param>
     public virtual void Draw (ConsoleDriver driver, ColorScheme colorScheme, int y, int availableWidth)
     public virtual void Draw (ConsoleDriver driver, ColorScheme colorScheme, int y, int availableWidth)
     {
     {
-        List<RuneCell> cells = new ();
+        List<Cell> cells = new ();
         int? indexOfExpandCollapseSymbol = null;
         int? indexOfExpandCollapseSymbol = null;
         int indexOfModelText;
         int indexOfModelText;
 
 
@@ -106,7 +106,7 @@ internal class Branch<T> where T : class
             }
             }
             else
             else
             {
             {
-                cells.Add (NewRuneCell (attr, r));
+                cells.Add (NewCell (attr, r));
                 availableWidth -= r.GetColumns ();
                 availableWidth -= r.GetColumns ();
             }
             }
         }
         }
@@ -148,7 +148,7 @@ internal class Branch<T> where T : class
         else
         else
         {
         {
             indexOfExpandCollapseSymbol = cells.Count;
             indexOfExpandCollapseSymbol = cells.Count;
-            cells.Add (NewRuneCell (attr, expansion));
+            cells.Add (NewCell (attr, expansion));
             availableWidth -= expansion.GetColumns ();
             availableWidth -= expansion.GetColumns ();
         }
         }
 
 
@@ -211,7 +211,7 @@ internal class Branch<T> where T : class
         }
         }
 
 
         attr = modelColor;
         attr = modelColor;
-        cells.AddRange (lineBody.Select (r => NewRuneCell (attr, new Rune (r))));
+        cells.AddRange (lineBody.Select (r => NewCell (attr, new Rune (r))));
 
 
         if (availableWidth > 0)
         if (availableWidth > 0)
         {
         {
@@ -219,7 +219,7 @@ internal class Branch<T> where T : class
 
 
             cells.AddRange (
             cells.AddRange (
                             Enumerable.Repeat (
                             Enumerable.Repeat (
-                                               NewRuneCell (attr, new Rune (' ')),
+                                               NewCell (attr, new Rune (' ')),
                                                availableWidth
                                                availableWidth
                                               )
                                               )
                            );
                            );
@@ -229,7 +229,7 @@ internal class Branch<T> where T : class
         {
         {
             Model = Model,
             Model = Model,
             Y = y,
             Y = y,
-            RuneCells = cells,
+            Cells = cells,
             Tree = tree,
             Tree = tree,
             IndexOfExpandCollapseSymbol =
             IndexOfExpandCollapseSymbol =
                 indexOfExpandCollapseSymbol,
                 indexOfExpandCollapseSymbol,
@@ -239,9 +239,9 @@ internal class Branch<T> where T : class
 
 
         if (!e.Handled)
         if (!e.Handled)
         {
         {
-            foreach (RuneCell cell in cells)
+            foreach (Cell cell in cells)
             {
             {
-                driver.SetAttribute (cell.ColorScheme.Normal);
+                driver.SetAttribute ((Attribute)cell.Attribute!);
                 driver.AddRune (cell.Rune);
                 driver.AddRune (cell.Rune);
             }
             }
         }
         }
@@ -529,5 +529,5 @@ internal class Branch<T> where T : class
         return Parent.ChildBranches.Values.LastOrDefault () == this;
         return Parent.ChildBranches.Values.LastOrDefault () == this;
     }
     }
 
 
-    private static RuneCell NewRuneCell (Attribute attr, Rune r) { return new RuneCell { Rune = r, ColorScheme = new ColorScheme (attr) }; }
+    private static Cell NewCell (Attribute attr, Rune r) { return new Cell { Rune = r, Attribute = new (attr) }; }
 }
 }

+ 4 - 4
Terminal.Gui/Views/TreeView/DrawTreeViewLineEventArgs.cs

@@ -12,16 +12,16 @@ public class DrawTreeViewLineEventArgs<T> where T : class
     public bool Handled { get; set; }
     public bool Handled { get; set; }
 
 
     /// <summary>
     /// <summary>
-    ///     If line contains a branch that can be expanded/collapsed then this is the index in <see cref="RuneCells"/> at
+    ///     If line contains a branch that can be expanded/collapsed then this is the index in <see cref="Cells"/> at
     ///     which the symbol is (or null for leaf elements).
     ///     which the symbol is (or null for leaf elements).
     /// </summary>
     /// </summary>
     public int? IndexOfExpandCollapseSymbol { get; init; }
     public int? IndexOfExpandCollapseSymbol { get; init; }
 
 
     /// <summary>
     /// <summary>
-    ///     The notional index in <see cref="RuneCells"/> which contains the first character of the
+    ///     The notional index in <see cref="Cells"/> which contains the first character of the
     ///     <see cref="TreeView{T}.AspectGetter"/> text (i.e. after all branch lines and expansion/collapse symbols).
     ///     <see cref="TreeView{T}.AspectGetter"/> text (i.e. after all branch lines and expansion/collapse symbols).
     /// </summary>
     /// </summary>
-    /// <remarks>May be negative or outside of bounds of <see cref="RuneCells"/> if the view has been scrolled horizontally.</remarks>
+    /// <remarks>May be negative or outside of bounds of <see cref="Cells"/> if the view has been scrolled horizontally.</remarks>
     public int IndexOfModelText { get; init; }
     public int IndexOfModelText { get; init; }
 
 
     /// <summary>The object at this line in the tree</summary>
     /// <summary>The object at this line in the tree</summary>
@@ -32,7 +32,7 @@ public class DrawTreeViewLineEventArgs<T> where T : class
     ///     respected.  You can modify these to change what is rendered.
     ///     respected.  You can modify these to change what is rendered.
     /// </summary>
     /// </summary>
     /// <remarks>Changing the length of this collection may result in corrupt rendering</remarks>
     /// <remarks>Changing the length of this collection may result in corrupt rendering</remarks>
-    public List<RuneCell> RuneCells { get; init; }
+    public List<Cell> Cells { get; init; }
 
 
     /// <summary>The <see cref="TreeView{T}"/> that is performing the rendering.</summary>
     /// <summary>The <see cref="TreeView{T}"/> that is performing the rendering.</summary>
     public TreeView<T> Tree { get; init; }
     public TreeView<T> Tree { get; init; }

+ 8 - 15
Terminal.Gui/Views/TreeView/TreeView.cs

@@ -990,18 +990,14 @@ public class TreeView<T> : View, ITreeView where T : class
 
 
     // BUGBUG: OnMouseEvent is internal. TreeView should not be overriding.
     // BUGBUG: OnMouseEvent is internal. TreeView should not be overriding.
     ///<inheritdoc/>
     ///<inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         // If it is not an event we care about
         // If it is not an event we care about
-        if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
-            && !me.Flags.HasFlag (ObjectActivationButton ?? MouseFlags.Button1DoubleClicked)
-            && !me.Flags.HasFlag (MouseFlags.WheeledDown)
-            && !me.Flags.HasFlag (MouseFlags.WheeledUp)
-            && !me.Flags.HasFlag (MouseFlags.WheeledRight)
-            && !me.Flags.HasFlag (MouseFlags.WheeledLeft))
+        if (me is { IsSingleClicked: false, IsPressed: false, IsReleased: false, IsWheel: false }
+            && !me.Flags.HasFlag (ObjectActivationButton ?? MouseFlags.Button1DoubleClicked))
         {
         {
             // do nothing
             // do nothing
-            return base.OnMouseEvent (me);
+            return false;
         }
         }
 
 
         if (!HasFocus && CanFocus)
         if (!HasFocus && CanFocus)
@@ -1182,26 +1178,23 @@ public class TreeView<T> : View, ITreeView where T : class
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key keyEvent)
+    protected override bool OnKeyDown (Key key)
     {
     {
         if (!Enabled)
         if (!Enabled)
         {
         {
             return false;
             return false;
         }
         }
 
 
-        // BUGBUG: this should move to OnInvokingKeyBindings
         // If not a keybinding, is the key a searchable key press?
         // If not a keybinding, is the key a searchable key press?
-        if (CollectionNavigatorBase.IsCompatibleKey (keyEvent) && AllowLetterBasedNavigation)
+        if (CollectionNavigatorBase.IsCompatibleKey (key) && AllowLetterBasedNavigation)
         {
         {
-            IReadOnlyCollection<Branch<T>> map;
-
             // If there has been a call to InvalidateMap since the last time
             // If there has been a call to InvalidateMap since the last time
             // we need a new one to reflect the new exposed tree state
             // we need a new one to reflect the new exposed tree state
-            map = BuildLineMap ();
+            IReadOnlyCollection<Branch<T>> map = BuildLineMap ();
 
 
             // Find the current selected object within the tree
             // Find the current selected object within the tree
             int current = map.IndexOf (b => b.Model == SelectedObject);
             int current = map.IndexOf (b => b.Model == SelectedObject);
-            int? newIndex = KeystrokeNavigator?.GetNextMatchingItem (current, (char)keyEvent);
+            int? newIndex = KeystrokeNavigator?.GetNextMatchingItem (current, (char)key);
 
 
             if (newIndex is int && newIndex != -1)
             if (newIndex is int && newIndex != -1)
             {
             {

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

@@ -381,12 +381,12 @@ public class Wizard : Dialog
     /// <summary>
     /// <summary>
     ///     <see cref="Wizard"/> is derived from <see cref="Dialog"/> and Dialog causes <c>Esc</c> to call
     ///     <see cref="Wizard"/> is derived from <see cref="Dialog"/> and Dialog causes <c>Esc</c> to call
     ///     <see cref="Application.RequestStop(Toplevel)"/>, closing the Dialog. Wizard overrides
     ///     <see cref="Application.RequestStop(Toplevel)"/>, closing the Dialog. Wizard overrides
-    ///     <see cref="OnProcessKeyDown"/> to instead fire the <see cref="Cancelled"/> event when Wizard is being used as a
+    ///     <see cref="OnKeyDownNotHandled"/> to instead fire the <see cref="Cancelled"/> event when Wizard is being used as a
     ///     non-modal (see <see cref="Wizard.Modal"/>).
     ///     non-modal (see <see cref="Wizard.Modal"/>).
     /// </summary>
     /// </summary>
     /// <param name="key"></param>
     /// <param name="key"></param>
     /// <returns></returns>
     /// <returns></returns>
-    public override bool OnProcessKeyDown (Key key)
+    protected override bool OnKeyDownNotHandled (Key key)
     {
     {
         //// BUGBUG: Why is this not handled by a key binding???
         //// BUGBUG: Why is this not handled by a key binding???
         if (!Modal)
         if (!Modal)

+ 4 - 4
UICatalog/Scenarios/ASCIICustomButton.cs

@@ -127,7 +127,7 @@ public class ASCIICustomButtonTest : Scenario
         }
         }
 
 
         public event Action<ASCIICustomButton> PointerEnter;
         public event Action<ASCIICustomButton> PointerEnter;
-        private void This_MouseClick (object sender, MouseEventEventArgs obj) { NewMouseEvent (obj.MouseEvent); }
+        private void This_MouseClick (object sender, MouseEventArgs obj) { NewMouseEvent (obj); }
     }
     }
 
 
     public class ScrollViewTestWindow : Window
     public class ScrollViewTestWindow : Window
@@ -310,9 +310,9 @@ public class ASCIICustomButtonTest : Scenario
             }
             }
         }
         }
 
 
-        private void Button_MouseClick (object sender, MouseEventEventArgs obj)
+        private void Button_MouseClick (object sender, MouseEventArgs obj)
         {
         {
-            if (obj.MouseEvent.Flags == MouseFlags.WheeledDown)
+            if (obj.Flags == MouseFlags.WheeledDown)
             {
             {
                 _scrollView.ContentOffset = new Point (
                 _scrollView.ContentOffset = new Point (
                                                        _scrollView.ContentOffset.X,
                                                        _scrollView.ContentOffset.X,
@@ -320,7 +320,7 @@ public class ASCIICustomButtonTest : Scenario
                                                       );
                                                       );
                 obj.Handled = true;
                 obj.Handled = true;
             }
             }
-            else if (obj.MouseEvent.Flags == MouseFlags.WheeledUp)
+            else if (obj.Flags == MouseFlags.WheeledUp)
             {
             {
                 _scrollView.ContentOffset = new Point (
                 _scrollView.ContentOffset = new Point (
                                                        _scrollView.ContentOffset.X,
                                                        _scrollView.ContentOffset.X,

+ 1 - 1
UICatalog/Scenarios/AdornmentsEditor.cs

@@ -108,7 +108,7 @@ public class AdornmentsEditor : View
         ViewToEdit = Application.Navigation!.GetFocused ();
         ViewToEdit = Application.Navigation!.GetFocused ();
     }
     }
 
 
-    private void ApplicationOnMouseEvent (object? sender, MouseEvent e)
+    private void ApplicationOnMouseEvent (object? sender, MouseEventArgs e)
     {
     {
         if (e.Flags != MouseFlags.Button1Clicked || !AutoSelectViewToEdit)
         if (e.Flags != MouseFlags.Button1Clicked || !AutoSelectViewToEdit)
         {
         {

+ 1 - 1
UICatalog/Scenarios/ArrangementEditor.cs

@@ -147,7 +147,7 @@ public sealed class ArrangementEditor : View
         }
         }
     }
     }
 
 
-    private void ApplicationOnMouseEvent (object? sender, MouseEvent e)
+    private void ApplicationOnMouseEvent (object? sender, MouseEventArgs e)
     {
     {
         if (e.Flags != MouseFlags.Button1Clicked || !AutoSelectViewToEdit)
         if (e.Flags != MouseFlags.Button1Clicked || !AutoSelectViewToEdit)
         {
         {

+ 8 - 8
UICatalog/Scenarios/Bars.cs

@@ -187,12 +187,12 @@ public class Bars : Scenario
 
 
         menuLikeExamples.MouseClick += MenuLikeExamplesMouseClick;
         menuLikeExamples.MouseClick += MenuLikeExamplesMouseClick;
 
 
-        void MenuLikeExamplesMouseClick (object sender, MouseEventEventArgs e)
+        void MenuLikeExamplesMouseClick (object sender, MouseEventArgs e)
         {
         {
-            if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked))
+            if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
             {
             {
-                popOverMenu.X = e.MouseEvent.Position.X;
-                popOverMenu.Y = e.MouseEvent.Position.Y;
+                popOverMenu.X = e.Position.X;
+                popOverMenu.Y = e.Position.Y;
                 popOverMenu.Visible = true;
                 popOverMenu.Visible = true;
                 //popOverMenu.Enabled = popOverMenu.Visible;
                 //popOverMenu.Enabled = popOverMenu.Visible;
                 popOverMenu.SetFocus ();
                 popOverMenu.SetFocus ();
@@ -275,7 +275,7 @@ public class Bars : Scenario
 
 
     //private void ShowContextMenu (object s, MouseEventEventArgs e)
     //private void ShowContextMenu (object s, MouseEventEventArgs e)
     //{
     //{
-    //    if (e.MouseEvent.Flags != MouseFlags.Button3Clicked)
+    //    if (e.Flags != MouseFlags.Button3Clicked)
     //    {
     //    {
     //        return;
     //        return;
     //    }
     //    }
@@ -283,8 +283,8 @@ public class Bars : Scenario
     //    var contextMenu = new Bar
     //    var contextMenu = new Bar
     //    {
     //    {
     //        Id = "contextMenu",
     //        Id = "contextMenu",
-    //        X = e.MouseEvent.Position.X,
-    //        Y = e.MouseEvent.Position.Y,
+    //        X = e.Position.X,
+    //        Y = e.Position.Y,
     //        Width = Dim.Auto (DimAutoStyle.Content),
     //        Width = Dim.Auto (DimAutoStyle.Content),
     //        Height = Dim.Auto (DimAutoStyle.Content),
     //        Height = Dim.Auto (DimAutoStyle.Content),
     //        Orientation = Orientation.Vertical,
     //        Orientation = Orientation.Vertical,
@@ -387,7 +387,7 @@ public class Bars : Scenario
 
 
     //    contextMenu.Initialized += Menu_Initialized;
     //    contextMenu.Initialized += Menu_Initialized;
 
 
-    //    void Application_MouseEvent (object sender, MouseEvent e)
+    //    void Application_MouseEvent (object sender, MouseEventArgs e)
     //    {
     //    {
     //        // If user clicks outside of the menuWindow, close it
     //        // If user clicks outside of the menuWindow, close it
     //        if (!contextMenu.Frame.Contains (e.Position.X, e.Position.Y))
     //        if (!contextMenu.Frame.Contains (e.Position.X, e.Position.Y))

+ 9 - 11
UICatalog/Scenarios/CharacterMap.cs

@@ -98,9 +98,9 @@ public class CharacterMap : Scenario
         // if user clicks the mouse in TableView
         // if user clicks the mouse in TableView
         _categoryList.MouseClick += (s, e) =>
         _categoryList.MouseClick += (s, e) =>
                                     {
                                     {
-                                        _categoryList.ScreenToCell (e.MouseEvent.Position, out int? clickedCol);
+                                        _categoryList.ScreenToCell (e.Position, out int? clickedCol);
 
 
-                                        if (clickedCol != null && e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+                                        if (clickedCol != null && e.Flags.HasFlag (MouseFlags.Button1Clicked))
                                         {
                                         {
                                             EnumerableTableSource<UnicodeRange> table = (EnumerableTableSource<UnicodeRange>)_categoryList.Table;
                                             EnumerableTableSource<UnicodeRange> table = (EnumerableTableSource<UnicodeRange>)_categoryList.Table;
                                             string prevSelection = table.Data.ElementAt (_categoryList.SelectedRow).Category;
                                             string prevSelection = table.Data.ElementAt (_categoryList.SelectedRow).Category;
@@ -527,9 +527,9 @@ internal class CharMap : View
         Padding.Add (up, down, left, right);
         Padding.Add (up, down, left, right);
     }
     }
 
 
-    private void Handle_MouseEvent (object sender, MouseEventEventArgs e)
+    private void Handle_MouseEvent (object sender, MouseEventArgs e)
     {
     {
-        if (e.MouseEvent.Flags == MouseFlags.WheeledDown)
+        if (e.Flags == MouseFlags.WheeledDown)
         {
         {
             ScrollVertical (1);
             ScrollVertical (1);
             e.Handled = true;
             e.Handled = true;
@@ -537,7 +537,7 @@ internal class CharMap : View
             return;
             return;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledUp)
+        if (e.Flags == MouseFlags.WheeledUp)
         {
         {
             ScrollVertical (-1);
             ScrollVertical (-1);
             e.Handled = true;
             e.Handled = true;
@@ -545,7 +545,7 @@ internal class CharMap : View
             return;
             return;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledRight)
+        if (e.Flags == MouseFlags.WheeledRight)
         {
         {
             ScrollHorizontal (1);
             ScrollHorizontal (1);
             e.Handled = true;
             e.Handled = true;
@@ -553,7 +553,7 @@ internal class CharMap : View
             return;
             return;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledLeft)
+        if (e.Flags == MouseFlags.WheeledLeft)
         {
         {
             ScrollHorizontal (-1);
             ScrollHorizontal (-1);
             e.Handled = true;
             e.Handled = true;
@@ -839,10 +839,8 @@ internal class CharMap : View
     private void CopyCodePoint () { Clipboard.Contents = $"U+{SelectedCodePoint:x5}"; }
     private void CopyCodePoint () { Clipboard.Contents = $"U+{SelectedCodePoint:x5}"; }
     private void CopyGlyph () { Clipboard.Contents = $"{new Rune (SelectedCodePoint)}"; }
     private void CopyGlyph () { Clipboard.Contents = $"{new Rune (SelectedCodePoint)}"; }
 
 
-    private void Handle_MouseClick (object sender, MouseEventEventArgs args)
+    private void Handle_MouseClick (object sender, MouseEventArgs me)
     {
     {
-        MouseEvent me = args.MouseEvent;
-
         if (me.Flags != MouseFlags.ReportMousePosition && me.Flags != MouseFlags.Button1Clicked && me.Flags != MouseFlags.Button1DoubleClicked)
         if (me.Flags != MouseFlags.ReportMousePosition && me.Flags != MouseFlags.Button1Clicked && me.Flags != MouseFlags.Button1DoubleClicked)
         {
         {
             return;
             return;
@@ -883,7 +881,7 @@ internal class CharMap : View
             SetFocus ();
             SetFocus ();
         }
         }
 
 
-        args.Handled = true;
+        me.Handled = true;
 
 
         if (me.Flags == MouseFlags.Button1Clicked)
         if (me.Flags == MouseFlags.Button1Clicked)
         {
         {

+ 5 - 5
UICatalog/Scenarios/ContentScrolling.cs

@@ -52,30 +52,30 @@ public class ContentScrolling : Scenario
             MouseEvent += VirtualDemoView_MouseEvent;
             MouseEvent += VirtualDemoView_MouseEvent;
         }
         }
 
 
-        private void VirtualDemoView_MouseEvent (object sender, MouseEventEventArgs e)
+        private void VirtualDemoView_MouseEvent (object sender, MouseEventArgs e)
         {
         {
-            if (e.MouseEvent.Flags == MouseFlags.WheeledDown)
+            if (e.Flags == MouseFlags.WheeledDown)
             {
             {
                 ScrollVertical (1);
                 ScrollVertical (1);
 
 
                 return;
                 return;
             }
             }
 
 
-            if (e.MouseEvent.Flags == MouseFlags.WheeledUp)
+            if (e.Flags == MouseFlags.WheeledUp)
             {
             {
                 ScrollVertical (-1);
                 ScrollVertical (-1);
 
 
                 return;
                 return;
             }
             }
 
 
-            if (e.MouseEvent.Flags == MouseFlags.WheeledRight)
+            if (e.Flags == MouseFlags.WheeledRight)
             {
             {
                 ScrollHorizontal (1);
                 ScrollHorizontal (1);
 
 
                 return;
                 return;
             }
             }
 
 
-            if (e.MouseEvent.Flags == MouseFlags.WheeledLeft)
+            if (e.Flags == MouseFlags.WheeledLeft)
             {
             {
                 ScrollHorizontal (-1);
                 ScrollHorizontal (-1);
             }
             }

+ 3 - 3
UICatalog/Scenarios/ContextMenus.cs

@@ -75,16 +75,16 @@ public class ContextMenus : Scenario
 
 
         appWindow.MouseClick += (s, e) =>
         appWindow.MouseClick += (s, e) =>
                                 {
                                 {
-                                    if (e.MouseEvent.Flags == _contextMenu.MouseFlags)
+                                    if (e.Flags == _contextMenu.MouseFlags)
                                     {
                                     {
-                                        ShowContextMenu (e.MouseEvent.Position.X, e.MouseEvent.Position.Y);
+                                        ShowContextMenu (e.Position.X, e.Position.Y);
                                         e.Handled = true;
                                         e.Handled = true;
                                     }
                                     }
                                 };
                                 };
 
 
         Application.MouseEvent += ApplicationMouseEvent;
         Application.MouseEvent += ApplicationMouseEvent;
 
 
-        void ApplicationMouseEvent (object sender, MouseEvent a) { mousePos = a.Position; }
+        void ApplicationMouseEvent (object sender, MouseEventArgs a) { mousePos = a.Position; }
 
 
         appWindow.WantMousePositionReports = true;
         appWindow.WantMousePositionReports = true;
 
 

+ 9 - 1
UICatalog/Scenarios/Editor.cs

@@ -202,7 +202,15 @@ public class Editor : Scenario
                          CreateWrapChecked (),
                          CreateWrapChecked (),
                          CreateAutocomplete (),
                          CreateAutocomplete (),
                          CreateAllowsTabChecked (),
                          CreateAllowsTabChecked (),
-                         CreateReadOnlyChecked ()
+                         CreateReadOnlyChecked (),
+                         new MenuItem (
+                                       "Colors",
+                                       "",
+                                       () => _textView.PromptForColors (),
+                                       null,
+                                       null,
+                                       KeyCode.CtrlMask | KeyCode.L
+                                      )
                      }
                      }
                     ),
                     ),
                 new (
                 new (

+ 92 - 70
UICatalog/Scenarios/Keys.cs

@@ -10,120 +10,142 @@ public class Keys : Scenario
     public override void Main ()
     public override void Main ()
     {
     {
         Application.Init ();
         Application.Init ();
-        ObservableCollection<string> keyPressedList = [];
-        ObservableCollection<string> invokingKeyBindingsList = new ();
+        ObservableCollection<string> keyDownList = [];
+        ObservableCollection<string> keyDownNotHandledList = new ();
 
 
         var win = new Window { Title = GetQuitKeyAndName () };
         var win = new Window { Title = GetQuitKeyAndName () };
-        var editLabel = new Label { X = 0, Y = 0, Text = "Type text here:" };
-        win.Add (editLabel);
 
 
-        var edit = new TextField { X = Pos.Right (editLabel) + 1, Y = Pos.Top (editLabel), Width = Dim.Fill (2) };
+        var label = new Label
+        {
+            X = 0,
+            Y = 0,
+            Text = "_Type text here:"
+        };
+        win.Add (label);
+
+        var edit = new TextField
+        {
+            X = Pos.Right (label) + 1,
+            Y = Pos.Top (label),
+            Width = Dim.Fill (2),
+            Height = 1,
+        };
         win.Add (edit);
         win.Add (edit);
 
 
-        edit.KeyDown += (s, a) => { keyPressedList.Add (a.ToString ()); };
+        label = new Label
+        {
+            X = 0,
+            Y = Pos.Bottom (label),
+            Text = "Last _Application.KeyDown:"
+        };
+        win.Add (label);
+        var labelAppKeypress = new Label
+        {
+            X = Pos.Right (label) + 1,
+            Y = Pos.Top (label)
+        };
+        win.Add (labelAppKeypress);
 
 
-        edit.InvokingKeyBindings += (s, a) =>
-                                    {
-                                        if (edit.KeyBindings.TryGet (a, out KeyBinding binding))
-                                        {
-                                            invokingKeyBindingsList.Add ($"{a}: {string.Join (",", binding.Commands)}");
-                                        }
-                                    };
+        Application.KeyDown += (s, e) => labelAppKeypress.Text = e.ToString ();
 
 
-        // Last KeyPress: ______
-        var keyPressedLabel = new Label
+        label = new ()
         {
         {
-            X = Pos.Left (editLabel), Y = Pos.Top (editLabel) + 1, Text = "Last TextView.KeyPressed:"
+            X = 0,
+            Y = Pos.Bottom (label),
+            Text = "_Last TextField.KeyDown:"
         };
         };
-        win.Add (keyPressedLabel);
-        var labelTextViewKeypress = new Label { X = Pos.Right (keyPressedLabel) + 1, Y = Pos.Top (keyPressedLabel) };
-        win.Add (labelTextViewKeypress);
-
-        edit.KeyDown += (s, e) => labelTextViewKeypress.Text = e.ToString ();
+        win.Add (label);
 
 
-        keyPressedLabel = new Label
+        var lastTextFieldKeyDownLabel = new Label
         {
         {
-            X = Pos.Left (keyPressedLabel), Y = Pos.Bottom (keyPressedLabel), Text = "Last Application.KeyDown:"
+            X = Pos.Right (label) + 1,
+            Y = Pos.Top (label),
+            Height = 1,
         };
         };
-        win.Add (keyPressedLabel);
-        var labelAppKeypress = new Label { X = Pos.Right (keyPressedLabel) + 1, Y = Pos.Top (keyPressedLabel) };
-        win.Add (labelAppKeypress);
+        win.Add (lastTextFieldKeyDownLabel);
 
 
-        Application.KeyDown += (s, e) => labelAppKeypress.Text = e.ToString ();
+        edit.KeyDown += (s, e) => lastTextFieldKeyDownLabel.Text = e.ToString ();
 
 
-        // Key stroke log:
-        var keyLogLabel = new Label
+        // Application key event log:
+        label = new Label
         {
         {
-            X = Pos.Left (editLabel), Y = Pos.Top (editLabel) + 4, Text = "Application Key Events:"
+            X = 0,
+            Y = Pos.Bottom (label) + 1,
+            Text = "Application Key Events:"
         };
         };
-        win.Add (keyLogLabel);
+        win.Add (label);
         int maxKeyString = Key.CursorRight.WithAlt.WithCtrl.WithShift.ToString ().Length;
         int maxKeyString = Key.CursorRight.WithAlt.WithCtrl.WithShift.ToString ().Length;
-        var yOffset = 1;
-        ObservableCollection<string> keyEventlist = new ();
 
 
-        var keyEventListView = new ListView
+        ObservableCollection<string> keyList = new ();
+
+        var appKeyListView = new ListView
         {
         {
             X = 0,
             X = 0,
-            Y = Pos.Top (keyLogLabel) + yOffset,
-            Width = "Key Down:".Length + maxKeyString,
+            Y = Pos.Bottom (label),
+            Width = "KeyDown:".Length + maxKeyString,
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            Source = new ListWrapper<string> (keyEventlist)
+            Source = new ListWrapper<string> (keyList)
         };
         };
-        keyEventListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        win.Add (keyEventListView);
+        appKeyListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
+        win.Add (appKeyListView);
+
+        // View key events...
+        edit.KeyDown += (s, a) => { keyDownList.Add (a.ToString ()); };
+
+        edit.KeyDownNotHandled += (s, a) =>
+                                  {
+                                      keyDownNotHandledList.Add ($"{a}");
+                                  };
 
 
-        // OnKeyPressed
-        var onKeyPressedLabel = new Label
+        // KeyDown
+        label = new Label
         {
         {
-            X = Pos.Right (keyEventListView) + 1, Y = Pos.Top (editLabel) + 4, Text = "TextView KeyDown:"
+            X = Pos.Right (appKeyListView) + 1,
+            Y = Pos.Top (label),
+            Text = "TextView Key Down:"
         };
         };
-        win.Add (onKeyPressedLabel);
+        win.Add (label);
 
 
-        yOffset = 1;
-
-        var onKeyPressedListView = new ListView
+        var onKeyDownListView = new ListView
         {
         {
-            X = Pos.Left (onKeyPressedLabel),
-            Y = Pos.Top (onKeyPressedLabel) + yOffset,
+            X = Pos.Left (label),
+            Y = Pos.Bottom (label),
             Width = maxKeyString,
             Width = maxKeyString,
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            Source = new ListWrapper<string> (keyPressedList)
+            Source = new ListWrapper<string> (keyDownList)
         };
         };
-        onKeyPressedListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        win.Add (onKeyPressedListView);
+        onKeyDownListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
+        win.Add (onKeyDownListView);
 
 
-        // OnInvokeKeyBindings
-        var onInvokingKeyBindingsLabel = new Label
+        // KeyDownNotHandled
+        label = new Label
         {
         {
-            X = Pos.Right (onKeyPressedListView) + 1,
-            Y = Pos.Top (editLabel) + 4,
-            Text = "TextView InvokingKeyBindings:"
+            X = Pos.Right (onKeyDownListView) + 1,
+            Y = Pos.Top (label),
+            Text = "TextView KeyDownNotHandled:"
         };
         };
-        win.Add (onInvokingKeyBindingsLabel);
+        win.Add (label);
 
 
-        var onInvokingKeyBindingsListView = new ListView
+        var onKeyDownNotHandledListView = new ListView
         {
         {
-            X = Pos.Left (onInvokingKeyBindingsLabel),
-            Y = Pos.Top (onInvokingKeyBindingsLabel) + yOffset,
-            Width = Dim.Fill (1),
+            X = Pos.Left (label),
+            Y = Pos.Bottom (label),
+            Width = maxKeyString,
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            Source = new ListWrapper<string> (invokingKeyBindingsList)
+            Source = new ListWrapper<string> (keyDownNotHandledList)
         };
         };
-        onInvokingKeyBindingsListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        win.Add (onInvokingKeyBindingsListView);
+        onKeyDownNotHandledListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
+        win.Add (onKeyDownNotHandledListView);
 
 
-        //Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
         Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
         Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
         Application.KeyUp += (s, a) => KeyDownPressUp (a, "Up");
         Application.KeyUp += (s, a) => KeyDownPressUp (a, "Up");
 
 
         void KeyDownPressUp (Key args, string updown)
         void KeyDownPressUp (Key args, string updown)
         {
         {
-            // BUGBUG: KeyEvent.ToString is badly broken
             var msg = $"Key{updown,-7}: {args}";
             var msg = $"Key{updown,-7}: {args}";
-            keyEventlist.Add (msg);
-            keyEventListView.MoveDown ();
-            onKeyPressedListView.MoveDown ();
-            onInvokingKeyBindingsListView.MoveDown ();
+            keyList.Add (msg);
+            appKeyListView.MoveDown ();
+            onKeyDownNotHandledListView.MoveDown ();
         }
         }
 
 
         Application.Run (win);
         Application.Run (win);

+ 35 - 17
UICatalog/Scenarios/LineDrawing.cs

@@ -8,7 +8,7 @@ namespace UICatalog.Scenarios;
 
 
 public interface ITool
 public interface ITool
 {
 {
-    void OnMouseEvent (DrawingArea area, MouseEvent mouseEvent);
+    void OnMouseEvent (DrawingArea area, MouseEventArgs mouseEvent);
 }
 }
 
 
 internal class DrawLineTool : ITool
 internal class DrawLineTool : ITool
@@ -17,7 +17,7 @@ internal class DrawLineTool : ITool
     public LineStyle LineStyle { get; set; } = LineStyle.Single;
     public LineStyle LineStyle { get; set; } = LineStyle.Single;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void OnMouseEvent (DrawingArea area, MouseEvent mouseEvent)
+    public void OnMouseEvent (DrawingArea area, MouseEventArgs mouseEvent)
     {
     {
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
         {
         {
@@ -96,6 +96,8 @@ internal class DrawLineTool : ITool
                 area.SetNeedsDisplay ();
                 area.SetNeedsDisplay ();
             }
             }
         }
         }
+
+        mouseEvent.Handled = true;
     }
     }
 }
 }
 
 
@@ -121,7 +123,7 @@ public class LineDrawing : Scenario
         tools.CurrentColor = canvas.GetNormalColor ();
         tools.CurrentColor = canvas.GetNormalColor ();
         canvas.CurrentAttribute = tools.CurrentColor;
         canvas.CurrentAttribute = tools.CurrentColor;
 
 
-        win.KeyDown += (s, e) => { e.Handled = canvas.OnKeyDown (e); };
+        win.KeyDown += (s, e) => { e.Handled = canvas.NewKeyDownEvent (e); };
 
 
         Application.Run (win);
         Application.Run (win);
         win.Dispose ();
         win.Dispose ();
@@ -135,13 +137,14 @@ public class LineDrawing : Scenario
         var d = new Dialog
         var d = new Dialog
         {
         {
             Title = title,
             Title = title,
-            Height = 7
+            Width = Application.Force16Colors ? 35 : Dim.Auto (DimAutoStyle.Auto, Dim.Percent (80), Dim.Percent (90)),
+            Height = 10
         };
         };
 
 
         var btnOk = new Button
         var btnOk = new Button
         {
         {
             X = Pos.Center () - 5,
             X = Pos.Center () - 5,
-            Y = 4,
+            Y = Application.Force16Colors ? 6 : 4,
             Text = "Ok",
             Text = "Ok",
             Width = Dim.Auto (),
             Width = Dim.Auto (),
             IsDefault = true
             IsDefault = true
@@ -171,21 +174,34 @@ public class LineDrawing : Scenario
         d.Add (btnOk);
         d.Add (btnOk);
         d.Add (btnCancel);
         d.Add (btnCancel);
 
 
-        /* Does not work
         d.AddButton (btnOk);
         d.AddButton (btnOk);
         d.AddButton (btnCancel);
         d.AddButton (btnCancel);
-        */
-        var cp = new ColorPicker
+
+        View cp;
+        if (Application.Force16Colors)
         {
         {
-            SelectedColor = current,
-            Width = Dim.Fill ()
-        };
+            cp = new ColorPicker16
+            {
+                SelectedColor = current.GetClosestNamedColor16 (),
+                Width = Dim.Fill ()
+            };
+        }
+        else
+        {
+            cp = new ColorPicker
+            {
+                SelectedColor = current,
+                Width = Dim.Fill (),
+                Style = new () { ShowColorName = true, ShowTextFields = true }
+            };
+            ((ColorPicker)cp).ApplyStyleChanges ();
+        }
 
 
         d.Add (cp);
         d.Add (cp);
 
 
         Application.Run (d);
         Application.Run (d);
         d.Dispose ();
         d.Dispose ();
-        newColor = cp.SelectedColor;
+        newColor = Application.Force16Colors ? ((ColorPicker16)cp).SelectedColor : ((ColorPicker)cp).SelectedColor;
 
 
         return accept;
         return accept;
     }
     }
@@ -276,7 +292,7 @@ public class DrawingArea : View
     }
     }
 
 
     //// BUGBUG: Why is this not handled by a key binding???
     //// BUGBUG: Why is this not handled by a key binding???
-    public override bool OnKeyDown (Key e)
+    protected override bool OnKeyDown (Key e)
     {
     {
         // BUGBUG: These should be implemented with key bindings
         // BUGBUG: These should be implemented with key bindings
         if (e.KeyCode == (KeyCode.Z | KeyCode.CtrlMask))
         if (e.KeyCode == (KeyCode.Z | KeyCode.CtrlMask))
@@ -307,11 +323,11 @@ public class DrawingArea : View
         return false;
         return false;
     }
     }
 
 
-    protected override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         CurrentTool.OnMouseEvent (this, mouseEvent);
         CurrentTool.OnMouseEvent (this, mouseEvent);
 
 
-        return base.OnMouseEvent (mouseEvent);
+        return mouseEvent.Handled;
     }
     }
 
 
     internal void AddLayer ()
     internal void AddLayer ()
@@ -415,7 +431,7 @@ public class AttributeView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
         {
         {
@@ -427,9 +443,11 @@ public class AttributeView : View
             {
             {
                 ClickedInBackground ();
                 ClickedInBackground ();
             }
             }
+
+            mouseEvent.Handled = true;
         }
         }
 
 
-        return base.OnMouseEvent (mouseEvent);
+        return mouseEvent.Handled;
     }
     }
 
 
     private bool IsForegroundPoint (int x, int y) { return ForegroundPoints.Contains ((x, y)); }
     private bool IsForegroundPoint (int x, int y) { return ForegroundPoints.Contains ((x, y)); }

+ 1 - 1
UICatalog/Scenarios/ListColumns.cs

@@ -248,7 +248,7 @@ public class ListColumns : Scenario
         };
         };
 
 
         // if user clicks the mouse in TableView
         // if user clicks the mouse in TableView
-        _listColView.MouseClick += (s, e) => { _listColView.ScreenToCell (e.MouseEvent.Position, out int? clickedCol); };
+        _listColView.MouseClick += (s, e) => { _listColView.ScreenToCell (e.Position, out int? clickedCol); };
 
 
         _listColView.KeyBindings.ReplaceCommands (Key.Space, Command.Accept);
         _listColView.KeyBindings.ReplaceCommands (Key.Space, Command.Accept);
 
 

+ 3 - 3
UICatalog/Scenarios/Mouse.cs

@@ -251,18 +251,18 @@ public class Mouse : Scenario
 
 
         win.MouseEvent += (sender, a) =>
         win.MouseEvent += (sender, a) =>
                           {
                           {
-                              int i = filterSlider.Options.FindIndex (o => o.Data == a.MouseEvent.Flags);
+                              int i = filterSlider.Options.FindIndex (o => o.Data == a.Flags);
 
 
                               if (filterSlider.GetSetOptions ().Contains (i))
                               if (filterSlider.GetSetOptions ().Contains (i))
                               {
                               {
-                                  winLogList.Add ($"MouseEvent: ({a.MouseEvent.Position}) - {a.MouseEvent.Flags} {count++}");
+                                  winLogList.Add ($"MouseEvent: ({a.Position}) - {a.Flags} {count++}");
                                   winLog.MoveDown ();
                                   winLog.MoveDown ();
                               }
                               }
                           };
                           };
 
 
         win.MouseClick += (sender, a) =>
         win.MouseClick += (sender, a) =>
                           {
                           {
-                              winLogList.Add ($"MouseClick: ({a.MouseEvent.Position}) - {a.MouseEvent.Flags} {count++}");
+                              winLogList.Add ($"MouseClick: ({a.Position}) - {a.Flags} {count++}");
                               winLog.MoveDown ();
                               winLog.MoveDown ();
                           };
                           };
 
 

+ 1 - 1
UICatalog/Scenarios/ProgressBarStyles.cs

@@ -35,7 +35,7 @@ public class ProgressBarStyles : Scenario
 
 
         var editor = new AdornmentsEditor ()
         var editor = new AdornmentsEditor ()
         {
         {
-            AutoSelectViewToEdit = true
+            AutoSelectViewToEdit = false
         };
         };
         app.Add (editor);
         app.Add (editor);
 
 

+ 5 - 5
UICatalog/Scenarios/Snake.cs

@@ -357,30 +357,30 @@ public class Snake : Scenario
         }
         }
 
 
         // BUGBUG: Should (can) this use key bindings instead.
         // BUGBUG: Should (can) this use key bindings instead.
-        public override bool OnKeyDown (Key keyEvent)
+        protected override bool OnKeyDown (Key key)
         {
         {
-            if (keyEvent.KeyCode == KeyCode.CursorUp)
+            if (key.KeyCode == KeyCode.CursorUp)
             {
             {
                 State.PlannedDirection = Direction.Up;
                 State.PlannedDirection = Direction.Up;
 
 
                 return true;
                 return true;
             }
             }
 
 
-            if (keyEvent.KeyCode == KeyCode.CursorDown)
+            if (key.KeyCode == KeyCode.CursorDown)
             {
             {
                 State.PlannedDirection = Direction.Down;
                 State.PlannedDirection = Direction.Down;
 
 
                 return true;
                 return true;
             }
             }
 
 
-            if (keyEvent.KeyCode == KeyCode.CursorLeft)
+            if (key.KeyCode == KeyCode.CursorLeft)
             {
             {
                 State.PlannedDirection = Direction.Left;
                 State.PlannedDirection = Direction.Left;
 
 
                 return true;
                 return true;
             }
             }
 
 
-            if (keyEvent.KeyCode == KeyCode.CursorRight)
+            if (key.KeyCode == KeyCode.CursorRight)
             {
             {
                 State.PlannedDirection = Direction.Right;
                 State.PlannedDirection = Direction.Right;
 
 

+ 31 - 28
UICatalog/Scenarios/SyntaxHighlighting.cs

@@ -85,13 +85,13 @@ public class SyntaxHighlighting : Scenario
         "exists"
         "exists"
     };
     };
 
 
-    private readonly string _path = "RuneCells.rce";
-    private ColorScheme _blue;
-    private ColorScheme _green;
-    private ColorScheme _magenta;
+    private readonly string _path = "Cells.rce";
+    private Attribute _blue;
+    private Attribute _green;
+    private Attribute _magenta;
     private MenuItem _miWrap;
     private MenuItem _miWrap;
     private TextView _textView;
     private TextView _textView;
-    private ColorScheme _white;
+    private Attribute _white;
 
 
     /// <summary>
     /// <summary>
     ///     Reads an object instance from an Json file.
     ///     Reads an object instance from an Json file.
@@ -155,12 +155,12 @@ public class SyntaxHighlighting : Scenario
                          new (
                          new (
                               "_Load Rune Cells",
                               "_Load Rune Cells",
                               "",
                               "",
-                              () => ApplyLoadRuneCells ()
+                              () => ApplyLoadCells ()
                              ),
                              ),
                          new (
                          new (
                               "_Save Rune Cells",
                               "_Save Rune Cells",
                               "",
                               "",
-                              () => SaveRuneCells ()
+                              () => SaveCells ()
                              ),
                              ),
                          null,
                          null,
                          new ("_Quit", "", () => Quit ())
                          new ("_Quit", "", () => Quit ())
@@ -231,11 +231,11 @@ public class SyntaxHighlighting : Scenario
         }
         }
     }
     }
 
 
-    private void ApplyLoadRuneCells ()
+    private void ApplyLoadCells ()
     {
     {
         ClearAllEvents ();
         ClearAllEvents ();
 
 
-        List<RuneCell> runeCells = new ();
+        List<Cell> cells = new ();
 
 
         foreach (KeyValuePair<string, ColorScheme> color in Colors.ColorSchemes)
         foreach (KeyValuePair<string, ColorScheme> color in Colors.ColorSchemes)
         {
         {
@@ -243,21 +243,21 @@ public class SyntaxHighlighting : Scenario
 
 
             foreach (Rune rune in csName.EnumerateRunes ())
             foreach (Rune rune in csName.EnumerateRunes ())
             {
             {
-                runeCells.Add (new() { Rune = rune, ColorScheme = color.Value });
+                cells.Add (new() { Rune = rune, Attribute = color.Value.Normal });
             }
             }
 
 
-            runeCells.Add (new() { Rune = (Rune)'\n', ColorScheme = color.Value });
+            cells.Add (new() { Rune = (Rune)'\n', Attribute = color.Value.Focus });
         }
         }
 
 
         if (File.Exists (_path))
         if (File.Exists (_path))
         {
         {
-            //Reading the file  
-            List<List<RuneCell>> cells = ReadFromJsonFile<List<List<RuneCell>>> (_path);
-            _textView.Load (cells);
+            //Reading the file
+            List<List<Cell>> fileCells = ReadFromJsonFile<List<List<Cell>>> (_path);
+            _textView.Load (fileCells);
         }
         }
         else
         else
         {
         {
-            _textView.Load (runeCells);
+            _textView.Load (cells);
         }
         }
 
 
         _textView.Autocomplete.SuggestionGenerator = new SingleWordSuggestionGenerator ();
         _textView.Autocomplete.SuggestionGenerator = new SingleWordSuggestionGenerator ();
@@ -267,11 +267,11 @@ public class SyntaxHighlighting : Scenario
     {
     {
         ClearAllEvents ();
         ClearAllEvents ();
 
 
-        _green = new (new Attribute (Color.Green, Color.Black));
-        _blue = new (new Attribute (Color.Blue, Color.Black));
-        _magenta = new (new Attribute (Color.Magenta, Color.Black));
-        _white = new (new Attribute (Color.White, Color.Black));
-        _textView.ColorScheme = _white;
+        _green = new Attribute (Color.Green, Color.Black);
+        _blue = new Attribute (Color.Blue, Color.Black);
+        _magenta = new Attribute (Color.Magenta, Color.Black);
+        _white = new Attribute (Color.White, Color.Black);
+        _textView.ColorScheme = new () { Focus = _white };
 
 
         _textView.Text =
         _textView.Text =
             "/*Query to select:\nLots of data*/\nSELECT TOP 100 * \nfrom\n MyDb.dbo.Biochemistry where TestCode = 'blah';";
             "/*Query to select:\nLots of data*/\nSELECT TOP 100 * \nfrom\n MyDb.dbo.Biochemistry where TestCode = 'blah';";
@@ -292,7 +292,7 @@ public class SyntaxHighlighting : Scenario
         _textView.ClearEventHandlers ("DrawContent");
         _textView.ClearEventHandlers ("DrawContent");
         _textView.ClearEventHandlers ("DrawContentComplete");
         _textView.ClearEventHandlers ("DrawContentComplete");
 
 
-        _textView.InheritsPreviousColorScheme = false;
+        _textView.InheritsPreviousAttribute = false;
     }
     }
 
 
     private bool ContainsPosition (Match m, int pos) { return pos >= m.Index && pos < m.Index + m.Length; }
     private bool ContainsPosition (Match m, int pos) { return pos >= m.Index && pos < m.Index + m.Length; }
@@ -317,27 +317,30 @@ public class SyntaxHighlighting : Scenario
 
 
         for (var y = 0; y < _textView.Lines; y++)
         for (var y = 0; y < _textView.Lines; y++)
         {
         {
-            List<RuneCell> line = _textView.GetLine (y);
+            List<Cell> line = _textView.GetLine (y);
 
 
             for (var x = 0; x < line.Count; x++)
             for (var x = 0; x < line.Count; x++)
             {
             {
+                Cell cell = line [x];
+
                 if (commentMatches.Any (m => ContainsPosition (m, pos)))
                 if (commentMatches.Any (m => ContainsPosition (m, pos)))
                 {
                 {
-                    line [x].ColorScheme = _green;
+                    cell.Attribute = _green;
                 }
                 }
                 else if (singleQuoteMatches.Any (m => ContainsPosition (m, pos)))
                 else if (singleQuoteMatches.Any (m => ContainsPosition (m, pos)))
                 {
                 {
-                    line [x].ColorScheme = _magenta;
+                    cell.Attribute = _magenta;
                 }
                 }
                 else if (keywordMatches.Any (m => ContainsPosition (m, pos)))
                 else if (keywordMatches.Any (m => ContainsPosition (m, pos)))
                 {
                 {
-                    line [x].ColorScheme = _blue;
+                    cell.Attribute = _blue;
                 }
                 }
                 else
                 else
                 {
                 {
-                    line [x].ColorScheme = _white;
+                    cell.Attribute = _white;
                 }
                 }
 
 
+                line [x] = cell;
                 pos++;
                 pos++;
             }
             }
 
 
@@ -384,10 +387,10 @@ public class SyntaxHighlighting : Scenario
 
 
     private void Quit () { Application.RequestStop (); }
     private void Quit () { Application.RequestStop (); }
 
 
-    private void SaveRuneCells ()
+    private void SaveCells ()
     {
     {
         //Writing to file  
         //Writing to file  
-        List<List<RuneCell>> cells = _textView.GetAllLines ();
+        List<List<Cell>> cells = _textView.GetAllLines ();
         WriteToJsonFile (_path, cells);
         WriteToJsonFile (_path, cells);
     }
     }
 
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä