浏览代码

Moved view navigation out of Toplevel and into Application (via ViewNavigation static class).

Tig 1 年之前
父节点
当前提交
0c56dfeb5a

+ 4 - 4
Terminal.Gui/Application/Application.Keyboard.cs

@@ -330,7 +330,7 @@ public static partial class Application // Keyboard handling
                     () =>
                     {
                         // TODO: Move this method to Application.Navigation.cs
-                        Current.MoveNextView ();
+                        ViewNavigation.MoveNextView ();
 
                         return true;
                     }
@@ -341,7 +341,7 @@ public static partial class Application // Keyboard handling
                     () =>
                     {
                         // TODO: Move this method to Application.Navigation.cs
-                        Current.MovePreviousView ();
+                        ViewNavigation.MovePreviousView ();
 
                         return true;
                     }
@@ -352,7 +352,7 @@ public static partial class Application // Keyboard handling
                     () =>
                     {
                         // TODO: Move this method to Application.Navigation.cs
-                        Current.MoveNextViewOrTop ();
+                        ViewNavigation.MoveNextViewOrTop ();
 
                         return true;
                     }
@@ -363,7 +363,7 @@ public static partial class Application // Keyboard handling
                     () =>
                     {
                         // TODO: Move this method to Application.Navigation.cs
-                        Current.MovePreviousViewOrTop ();
+                        ViewNavigation.MovePreviousViewOrTop ();
 
                         return true;
                     }

+ 163 - 0
Terminal.Gui/Application/Application.Overlapped.cs

@@ -1,6 +1,169 @@
 #nullable enable
+using static Terminal.Gui.View;
+using System.Reflection;
+
 namespace Terminal.Gui;
 
+internal static class ViewNavigation
+{
+    /// <summary>
+    ///    Gets the deepest focused subview of the specified <paramref name="view"/>.
+    /// </summary>
+    /// <param name="view"></param>
+    /// <returns></returns>
+    internal static View GetDeepestFocusedSubview (View view)
+    {
+        if (view is null)
+        {
+            return null;
+        }
+
+        foreach (View v in view.Subviews)
+        {
+            if (v.HasFocus)
+            {
+                return GetDeepestFocusedSubview (v);
+            }
+        }
+
+        return view;
+    }
+
+    /// <summary>
+    ///    Sets the focus to the next view in the <see cref="TabIndexes"/> list. If the last view is focused, the first view is focused.
+    /// </summary>
+    /// <param name="viewsInTabIndexes"></param>
+    /// <param name="direction"></param>
+    internal static void FocusNearestView (IEnumerable<View>? viewsInTabIndexes, NavigationDirection direction)
+    {
+        if (viewsInTabIndexes is null)
+        {
+            return;
+        }
+
+        var found = false;
+        var focusProcessed = false;
+        var idx = 0;
+
+        foreach (View v in viewsInTabIndexes)
+        {
+            if (v == Application.Current)
+            {
+                found = true;
+            }
+
+            if (found && v != Application.Current)
+            {
+                if (direction == NavigationDirection.Forward)
+                {
+                    Application.Current.SuperView?.FocusNext ();
+                }
+                else
+                {
+                    Application.Current.SuperView?.FocusPrev ();
+                }
+
+                focusProcessed = true;
+
+                if (Application.Current.SuperView?.Focused is { } && Application.Current.SuperView.Focused != Application.Current)
+                {
+                    return;
+                }
+            }
+            else if (found && !focusProcessed && idx == viewsInTabIndexes.Count () - 1)
+            {
+                viewsInTabIndexes.ToList () [0].SetFocus ();
+            }
+
+            idx++;
+        }
+    }
+    /// <summary>
+    ///     Moves the focus to 
+    /// </summary>
+    internal static void MoveNextView ()
+    {
+        View old = GetDeepestFocusedSubview (Application.Current.Focused);
+
+        if (!Application.Current.FocusNext ())
+        {
+            Application.Current.FocusNext ();
+        }
+
+        if (old != Application.Current.Focused && old != Application.Current.Focused?.Focused)
+        {
+            old?.SetNeedsDisplay ();
+            Application.Current.Focused?.SetNeedsDisplay ();
+        }
+        else
+        {
+            FocusNearestView (Application.Current.SuperView?.TabIndexes, NavigationDirection.Forward);
+        }
+    }
+
+    internal static void MoveNextViewOrTop ()
+    {
+        if (Application.OverlappedTop is null)
+        {
+            Toplevel top = Application.Current.Modal ? Application.Current : Application.Top;
+            top.FocusNext ();
+
+            if (top.Focused is null)
+            {
+                top.FocusNext ();
+            }
+
+            top.SetNeedsDisplay ();
+            Application.BringOverlappedTopToFront ();
+        }
+        else
+        {
+            Application.OverlappedMoveNext ();
+        }
+    }
+
+    internal static void MovePreviousView ()
+    {
+        View old = GetDeepestFocusedSubview (Application.Current.Focused);
+
+        if (!Application.Current.FocusPrev ())
+        {
+            Application.Current.FocusPrev ();
+        }
+
+        if (old != Application.Current.Focused && old != Application.Current.Focused?.Focused)
+        {
+            old?.SetNeedsDisplay ();
+            Application.Current.Focused?.SetNeedsDisplay ();
+        }
+        else
+        {
+            FocusNearestView (Application.Current.SuperView?.TabIndexes?.Reverse (), NavigationDirection.Backward);
+        }
+    }
+
+    internal static void MovePreviousViewOrTop ()
+    {
+        if (Application.OverlappedTop is null)
+        {
+            Toplevel top = Application.Current.Modal ? Application.Current : Application.Top;
+            top.FocusPrev ();
+
+            if (top.Focused is null)
+            {
+                top.FocusPrev ();
+            }
+
+            top.SetNeedsDisplay ();
+            Application.BringOverlappedTopToFront ();
+        }
+        else
+        {
+            Application.OverlappedMovePrevious ();
+        }
+    }
+}
+
 public static partial class Application // App-level View Navigation
 {
  

+ 19 - 0
Terminal.Gui/Input/KeyBindings.cs

@@ -110,6 +110,25 @@ public class KeyBindings
         }
     }
 
