Sfoglia il codice sorgente

Rewrote FindDeepestView to be clearer and more performant

Tig 1 anno fa
parent
commit
a6ff5629b4
1 ha cambiato i file con 44 aggiunte e 34 eliminazioni
  1. 44 34
      Terminal.Gui/View/Layout/ViewLayout.cs

+ 44 - 34
Terminal.Gui/View/Layout/ViewLayout.cs

@@ -605,53 +605,63 @@ public partial class View
     // CONCURRENCY: This method is not thread-safe. Undefined behavior and likely program crashes are exposed by unsynchronized access to InternalSubviews.
     // CONCURRENCY: This method is not thread-safe. Undefined behavior and likely program crashes are exposed by unsynchronized access to InternalSubviews.
     internal static View? FindDeepestView (View? start, int x, int y)
     internal static View? FindDeepestView (View? start, int x, int y)
     {
     {
-        if (start is null || !start.Visible || !start.Contains (x, y))
+        while (start is { Visible: true } && start.Contains (x, y))
         {
         {
-            return null;
-        }
-
-        Adornment? found = null;
+            Adornment? found = null;
 
 
-        if (start.Margin.Contains (x, y))
-        {
-            found = start.Margin;
-        }
-        else if (start.Border.Contains (x, y))
-        {
-            found = start.Border;
-        }
-        else if (start.Padding.Contains (x, y))
-        {
-            found = start.Padding;
-        }
+            if (start.Margin.Contains (x, y))
+            {
+                found = start.Margin;
+            }
+            else if (start.Border.Contains (x, y))
+            {
+                found = start.Border;
+            }
+            else if (start.Padding.Contains (x, y))
+            {
+                found = start.Padding;
+            }
 
 
-        Point viewportOffset = start.GetViewportOffsetFromFrame ();
+            Point viewportOffset = start.GetViewportOffsetFromFrame ();
 
 
-        if (found is { })
-        {
-            start = found;
-            viewportOffset = found.Parent.Frame.Location;
-        }
-
-        if (start.InternalSubviews is { Count: > 0 })
-        {
-            int startOffsetX = x - (start.Frame.X + viewportOffset.X);
-            int startOffsetY = y - (start.Frame.Y + viewportOffset.Y);
+            if (found is { })
+            {
+                start = found;
+                viewportOffset = found.Parent.Frame.Location;
+            }
 
 
-            for (int i = start.InternalSubviews.Count - 1; i >= 0; i--)
+            if (start.InternalSubviews is { Count: > 0 })
             {
             {
-                View nextStart = start.InternalSubviews [i];
+                int startOffsetX = x - (start.Frame.X + viewportOffset.X);
+                int startOffsetY = y - (start.Frame.Y + viewportOffset.Y);
 
 
-                if (nextStart.Visible && nextStart.Contains (startOffsetX + start.Viewport.X, startOffsetY + start.Viewport.Y))
+                for (int i = start.InternalSubviews.Count - 1; i >= 0; i--)
                 {
                 {
-                    // TODO: Remove recursion
-                    return FindDeepestView (nextStart, startOffsetX + start.Viewport.X, startOffsetY + start.Viewport.Y) ?? nextStart;
+                    View nextStart = start.InternalSubviews [i];
+
+                    if (nextStart.Visible && nextStart.Contains (startOffsetX + start.Viewport.X, startOffsetY + start.Viewport.Y))
+                    {
+                        start = nextStart;
+                        x = startOffsetX + start.Viewport.X;
+                        y = startOffsetY + start.Viewport.Y;
+                        break;
+                    }
+
+                    if (i == 0)
+                    {
+                        return start; // If no visible subview is found, return the current start view
+                    }
                 }
                 }
             }
             }
+            else
+            {
+                return start;
+            }
         }
         }
 
 
-        return start;
+        return null;
     }
     }
+
 #nullable restore
 #nullable restore
 
 
     /// <summary>
     /// <summary>