Przeglądaj źródła

Addressed feedback #1

Tig 11 miesięcy temu
rodzic
commit
7556892c02

+ 1 - 1
README.md

@@ -35,7 +35,7 @@ dotnet run
 * [API Documentation](https://gui-cs.github.io/Terminal.GuiV2Docs/api/Terminal.Gui.html)
 * [API Documentation](https://gui-cs.github.io/Terminal.GuiV2Docs/api/Terminal.Gui.html)
 * [Documentation Home](https://gui-cs.github.io/Terminal.GuiV2Docs)
 * [Documentation Home](https://gui-cs.github.io/Terminal.GuiV2Docs)
 
 
-The above documentation matches the most recent Nuget release from the `v2_develop` branch. Get the [v1 documentation here]( (This is the v2 API documentation. For v1 go here: https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui.html)
+The above documentation matches the most recent Nuget release from the `v2_develop` branch. Get the [v1 documentation here](This is the v2 API documentation. For v1 go here: https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui.html)
 
 
 See the [`Terminal.Gui/` README](https://github.com/gui-cs/Terminal.Gui/tree/master/Terminal.Gui) for an overview of how the library is structured. 
 See the [`Terminal.Gui/` README](https://github.com/gui-cs/Terminal.Gui/tree/master/Terminal.Gui) for an overview of how the library is structured. 
 
 

+ 137 - 158
Terminal.Gui/Application/Application.Keyboard.cs

@@ -1,45 +1,49 @@
 #nullable enable
 #nullable enable
-using System.Text.Json.Serialization;
-
 namespace Terminal.Gui;
 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 _nextTabKey = Key.Tab; // Resources/config.json overrrides
 
 
-    /// <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;
-            }
-        }
-    }
+    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 _prevTabKey = Key.Tab.WithShift; // Resources/config.json overrrides
 
 
-    /// <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;
-            }
-        }
-    }
+    private static Key _quitKey = Key.Esc; // Resources/config.json overrrides
 
 
-    private static Key _nextTabGroupKey = Key.F6; // 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>
+    ///     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>
     /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
     [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
     [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
@@ -56,71 +60,21 @@ public static partial class Application // Keyboard handling
         }
         }
     }
     }
 
 
-    private static Key _prevTabGroupKey = Key.F6.WithShift; // Resources/config.json overrrides
-
-    /// <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;
-            }
-        }
-    }
-
-    private static Key _quitKey = Key.Esc; // Resources/config.json overrrides
-
-    /// <summary>Gets or sets the key to quit the application.</summary>
+    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
     [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
     [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key QuitKey
+    public static Key NextTabKey
     {
     {
-        get => _quitKey;
+        get => _nextTabKey;
         set
         set
         {
         {
-            if (_quitKey != value)
+            if (_nextTabKey != value)
             {
             {
-                ReplaceKey (_quitKey, value);
-                _quitKey = value;
+                ReplaceKey (_nextTabKey, value);
+                _nextTabKey = value;
             }
             }
         }
         }
     }
     }
 
 
-    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);
-        }
-    }
-
-    /// <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>
     ///     Called by the <see cref="ConsoleDriver"/> when the user presses a key. Fires the <see cref="KeyDown"/> event
     ///     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
     ///     then calls <see cref="View.NewKeyDownEvent"/> on all top level views. Called after <see cref="OnKeyDown"/> and
@@ -217,20 +171,6 @@ public static partial class Application // Keyboard handling
         return false;
         return false;
     }
     }
 
 
-    /// <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>
     /// <summary>
     ///     Called by the <see cref="ConsoleDriver"/> when the user releases a key. Fires the <see cref="KeyUp"/> event
     ///     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"/>.
     ///     then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="OnKeyDown"/>.
@@ -268,33 +208,50 @@ public static partial class Application // Keyboard handling
         return false;
         return false;
     }
     }
 
 
