ソースを参照

Create IsViewLocationVisibleInViewport method.

BDisp 1 年間 前
コミット
46fcb58a71

+ 30 - 0
Terminal.Gui/View/Layout/ViewLayout.cs

@@ -689,6 +689,36 @@ public partial class View
 
 
 #nullable restore
 #nullable restore
 
 
+    /// <summary>
+    /// Determines if this view is currently visible in the visible <see cref="Viewport"/> area, 
+    /// given the passed x and y location coordinates.
+    /// </summary>
+    /// <param name="x">The x location.</param>
+    /// <param name="y">The y location.</param>
+    /// <returns><see langword="true"/> if it's visible, <see langword="false"/> otherwise.</returns>
+    public bool IsViewLocationVisibleInViewport (int x, int y)
+    {
+        Rectangle thisFrame = ViewportToScreen (Viewport);
+        Rectangle thisOffset = ViewportToScreen (new (new (x, y), new (Viewport.Width, Viewport.Height )));
+        View view;
+
+        if (Application.Current is { })
+        {
+            view = FindDeepestView (Application.Current, thisOffset.X, thisOffset.Y);
+        }
+        else if (SuperView is { })
+        {
+            Rectangle containerFrame = SuperView.ViewportToScreen (SuperView.Viewport);
+            view = containerFrame.IntersectsWith (thisOffset) ? this : null;
+        }
+        else
+        {
+            view = thisFrame.IntersectsWith (thisOffset) ? this : null;
+        }
+
+        return view == this;
+    }
+
     /// <summary>
     /// <summary>
     ///     Gets a new location of the <see cref="View"/> that is within the Viewport of the <paramref name="viewToMove"/>'s
     ///     Gets a new location of the <see cref="View"/> that is within the Viewport of the <paramref name="viewToMove"/>'s
     ///     <see cref="View.SuperView"/> (e.g. for dragging a Window). The `out` parameters are the new X and Y coordinates.
     ///     <see cref="View.SuperView"/> (e.g. for dragging a Window). The `out` parameters are the new X and Y coordinates.

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

@@ -1196,10 +1196,10 @@ public class TextField : View
 
 
         int pos = _cursorPosition - ScrollOffset + Math.Min (Frame.X, 0);
         int pos = _cursorPosition - ScrollOffset + Math.Min (Frame.X, 0);
         int offB = OffSetBackground ();
         int offB = OffSetBackground ();
