Bläddra i källkod

Fixed focus issue - 3

Tig 10 månader sedan
förälder
incheckning
697711ad2d

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

@@ -28,6 +28,7 @@ public class Adornment : View
     {
         // By default Adornments can't get focus; has to be enabled specifically.
         CanFocus = false;
+        TabStop = TabBehavior.NoStop;
         Parent = parent;
     }
 

+ 4 - 1
Terminal.Gui/View/View.Hierarchy.cs

@@ -162,7 +162,10 @@ public partial class View // SuperView/SubView hierarchy management (SuperView,
         bool hadFocus = view.HasFocus;
         bool couldFocus = view.CanFocus;
 
-        view.CanFocus = false; // If view had focus, this will ensure it doesn't and it stays that way
+        if (hadFocus)
+        {
+            view.CanFocus = false; // If view had focus, this will ensure it doesn't and it stays that way
+        }
         Debug.Assert (!view.HasFocus);
 
         _subviews.Remove (view);

+ 21 - 18
Terminal.Gui/View/View.Navigation.cs

@@ -286,14 +286,11 @@ public partial class View // Focus and cross-view navigation management (TabStop
     /// </returns>
     internal bool RestoreFocus ()
     {
-        if (Focused is null && _subviews?.Count > 0)
-        {
-            if (_previouslyFocused is { })
-            {
-                return _previouslyFocused.SetFocus ();
-            }
+        View [] indicies = GetFocusChain (NavigationDirection.Forward, TabStop);
 
-            return false;
+        if (Focused is null && _previouslyFocused is { } && indicies.Contains (_previouslyFocused))
+        {
+            return _previouslyFocused.SetFocus ();
         }
 
         return false;
@@ -368,6 +365,12 @@ public partial class View // Focus and cross-view navigation management (TabStop
             else
             {
                 SetHasFocusFalse (null);
+
+                if (_hasFocus)
+                {
+                    // force it.
+                    _hasFocus = false;
+                }
             }
         }
         get => _hasFocus;
@@ -477,25 +480,18 @@ public partial class View // Focus and cross-view navigation management (TabStop
                 if (!AdvanceFocus (NavigationDirection.Forward, null))
                 {
                     // Couldn't advance, so we're the most focused view in the application
+                    Application.Navigation?.SetFocused (this);
                 }
             }
         }
 
-        if (previousFocusedView is { HasFocus: true } && Subviews.Contains (previousFocusedView))
+        if (previousFocusedView is { HasFocus: true } && GetFocusChain (NavigationDirection.Forward, TabStop).Contains (previousFocusedView))
         {
             previousFocusedView.SetHasFocusFalse (this);
-        }
-
-        if (previousFocusedView is { HasFocus: true })
-        {
-            if (previousFocusedView.SuperView is Adornment a)
-            {
-                previousFocusedView.SetHasFocusFalse (this);
-            }
+            Debug.Assert (!_hasFocus);
         }
 
         _previouslyFocused = null;
-        Application.Navigation?.SetFocused (this);
 
         if (Arrangement.HasFlag (ViewArrangement.Overlapped))
         {
@@ -633,6 +629,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
             // No other focusable view to be found. Just "leave" us...
         }
 
+
         // Before we can leave focus, we need to make sure that all views down the subview-hierarchy have left focus.
         View? mostFocused = MostFocused;
 
@@ -646,6 +643,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
                 if (bottom.HasFocus)
                 {
                     bottom.SetHasFocusFalse (newFocusedView, true);
+
+                    Debug.Assert (_hasFocus);
                 }
 
                 bottom = bottom.SuperView;
@@ -653,9 +652,13 @@ public partial class View // Focus and cross-view navigation management (TabStop
 
             if (bottom == this && bottom.SuperView is Adornment a)
             {
-                a.SetHasFocusFalse (newFocusedView, true);
+                //a.SetHasFocusFalse (newFocusedView, true);
+
+                Debug.Assert (_hasFocus);
             }
 
+            Debug.Assert (_hasFocus);
+
         }
 
         if (superViewOrParent is { })

+ 20 - 18
UICatalog/Scenarios/ContentScrolling.cs

@@ -128,12 +128,13 @@ public class ContentScrolling : Scenario
         // Add Scroll Setting UI to Padding
         view.Padding.Thickness = new (0, 3, 0, 0);
         view.Padding.ColorScheme = Colors.ColorSchemes ["Error"];
+        view.Padding.CanFocus = true;
 
         var cbAllowNegativeX = new CheckBox
         {
             Title = "Allow _X < 0",
             Y = 0,
-            CanFocus = false
+            CanFocus = true
         };
         cbAllowNegativeX.CheckedState = view.ViewportSettings.HasFlag(ViewportSettings.AllowNegativeX) ? CheckState.Checked : CheckState.UnChecked;
         cbAllowNegativeX.CheckedStateChanging += AllowNegativeX_Toggle;
@@ -157,7 +158,7 @@ public class ContentScrolling : Scenario
             Title = "Allow _Y < 0",
             X = Pos.Right (cbAllowNegativeX) + 1,
             Y = 0,
-            CanFocus = false
+            CanFocus = true
         };
         cbAllowNegativeY.CheckedState = view.ViewportSettings.HasFlag(ViewportSettings.AllowNegativeY) ? CheckState.Checked : CheckState.UnChecked;
         cbAllowNegativeY.CheckedStateChanging += AllowNegativeY_Toggle;