-    /// <summary>Gets the key bindings for this view.</summary>
-    public static KeyBindings KeyBindings { get; internal set; } = new ();
-
-    /// <summary>
-    ///     Commands for Application.
-    /// </summary>
-    private static Dictionary<Command, Func<CommandContext, bool?>>? CommandImplementations { get; set; }
+    /// <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>
-    ///     <para>
-    ///         Sets the function that will be invoked for a <see cref="Command"/>.
-    ///     </para>
-    ///     <para>
-    ///         If AddCommand has already been called for <paramref name="command"/> <paramref name="f"/> will
-    ///         replace the old one.
-    ///     </para>
-    /// </summary>
-    /// <remarks>
-    ///     <para>
-    ///         This version of AddCommand is for commands that do not require a <see cref="CommandContext"/>.
-    ///     </para>
-    /// </remarks>
-    /// <param name="command">The command.</param>
-    /// <param name="f">The function.</param>
-    private static void AddCommand (Command command, Func<bool?> f) { CommandImplementations! [command] = ctx => f (); }
+    /// <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;
+            }
+        }
+    }
 
 
-    static Application () { AddApplicationKeyBindings (); }
+    /// <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;
+            }
+        }
+    }
 
 
     internal static void AddApplicationKeyBindings ()
     internal static void AddApplicationKeyBindings ()
     {
     {
@@ -303,7 +260,7 @@ public static partial class Application // Keyboard handling
         // Things this view knows how to do
         // Things this view knows how to do
         AddCommand (
         AddCommand (
                     Command.QuitToplevel, // TODO: IRunnable: Rename to Command.Quit to make more generic.
                     Command.QuitToplevel, // TODO: IRunnable: Rename to Command.Quit to make more generic.
-                    () =>
+                    static () =>
                     {
                     {
                         if (ApplicationOverlapped.OverlappedTop is { })
                         if (ApplicationOverlapped.OverlappedTop is { })
                         {
                         {
@@ -320,7 +277,7 @@ public static partial class Application // Keyboard handling
 
 
         AddCommand (
         AddCommand (
                     Command.Suspend,
                     Command.Suspend,
-                    () =>
+                    static () =>
                     {
                     {
                         Driver?.Suspend ();
                         Driver?.Suspend ();
 
 
@@ -330,40 +287,22 @@ public static partial class Application // Keyboard handling
 
 
         AddCommand (
         AddCommand (
                     Command.NextView,
                     Command.NextView,
-                    () =>
-                    {
-                        View? current = Application.Current;
-                        if (current is { })
-                        {
-                            return current.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
-                        }
-                        return false;
-                    }
-                   );
+                    static () => Current?.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop));
 
 
         AddCommand (
         AddCommand (
                     Command.PreviousView,
                     Command.PreviousView,
-                    () =>
-                    {
-                        View? current = Application.Current;
-                        if (current is { })
-                        {
-                            return current.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabStop);
-                        }
-                        return false;
-                    }
-                   );
+                    static () => Current?.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabStop));
 
 
         AddCommand (
         AddCommand (
                     Command.NextViewOrTop,
                     Command.NextViewOrTop,
-                    () =>
+                    static () =>
                     {
                     {
+                        // TODO: This OverlapppedTop tomfoolery goes away in addressing #2491
                         if (ApplicationOverlapped.OverlappedTop is null)
                         if (ApplicationOverlapped.OverlappedTop is null)
                         {
                         {
-                            View? current = Application.Current;
-                            if (current is { })
+                            if ((View?)Current is { })
                             {
                             {
-                                return current.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabGroup);
+                                return Current.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabGroup);
                             }
                             }
                         }
                         }
                         else
                         else
@@ -379,19 +318,19 @@ public static partial class Application // Keyboard handling
 
 
         AddCommand (
         AddCommand (
                     Command.PreviousViewOrTop,
                     Command.PreviousViewOrTop,
-                    () =>
+                    static () =>
                     {
                     {
+                        // TODO: This OverlapppedTop tomfoolery goes away in addressing #2491
                         if (ApplicationOverlapped.OverlappedTop is null)
                         if (ApplicationOverlapped.OverlappedTop is null)
                         {
                         {
-                            View? current = Application.Current;
-                            if (current is { })
+                            if ((View?)Current is { })
                             {
                             {
-                                return current.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup);
+                                return Current.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup);
                             }
                             }
                         }
                         }
                         else
                         else
                         {
                         {
-                            ApplicationOverlapped.OverlappedMovePrevious();
+                            ApplicationOverlapped.OverlappedMovePrevious ();
 
 
                             return true;
                             return true;
                         }
                         }
@@ -402,7 +341,7 @@ public static partial class Application // Keyboard handling
 
 
         AddCommand (
         AddCommand (
                     Command.Refresh,
                     Command.Refresh,
-                    () =>
+                    static () =>
                     {
                     {
                         Refresh ();
                         Refresh ();
 
 
@@ -464,4 +403,44 @@ public static partial class Application // Keyboard handling
                           .Distinct ()
                           .Distinct ()
                           .ToList ();
                           .ToList ();
     }
     }
+
+    /// <summary>
+    ///     <para>
+    ///         Sets the function that will be invoked for a <see cref="Command"/>.
+    ///     </para>
+    ///     <para>
+    ///         If AddCommand has already been called for <paramref name="command"/> <paramref name="f"/> will
+    ///         replace the old one.
+    ///     </para>
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         This version of AddCommand is for commands that do not require a <see cref="CommandContext"/>.
+    ///     </para>
+    /// </remarks>
+    /// <param name="command">The command.</param>
+    /// <param name="f">The function.</param>
+    private static void AddCommand (Command command, Func<bool?> f) { CommandImplementations! [command] = ctx => f (); }
+
+    /// <summary>
+    ///     Commands for Application.
+    /// </summary>
+    private static Dictionary<Command, Func<CommandContext, bool?>>? 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);
+        }
+    }
 }
 }

+ 33 - 3
UICatalog/Scenarios/Adornments.cs

@@ -19,11 +19,13 @@ public class Adornments : Scenario
         var editor = new AdornmentsEditor
         var editor = new AdornmentsEditor
         {
         {
             AutoSelectViewToEdit = true,
             AutoSelectViewToEdit = true,
+
             // This is for giggles, to show that the editor can be moved around.
             // This is for giggles, to show that the editor can be moved around.
             Arrangement = ViewArrangement.Movable,
             Arrangement = ViewArrangement.Movable,
-            X = Pos.AnchorEnd(),
+            X = Pos.AnchorEnd ()
         };
         };
-        editor.Border.Thickness = new Thickness (1, 2, 1, 1);
+
+        editor.Border.Thickness = new (1, 2, 1, 1);
 
 
         app.Add (editor);
         app.Add (editor);
 
 
@@ -31,7 +33,8 @@ public class Adornments : Scenario
         {
         {
             Title = "The _Window",
             Title = "The _Window",
             Arrangement = ViewArrangement.Movable,
             Arrangement = ViewArrangement.Movable,
-           // X = Pos.Center (),
+
+            // X = Pos.Center (),
             Width = Dim.Percent (60),
             Width = Dim.Percent (60),
             Height = Dim.Percent (80)
             Height = Dim.Percent (80)
         };
         };
@@ -127,9 +130,36 @@ public class Adornments : Scenario
 #endif
 #endif
                               };
                               };
 
 
+        Application.MouseEvent += ApplicationOnMouseEvent;
+
         Application.Run (app);
         Application.Run (app);
         app.Dispose ();
         app.Dispose ();
 
 
         Application.Shutdown ();
         Application.Shutdown ();
+
+        return;
+
+        void ApplicationOnMouseEvent (object sender, MouseEvent e)
+        {
+            if (!editor.AutoSelectViewToEdit || editor.FrameToScreen ().Contains (e.Position))
+            {
+                return;
+            }
+
+            // TODO: Add a setting (property) so only subviews of a specified view are considered.
+            View view = e.View;
+
+            if (view is { } && e.Flags == MouseFlags.Button1Clicked)
+            {
+                if (view is Adornment adornment)
+                {
+                    editor.ViewToEdit = adornment.Parent;
+                }
+                else
+                {
+                    editor.ViewToEdit = view;
+                }
+            }
+        }
     }
     }
 }
 }

+ 0 - 33
UICatalog/Scenarios/AdornmentsEditor.cs

@@ -21,8 +21,6 @@ public class AdornmentsEditor : View
 
 
         TabStop = TabBehavior.TabGroup;
         TabStop = TabBehavior.TabGroup;
 
 
-        //Application.MouseEvent += Application_MouseEvent;
-        Application.Navigation!.FocusedChanged += ApplicationNavigationOnFocusedChanged;
         Initialized += AdornmentsEditor_Initialized;
         Initialized += AdornmentsEditor_Initialized;
     }
     }
 
 
@@ -155,35 +153,4 @@ public class AdornmentsEditor : View
         Add (_diagRulerCheckBox);
         Add (_diagRulerCheckBox);
         _diagRulerCheckBox.Y = Pos.Bottom (_diagPaddingCheckBox);
         _diagRulerCheckBox.Y = Pos.Bottom (_diagPaddingCheckBox);
     }
     }