-        var thisOffset = ViewportToScreen (new (new (col, Viewport.Y), new (Viewport.Width - col, Viewport.Height - Viewport.Y)));
-        var view = Application.Current is { } ? FindDeepestView (Application.Current, thisOffset.X, thisOffset.Y) : this;
+        bool isVisibleInViewport = IsViewLocationVisibleInViewport (col, Viewport.Y);
 
 
-        if (view == this && pos > -1
+        if (isVisibleInViewport
+            && pos > -1
             && col >= pos
             && col >= pos
             && pos < Frame.Width + offB)
             && pos < Frame.Width + offB)
         {
         {

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

@@ -3888,10 +3888,9 @@ public class TextView : View
 
 
         int posX = CurrentColumn - _leftColumn;
         int posX = CurrentColumn - _leftColumn;
         int posY = CurrentRow - _topRow;
         int posY = CurrentRow - _topRow;
-        var thisOffset = ViewportToScreen (new (new (col, posY), new (Viewport.Width - col, Viewport.Height - posY)));
-        var view = Application.Current is { } ? FindDeepestView (Application.Current, thisOffset.X, thisOffset.Y)  : this;
+        bool isVisibleInViewport = IsViewLocationVisibleInViewport (col, posY);
 
 
-        if (view == this && posX > -1 && col >= posX && posX < Frame.Width - RightOffset && _topRow <= CurrentRow && posY < Frame.Height - BottomOffset)
+        if (isVisibleInViewport && posX > -1 && col >= posX && posX < Frame.Width - RightOffset && _topRow <= CurrentRow && posY < Frame.Height - BottomOffset)
         {
         {
             ResetCursorVisibility ();
             ResetCursorVisibility ();
             Move (col, CurrentRow - _topRow);
             Move (col, CurrentRow - _topRow);

+ 90 - 0
UnitTests/View/Layout/ViewportTests.cs

@@ -359,4 +359,94 @@ public class ViewportTests (ITestOutputHelper output)
         Assert.Equal (view.Viewport.Size, view.ContentSize);
         Assert.Equal (view.Viewport.Size, view.ContentSize);
     }
     }
 
 
+    [Theory]
+    [InlineData (0, 0, true)]
+    [InlineData (-1, 0, true)]
+    [InlineData (0, -1, true)]
+    [InlineData (-1, -1, true)]
+    [InlineData (-2, -2, true)]
+    [InlineData (-3, -3, true)]
+    [InlineData (-4, -4, true)]
+    [InlineData (-5, -4, false)]
+    [InlineData (-4, -5, false)]
+    [InlineData (-5, -5, false)]
+
+    [InlineData (1, 1, true)]
+    [InlineData (2, 2, true)]
+    [InlineData (3, 3, true)]
+    [InlineData (4, 4, true)]
+    [InlineData (5, 4, false)]
+    [InlineData (4, 5, false)]
+    [InlineData (5, 5, false)]
+    public void IsViewVisibleInViewport_No_Driver_No_SuperView (int x, int y, bool expected)
+    {
+        var view = new View { X = 1, Y = 1, Width = 5, Height = 5 };
+        Assert.True (view.IsViewLocationVisibleInViewport (x, y) == expected);
+    }
+
+    [Theory]
+    [InlineData (0, 0, true)]
+    [InlineData (-1, 0, true)]
+    [InlineData (0, -1, true)]
+    [InlineData (-1, -1, true)]
+    [InlineData (-2, -2, true)]
+    [InlineData (-3, -3, true)]
+    [InlineData (-4, -4, true)]
+    [InlineData (-5, -4, true)]
+    [InlineData (-4, -5, true)]
+    [InlineData (-5, -5, true)]
+    [InlineData (-6, -5, false)]
+    [InlineData (-5, -6, false)]
+    [InlineData (-6, -6, false)]
+
+    [InlineData (1, 1, true)]
+    [InlineData (2, 2, true)]
+    [InlineData (3, 3, true)]
+    [InlineData (4, 4, true)]
+    [InlineData (5, 4, true)]
+    [InlineData (4, 5, true)]
+    [InlineData (5, 5, true)]
+    [InlineData (6, 5, true)]
+    [InlineData (6, 6, true)]
+    [InlineData (7, 7, true)]
+    [InlineData (8, 8, true)]
+    [InlineData (9, 8, false)]
+    [InlineData (8, 9, false)]
+    [InlineData (9, 9, false)]
+    public void IsViewVisibleInViewport_No_Driver_With_SuperView (int x, int y, bool expected)
+    {
+        var view = new View { X = 1, Y = 1, Width = 5, Height = 5 };
+        var top = new Toplevel { Width = 10, Height = 10 };
+        top.Add (view);
+
+        Assert.True (view.IsViewLocationVisibleInViewport (x, y) == expected);
+    }
+
+    [SetupFakeDriver]
+    [Theory]
+    [InlineData (0, 0, true)]
+    [InlineData (-1, 0, false)]
+    [InlineData (0, -1, false)]
+    [InlineData (-1, -1, false)]
+
+    [InlineData (1, 0, true)]
+    [InlineData (0, 1, true)]
+    [InlineData (1, 1, true)]
+    [InlineData (2, 2, true)]
+    [InlineData (3, 3, true)]
+    [InlineData (4, 4, true)]
+    [InlineData (5, 4, false)]
+    [InlineData (4, 5, false)]
+    [InlineData (5, 5, false)]
+    public void IsViewVisibleInViewport_With_Driver (int x, int y, bool expected)
+    {
+        ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
+
+        var view = new View { X = 1, Y = 1, Width = 5, Height = 5 };
+        var top = new Toplevel ();
+        top.Add (view);
+        Application.Begin (top);
+
+        Assert.True (view.IsViewLocationVisibleInViewport (x, y) == expected);
+    }
 }
 }