@@ -180,7 +181,7 @@ public class ContentScrolling : Scenario
         {
             Title = "All_ow X > Content",
             Y = Pos.Bottom (cbAllowNegativeX),
-            CanFocus = false
+            CanFocus = true
         };
         cbAllowXGreaterThanContentWidth.CheckedState = view.ViewportSettings.HasFlag(ViewportSettings.AllowXGreaterThanContentWidth) ? CheckState.Checked : CheckState.UnChecked;
         cbAllowXGreaterThanContentWidth.CheckedStateChanging += AllowXGreaterThanContentWidth_Toggle;
@@ -204,7 +205,7 @@ public class ContentScrolling : Scenario
             Title = "Allo_w Y > Content",
             X = Pos.Right (cbAllowXGreaterThanContentWidth) + 1,
             Y = Pos.Bottom (cbAllowNegativeX),
-            CanFocus = false
+            CanFocus = true
         };
         cbAllowYGreaterThanContentHeight.CheckedState = view.ViewportSettings.HasFlag(ViewportSettings.AllowYGreaterThanContentHeight) ? CheckState.Checked : CheckState.UnChecked;
         cbAllowYGreaterThanContentHeight.CheckedStateChanging += AllowYGreaterThanContentHeight_Toggle;
@@ -233,7 +234,8 @@ public class ContentScrolling : Scenario
         {
             Value = view.GetContentSize ().Width,
             X = Pos.Right (labelContentSize) + 1,
-            Y = Pos.Top (labelContentSize)
+            Y = Pos.Top (labelContentSize),
+            CanFocus = true
         };
         contentSizeWidth.ValueChanging += ContentSizeWidth_ValueChanged;
 
@@ -261,7 +263,7 @@ public class ContentScrolling : Scenario
             Value = view.GetContentSize ().Height,
             X = Pos.Right (labelComma) + 1,
             Y = Pos.Top (labelContentSize),
-            CanFocus = false
+            CanFocus = true
         };
         contentSizeHeight.ValueChanging += ContentSizeHeight_ValueChanged;
 
@@ -277,17 +279,17 @@ public class ContentScrolling : Scenario
             view.SetContentSize (view.GetContentSize () with { Height = e.NewValue });
         }
 
-        var cbClearOnlyVisible = new CheckBox
+        var cbClearContentOnly = new CheckBox
         {
             Title = "ClearContentOnly",
             X = Pos.Right (contentSizeHeight) + 1,
             Y = Pos.Top (labelContentSize),
-            CanFocus = false
+            CanFocus = true
         };
-        cbClearOnlyVisible.CheckedState = view.ViewportSettings.HasFlag(ViewportSettings.ClearContentOnly) ? CheckState.Checked : CheckState.UnChecked;
-        cbClearOnlyVisible.CheckedStateChanging += ClearVisibleContentOnly_Toggle;
+        cbClearContentOnly.CheckedState = view.ViewportSettings.HasFlag(ViewportSettings.ClearContentOnly) ? CheckState.Checked : CheckState.UnChecked;
+        cbClearContentOnly.CheckedStateChanging += ClearContentOnly_Toggle;
 
-        void ClearVisibleContentOnly_Toggle (object sender, CancelEventArgs<CheckState> e)
+        void ClearContentOnly_Toggle (object sender, CancelEventArgs<CheckState> e)
         {
             if (e.NewValue == CheckState.Checked)
             {
@@ -299,17 +301,17 @@ public class ContentScrolling : Scenario
             }
         }
 
-        var cbDoNotClipContent = new CheckBox
+        var cbClipContentOnly = new CheckBox
         {
             Title = "ClipContentOnly",
-            X = Pos.Right (cbClearOnlyVisible) + 1,
+            X = Pos.Right (cbClearContentOnly) + 1,
             Y = Pos.Top (labelContentSize),
-            CanFocus = false
+            CanFocus = true
         };
-        cbDoNotClipContent.CheckedState = view.ViewportSettings.HasFlag (ViewportSettings.ClipContentOnly) ? CheckState.Checked : CheckState.UnChecked;
-        cbDoNotClipContent.CheckedStateChanging += ClipVisibleContentOnly_Toggle;
+        cbClipContentOnly.CheckedState = view.ViewportSettings.HasFlag (ViewportSettings.ClipContentOnly) ? CheckState.Checked : CheckState.UnChecked;
+        cbClipContentOnly.CheckedStateChanging += ClipContentOnlyOnly_Toggle;
 
-        void ClipVisibleContentOnly_Toggle (object sender, CancelEventArgs<CheckState> e)
+        void ClipContentOnlyOnly_Toggle (object sender, CancelEventArgs<CheckState> e)
         {
             if (e.NewValue == CheckState.Checked)
             {
@@ -321,7 +323,7 @@ public class ContentScrolling : Scenario
             }
         }
 
-        view.Padding.Add (labelContentSize, contentSizeWidth, labelComma, contentSizeHeight, cbClearOnlyVisible, cbDoNotClipContent);
+        view.Padding.Add (labelContentSize, contentSizeWidth, labelComma, contentSizeHeight, cbClearContentOnly, cbClipContentOnly);
 
         // Add demo views to show that things work correctly
         var textField = new TextField { X = 20, Y = 7, Width = 15, Text = "Test TextField" };

+ 1 - 1
UnitTests/View/Navigation/CanFocusTests.cs

@@ -329,7 +329,7 @@ public class CanFocusTests () : TestsAllViews
         Application.Current.Add (label, view);
 
         Application.Current.SetFocus ();
-        Assert.Equal (view, Application.Navigation.GetFocused());
+        Assert.Equal (view, Application.Navigation.GetFocused ());
         Assert.False (label.CanFocus);
         Assert.False (label.HasFocus);
         Assert.True (view.CanFocus);