-
-    private void Application_MouseEvent (object sender, MouseEvent e)
-    {
-        if (!AutoSelectViewToEdit || FrameToScreen ().Contains (e.Position))
-        {
-            return;
-        }
-
-        // TODO: Add a setting (property) so only subviews of a specified view are considered.
-        View view = e.View;
-
-        if (view is { } && e.Flags == MouseFlags.Button1Clicked)
-        {
-            if (view is Adornment adornment)
-            {
-                ViewToEdit = adornment.Parent;
-            }
-            else
-            {
-                ViewToEdit = view;
-            }
-        }
-    }
-
-    private void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e)
-    {
-        if (ApplicationNavigation.IsInHierarchy (this, Application.Navigation!.GetFocused ()))
-        {
-            return;
-        }
-    }
 }
 }

+ 27 - 0
UICatalog/Scenarios/ContentScrolling.cs

@@ -407,8 +407,35 @@ public class ContentScrolling : Scenario
 
 
         app.Closed += (s, e) => View.Diagnostics = _diagnosticFlags;
         app.Closed += (s, e) => View.Diagnostics = _diagnosticFlags;
 
 
+        Application.MouseEvent += ApplicationOnMouseEvent;
+
         Application.Run (app);
         Application.Run (app);
         app.Dispose ();
         app.Dispose ();
         Application.Shutdown ();
         Application.Shutdown ();
