Browse Source

Add in custom hit testing for ImmediateRenderer. Fixes #1879.

Jeremy Koritzinsky 7 years ago
parent
commit
bc850b49c1

+ 7 - 1
src/Avalonia.Controls/Primitives/AdornerLayer.cs

@@ -6,11 +6,12 @@ using System.Collections.Specialized;
 using System.Linq;
 using Avalonia.VisualTree;
 using Avalonia.Media;
+using Avalonia.Rendering;
 
 namespace Avalonia.Controls.Primitives
 {
     // TODO: Need to track position of adorned elements and move the adorner if they move.
-    public class AdornerLayer : Panel
+    public class AdornerLayer : Panel, ICustomSimpleHitTest
     {
         public static AttachedProperty<Visual> AdornedElementProperty =
             AvaloniaProperty.RegisterAttached<AdornerLayer, Visual, Visual>("AdornedElement");
@@ -137,6 +138,11 @@ namespace Avalonia.Controls.Primitives
             }
         }
 
+        public bool HitTest(Point point)
+        {
+            return Children.Any(ctrl => ctrl.TransformedBounds?.Contains(point) == true);
+        }
+
         private class AdornedElementInfo
         {
             public IDisposable Subscription { get; set; }

+ 12 - 0
src/Avalonia.Visuals/Rendering/ICustomSimpleHitTest.cs

@@ -0,0 +1,12 @@
+namespace Avalonia.Rendering
+{
+    /// <summary>
+    /// An interface to allow non-templated controls to customize their hit-testing
+    /// when using a renderer with a simple hit-testing algorithm without a scene graph,
+    /// such as <see cref="ImmediateRenderer" />
+    /// </summary>
+    public interface ICustomSimpleHitTest
+    {
+        bool HitTest(Point point);
+    }
+}

+ 10 - 1
src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs

@@ -200,7 +200,16 @@ namespace Avalonia.Rendering
 
             if (filter?.Invoke(visual) != false)
             {
-                bool containsPoint = visual.TransformedBounds?.Contains(p) == true;
+                bool containsPoint = false;
+
+                if (visual is ICustomSimpleHitTest custom)
+                {
+                    containsPoint = custom.HitTest(p);
+                }
+                else
+                {
+                    containsPoint = visual.TransformedBounds?.Contains(p) == true;
+                }
 
                 if ((containsPoint || !visual.ClipToBounds) && visual.VisualChildren.Count > 0)
                 {