+
+    /// <summary>
+    ///     <para>Adds a new key combination that will trigger the commands in <paramref name="commands"/>.</para>
+    ///     <para>
+    ///         If the key is already bound to a different array of <see cref="Command"/>s it will be rebound
+    ///         <paramref name="commands"/>.
+    ///     </para>
+    /// </summary>
+    /// <remarks>
+    ///     Commands are only ever applied to the current <see cref="View"/> (i.e. this feature cannot be used to switch
+    ///     focus to another view and perform multiple commands there).
+    /// </remarks>
+    /// <param name="key">The key to check.</param>
+    /// <param name="scope">The scope for the command.</param>
+    /// <param name="commands">
+    ///     The command to invoked on the <see cref="View"/> when <paramref name="key"/> is pressed. When
+    ///     multiple commands are provided,they will be applied in sequence. The bound <paramref name="key"/> strike will be
+    ///     consumed if any took effect.
+    /// </param>
     public void Add (Key key, KeyBindingScope scope,  params Command [] commands)
     {
         if (BoundView is { } && scope.FastHasFlags (KeyBindingScope.Application))

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

@@ -411,165 +411,7 @@ public partial class Toplevel : View
 
     /// <inheritdoc/>
     public override bool OnLeave (View view) { return MostFocused?.OnLeave (view) ?? base.OnLeave (view); }
-
-    /// <summary>
-    ///    Sets the focus to the next view in the <see cref="TabIndexes"/> list. If the last view is focused, the first view is focused.
-    /// </summary>
-    /// <param name="viewsInTabIndexes"></param>
-    /// <param name="direction"></param>
-    private void FocusNearestView (IEnumerable<View> viewsInTabIndexes, NavigationDirection direction)
-    {
-        if (viewsInTabIndexes is null)
-        {
-            return;
-        }
-
-        var found = false;
-        var focusProcessed = false;
-        var idx = 0;
-
-        foreach (View v in viewsInTabIndexes)
-        {
-            if (v == this)
-            {
-                found = true;
-            }
-
-            if (found && v != this)
-            {
-                if (direction == NavigationDirection.Forward)
-                {
-                    SuperView?.FocusNext ();
-                }
-                else
-                {
-                    SuperView?.FocusPrev ();
-                }
-
-                focusProcessed = true;
-
-                if (SuperView.Focused is { } && SuperView.Focused != this)
-                {
-                    return;
-                }
-            }
-            else if (found && !focusProcessed && idx == viewsInTabIndexes.Count () - 1)
-            {
-                viewsInTabIndexes.ToList () [0].SetFocus ();
-            }
-
-            idx++;
-        }
-    }
-
-    /// <summary>
-    ///    Gets the deepest focused subview of the specified <paramref name="view"/>.
-    /// </summary>
-    /// <param name="view"></param>
-    /// <returns></returns>
-    private View GetDeepestFocusedSubview (View view)
-    {
-        if (view is null)
-        {
-            return null;
-        }
-
-        foreach (View v in view.Subviews)
-        {
-            if (v.HasFocus)
-            {
-                return GetDeepestFocusedSubview (v);
-            }
-        }
-
-        return view;
-    }
-
-    /// <summary>
-    ///     Moves the focus to 
-    /// </summary>
-    internal void MoveNextView ()
-    {
-        View old = GetDeepestFocusedSubview (Focused);
-
-        if (!FocusNext ())
-        {
-            FocusNext ();
-        }
-
-        if (old != Focused && old != Focused?.Focused)
-        {
-            old?.SetNeedsDisplay ();
-            Focused?.SetNeedsDisplay ();
-        }
-        else
-        {
-            FocusNearestView (SuperView?.TabIndexes, NavigationDirection.Forward);
-        }
-    }
-
-    internal void MoveNextViewOrTop ()
-    {
-        if (Application.OverlappedTop is null)
-        {
-            Toplevel top = Modal ? this : Application.Top;
-            top.FocusNext ();
-
-            if (top.Focused is null)
-            {
-                top.FocusNext ();
-            }
-
-            top.SetNeedsDisplay ();
-            Application.BringOverlappedTopToFront ();
-        }
-        else
-        {
-            Application.OverlappedMoveNext ();
-        }
-    }
-
-    internal void MovePreviousView ()
-    {
-        View old = GetDeepestFocusedSubview (Focused);
-
-        if (!FocusPrev ())
-        {
-            FocusPrev ();
-        }
-
-        if (old != Focused && old != Focused?.Focused)
-        {
-            old?.SetNeedsDisplay ();
-            Focused?.SetNeedsDisplay ();
-        }
-        else
-        {
-            FocusNearestView (SuperView?.TabIndexes?.Reverse (), NavigationDirection.Backward);
-        }
-    }
-
-    internal void MovePreviousViewOrTop ()
-    {
-        if (Application.OverlappedTop is null)
-        {
-            Toplevel top = Modal ? this : Application.Top;
-            top.FocusPrev ();
-
-            if (top.Focused is null)
-            {
-                top.FocusPrev ();
-            }
-
-            top.SetNeedsDisplay ();
-            Application.BringOverlappedTopToFront ();
-        }
-        else
-        {
-            Application.OverlappedMovePrevious ();
-        }
-    }
-
+    
     #endregion
 
     #region Size / Position Management