+
+        return;
+
+        void ApplicationOnMouseEvent (object sender, MouseEvent e)
+        {
+            if (!editor.AutoSelectViewToEdit || editor.FrameToScreen ().Contains (e.Position))
+            {
+                return;
+            }
+
+            // TODO: Add a setting (property) so only subviews of a specified view are considered.
+            View view = e.View;
+
+            if (view is { } && e.Flags == MouseFlags.Button1Clicked)
+            {
+                if (view is Adornment adornment)
+                {
+                    editor.ViewToEdit = adornment.Parent;
+                }
+                else
+                {
+                    editor.ViewToEdit = view;
+                }
+            }
+        }
     }
     }
 }
 }

+ 165 - 0
UICatalog/Scenarios/Navigation.cs

@@ -0,0 +1,165 @@
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios;
+
+[ScenarioMetadata ("Navigation", "Navigation Tester")]
+[ScenarioCategory ("Mouse and Keyboard")]
+[ScenarioCategory ("Layout")]
+public class Navigation : Scenario
+{
+    public override void Main ()
+    {
+        Application.Init ();
+
+        Window app = new ()
+        {
+            Title = GetQuitKeyAndName (),
+            TabStop = TabBehavior.TabGroup
+        };
+
+        var editor = new AdornmentsEditor
+        {
+            X = 0,
+            Y = 0,
+            AutoSelectViewToEdit = true,
+            TabStop = TabBehavior.NoStop
+        };
+        app.Add (editor);
+
+        FrameView testFrame = new ()
+        {
+            Title = "_1 Test Frame",
+            X = Pos.Right (editor),
+            Width = Dim.Fill (),
+            Height = Dim.Fill (),
+        };
+
+        app.Add (testFrame);
+
+        Button button = new ()
+        {
+            X = 0,
+            Y = 0,
+            Title = $"TopButton _{GetNextHotKey ()}",
+        };
+
+        testFrame.Add (button);
+
+        var tiledView1 = CreateTiledView (0, 2, 2);
+        var tiledView2 = CreateTiledView (1, Pos.Right (tiledView1), Pos.Top (tiledView1));
+
+        testFrame.Add (tiledView1);
+        testFrame.Add (tiledView2);
+
+        var tiledView3 = CreateTiledView (1, Pos.Right (tiledView2), Pos.Top (tiledView2));
+        tiledView3.TabStop = TabBehavior.TabGroup;
+        tiledView3.BorderStyle = LineStyle.Double;
+        testFrame.Add (tiledView3);
+
+        var overlappedView1 = CreateOverlappedView (2, Pos.Center () - 5, Pos.Center ());
+        var tiledSubView = CreateTiledView (4, 0, 2);
+        overlappedView1.Add (tiledSubView);
+
+        var overlappedView2 = CreateOverlappedView (3, Pos.Center () + 10, Pos.Center () + 5);
+
+        // BUGBUG: F6 through nested tab groups doesn't work yet.
+#if NESTED_TABGROUPS
+        var overlappedInOverlapped1 = CreateOverlappedView (4, 1, 4);
+        overlappedView2.Add (overlappedInOverlapped1);
+
+        var overlappedInOverlapped2 = CreateOverlappedView (5, 10, 7);
+        overlappedView2.Add (overlappedInOverlapped2);
+
+#endif
+
+        testFrame.Add (overlappedView1);
+        testFrame.Add (overlappedView2);
+
+        button = new ()
+        {
+            X = Pos.AnchorEnd (),
+            Y = Pos.AnchorEnd (),
+            Title = $"TopButton _{GetNextHotKey ()}",
+        };
+
+        testFrame.Add (button);
+
+        Application.Run (app);
+        app.Dispose ();
+        Application.Shutdown ();
+    }
+
+    private int _hotkeyCount;
+
+    private char GetNextHotKey ()
+    {
+        return (char)((int)'A' + _hotkeyCount++);
+    }
+
+    private View CreateTiledView (int id, Pos x, Pos y)
+    {
+        View overlapped = new View
+        {
+            X = x,
+            Y = y,
+            Height = Dim.Auto (),
+            Width = Dim.Auto (),
+            Title = $"Tiled{id} _{GetNextHotKey ()}",
+            Id = $"Tiled{id}",
+            BorderStyle = LineStyle.Single,
+            CanFocus = true, // Can't drag without this? BUGBUG
+            TabStop = TabBehavior.TabStop,
+            Arrangement = ViewArrangement.Fixed
+        };
+
+        Button button = new ()
+        {
+            Title = $"Tiled Button{id} _{GetNextHotKey ()}"
+        };
+        overlapped.Add (button);
+
+        button = new ()
+        {
+            Y = Pos.Bottom (button),
+            Title = $"Tiled Button{id} _{GetNextHotKey ()}"
+        };
+        overlapped.Add (button);
+
+        return overlapped;
+    }
+
+
+    private View CreateOverlappedView (int id, Pos x, Pos y)
+    {
+        View overlapped = new View
+        {
+            X = x,
+            Y = y,
+            Height = Dim.Auto (),
+            Width = Dim.Auto (),
+            Title = $"Overlapped{id} _{GetNextHotKey ()}",
+            ColorScheme = Colors.ColorSchemes ["Toplevel"],
+            Id = $"Overlapped{id}",
+            ShadowStyle = ShadowStyle.Transparent,
+            BorderStyle = LineStyle.Double,
+            CanFocus = true, // Can't drag without this? BUGBUG
+            TabStop = TabBehavior.TabGroup,
+            Arrangement = ViewArrangement.Movable | ViewArrangement.Overlapped
+        };
+
+        Button button = new ()
+        {
+            Title = $"Button{id} _{GetNextHotKey ()}"
+        };
+        overlapped.Add (button);
+
+        button = new ()
+        {
+            Y = Pos.Bottom (button),
+            Title = $"Button{id} _{GetNextHotKey ()}"
+        };
+        overlapped.Add (button);
+
+        return overlapped;
+    }
+}

+ 25 - 0
UICatalog/Scenarios/ShadowStyles.cs

@@ -55,11 +55,36 @@ public class ShadowStyles : Scenario
         };
         };
         app.Add (button);
         app.Add (button);
 
 
+        Application.MouseEvent += ApplicationOnMouseEvent;
+
         Application.Run (app);
         Application.Run (app);
         app.Dispose ();
         app.Dispose ();
 
 
         Application.Shutdown ();
         Application.Shutdown ();
 
 
         return;
         return;
+
+        void ApplicationOnMouseEvent (object sender, MouseEvent e)
+        {
+            if (!editor.AutoSelectViewToEdit || editor.FrameToScreen ().Contains (e.Position))
+            {
+                return;
+            }
+
+            // TODO: Add a setting (property) so only subviews of a specified view are considered.
+            View view = e.View;
+
+            if (view is { } && e.Flags == MouseFlags.Button1Clicked)
+            {
+                if (view is Adornment adornment)
+                {
+                    editor.ViewToEdit = adornment.Parent;
+                }
+                else
+                {
+                    editor.ViewToEdit = view;
+                }
+            }
+        }
     }
     }
 }
 }

+ 47 - 32
UICatalog/Scenarios/ViewExperiments.cs

@@ -1,4 +1,5 @@
-using Terminal.Gui;
+using System;
+using Terminal.Gui;
 
 
 namespace UICatalog.Scenarios;
 namespace UICatalog.Scenarios;
 
 
@@ -47,36 +48,6 @@ public class ViewExperiments : Scenario
 
 
         testFrame.Add (button);
         testFrame.Add (button);
 
 
-        var tiledView1 = CreateTiledView (0, 2, 2);
-        var tiledView2 = CreateTiledView (1, Pos.Right (tiledView1), Pos.Top (tiledView1));
-
-        testFrame.Add (tiledView1);
-        testFrame.Add (tiledView2);
-
-        var tiledView3 = CreateTiledView (1, Pos.Right (tiledView2), Pos.Top (tiledView2));
-        tiledView3.TabStop = TabBehavior.TabGroup;
-        tiledView3.BorderStyle = LineStyle.Double;
-        testFrame.Add (tiledView3);
-
-        var overlappedView1 = CreateOverlappedView (2, Pos.Center () - 5, Pos.Center ());
-        var tiledSubView = CreateTiledView (4, 0, 2);
-        overlappedView1.Add (tiledSubView);
-
-        var overlappedView2 = CreateOverlappedView (3, Pos.Center () + 10, Pos.Center () + 5);
-
-        // BUGBUG: F6 through nested tab groups doesn't work yet.
-#if NESTED_TABGROUPS
-        var overlappedInOverlapped1 = CreateOverlappedView (4, 1, 4);
-        overlappedView2.Add (overlappedInOverlapped1);
-
-        var overlappedInOverlapped2 = CreateOverlappedView (5, 10, 7);
-        overlappedView2.Add (overlappedInOverlapped2);
-
-#endif
-
-        testFrame.Add (overlappedView1);
-        testFrame.Add (overlappedView2);
-
         button = new ()
         button = new ()
         {
         {
             X = Pos.AnchorEnd (),
             X = Pos.AnchorEnd (),
@@ -85,10 +56,54 @@ public class ViewExperiments : Scenario
         };
         };
 
 
         testFrame.Add (button);
         testFrame.Add (button);
+        Application.MouseEvent += ApplicationOnMouseEvent;
+        Application.Navigation.FocusedChanged += NavigationOnFocusedChanged;
+
 
 
         Application.Run (app);
         Application.Run (app);
         app.Dispose ();
         app.Dispose ();
+
         Application.Shutdown ();
         Application.Shutdown ();
+
+        return;
+
+
+        void NavigationOnFocusedChanged (object sender, EventArgs e)
+        {
+            if (!ApplicationNavigation.IsInHierarchy (testFrame, Application.Navigation!.GetFocused ()))
+            {
+                return;
+            }
+
+            editor.ViewToEdit = Application.Navigation!.GetFocused ();
+        }
+        void ApplicationOnMouseEvent (object sender, MouseEvent e)
+        {
+            if (e.Flags != MouseFlags.Button1Clicked)
+            {
+                return;
+            }
+
+            if (!editor.AutoSelectViewToEdit || !testFrame.FrameToScreen ().Contains (e.Position))
+            {
+                return;
+            }
+
+            // TODO: Add a setting (property) so only subviews of a specified view are considered.
+            View view = e.View;
+
+            if (view is { } && e.Flags == MouseFlags.Button1Clicked)
+            {
+                if (view is Adornment adornment)
+                {
+                    editor.ViewToEdit = adornment.Parent;
+                }
+                else
+                {
+                    editor.ViewToEdit = view;
+                }
+            }
+        }
     }
     }
 
 
     private int _hotkeyCount;
     private int _hotkeyCount;
@@ -110,7 +125,7 @@ public class ViewExperiments : Scenario
             Id = $"Tiled{id}",
             Id = $"Tiled{id}",
             BorderStyle = LineStyle.Single,
             BorderStyle = LineStyle.Single,
             CanFocus = true, // Can't drag without this? BUGBUG
             CanFocus = true, // Can't drag without this? BUGBUG
-            TabStop = TabBehavior.TabStop,
+            TabStop = TabBehavior.TabGroup,
             Arrangement = ViewArrangement.Fixed
             Arrangement = ViewArrangement.Fixed
         };
         };