Browse Source

Accept root in IRenderer.HitTest.

Fixes #1221.
pull/1223/head
Steven Kirk 8 years ago
parent
commit
880cf657ec
  1. 4
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  2. 8
      src/Avalonia.Visuals/Rendering/IRenderer.cs
  3. 4
      src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs
  4. 7
      src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
  5. 2
      src/Avalonia.Visuals/VisualTree/VisualExtensions.cs
  6. 4
      tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs
  7. 2
      tests/Avalonia.LeakTests/ControlTests.cs
  8. 32
      tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests_HitTesting.cs
  9. 22
      tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests_HitTesting.cs

4
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@ -106,7 +106,7 @@ namespace Avalonia.Rendering
public void Dispose() => Stop(); public void Dispose() => Stop();
/// <inheritdoc/> /// <inheritdoc/>
public IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter) public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
{ {
if (_renderLoop == null && (_dirty == null || _dirty.Count > 0)) if (_renderLoop == null && (_dirty == null || _dirty.Count > 0))
{ {
@ -114,7 +114,7 @@ namespace Avalonia.Rendering
UpdateScene(); UpdateScene();
} }
return _scene?.HitTest(p, filter) ?? Enumerable.Empty<IVisual>(); return _scene?.HitTest(p, root, filter) ?? Enumerable.Empty<IVisual>();
} }
/// <inheritdoc/> /// <inheritdoc/>

8
src/Avalonia.Visuals/Rendering/IRenderer.cs

@ -33,9 +33,13 @@ namespace Avalonia.Rendering
/// Hit tests a location to find the visuals at the specified point. /// Hit tests a location to find the visuals at the specified point.
/// </summary> /// </summary>
/// <param name="p">The point, in client coordinates.</param> /// <param name="p">The point, in client coordinates.</param>
/// <param name="filter">An optional filter.</param> /// <param name="root">The root of the subtree to search.</param>
/// <param name="filter">
/// A filter predicate. If the predicate returns false then the visual and all its
/// children will be excluded from the results.
/// </param>
/// <returns>The visuals at the specified point, topmost first.</returns> /// <returns>The visuals at the specified point, topmost first.</returns>
IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter); IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter);
/// <summary> /// <summary>
/// Called when a resize notification is received by the control being rendered. /// Called when a resize notification is received by the control being rendered.

4
src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs

@ -136,9 +136,9 @@ namespace Avalonia.Rendering
} }
/// <inheritdoc/> /// <inheritdoc/>
public IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter) public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
{ {
return HitTest(_root, p, filter); return HitTest(root, p, filter);
} }
/// <inheritdoc/> /// <inheritdoc/>

7
src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Avalonia.VisualTree; using Avalonia.VisualTree;
namespace Avalonia.Rendering.SceneGraph namespace Avalonia.Rendering.SceneGraph
@ -113,11 +114,13 @@ namespace Avalonia.Rendering.SceneGraph
/// Gets the visuals at a point in the scene. /// Gets the visuals at a point in the scene.
/// </summary> /// </summary>
/// <param name="p">The point.</param> /// <param name="p">The point.</param>
/// <param name="root">The root of the subtree to search.</param>
/// <param name="filter">A filter. May be null.</param> /// <param name="filter">A filter. May be null.</param>
/// <returns>The visuals at the specified point.</returns> /// <returns>The visuals at the specified point.</returns>
public IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter) public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
{ {
return HitTest(Root, p, null, filter); var node = FindNode(root);
return (node != null) ? HitTest(node, p, null, filter) : Enumerable.Empty<IVisual>();
} }
/// <summary> /// <summary>

2
src/Avalonia.Visuals/VisualTree/VisualExtensions.cs

@ -133,7 +133,7 @@ namespace Avalonia.VisualTree
var root = visual.GetVisualRoot(); var root = visual.GetVisualRoot();
p = visual.TranslatePoint(p, root); p = visual.TranslatePoint(p, root);
return root.Renderer.HitTest(p, filter); return root.Renderer.HitTest(p, visual, filter);
} }
/// <summary> /// <summary>

4
tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs

@ -59,7 +59,7 @@ namespace Avalonia.Input.UnitTests
} }
}; };
renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<Func<IVisual, bool>>())) renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<IVisual>(), It.IsAny<Func<IVisual, bool>>()))
.Returns(new[] { decorator }); .Returns(new[] { decorator });
inputManager.ProcessInput(new RawMouseEventArgs( inputManager.ProcessInput(new RawMouseEventArgs(
@ -75,7 +75,7 @@ namespace Avalonia.Input.UnitTests
Assert.False(canvas.IsPointerOver); Assert.False(canvas.IsPointerOver);
Assert.True(root.IsPointerOver); Assert.True(root.IsPointerOver);
renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<Func<IVisual, bool>>())) renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<IVisual>(), It.IsAny<Func<IVisual, bool>>()))
.Returns(new[] { canvas }); .Returns(new[] { canvas });
inputManager.ProcessInput(new RawMouseEventArgs( inputManager.ProcessInput(new RawMouseEventArgs(

2
tests/Avalonia.LeakTests/ControlTests.cs

@ -357,7 +357,7 @@ namespace Avalonia.LeakTests
{ {
} }
public IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter) => null; public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter) => null;
public void Paint(Rect rect) public void Paint(Rect rect)
{ {

32
tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests_HitTesting.cs

@ -42,7 +42,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Equal(new[] { root.Child }, result); Assert.Equal(new[] { root.Child }, result);
} }
@ -70,7 +70,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Empty(result); Assert.Empty(result);
} }
@ -107,7 +107,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Empty(result); Assert.Empty(result);
} }
@ -136,7 +136,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
var result = root.Renderer.HitTest(new Point(10, 10), null); var result = root.Renderer.HitTest(new Point(10, 10), root, null);
Assert.Empty(result); Assert.Empty(result);
} }
@ -180,7 +180,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(container.DesiredSize)); root.Arrange(new Rect(container.DesiredSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Equal(new[] { container.Children[1], container.Children[0] }, result); Assert.Equal(new[] { container.Children[1], container.Children[0] }, result);
} }
@ -234,7 +234,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(container.DesiredSize)); root.Arrange(new Rect(container.DesiredSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Equal(new[] { container.Children[2], container.Children[0], container.Children[1] }, result); Assert.Equal(new[] { container.Children[2], container.Children[0], container.Children[1] }, result);
} }
@ -283,7 +283,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
container.Measure(Size.Infinity); container.Measure(Size.Infinity);
container.Arrange(new Rect(container.DesiredSize)); container.Arrange(new Rect(container.DesiredSize));
var result = root.Renderer.HitTest(new Point(120, 120), null); var result = root.Renderer.HitTest(new Point(120, 120), root, null);
Assert.Equal(new IVisual[] { target, container }, result); Assert.Equal(new IVisual[] { target, container }, result);
} }
@ -331,7 +331,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(container.DesiredSize)); root.Arrange(new Rect(container.DesiredSize));
var result = root.Renderer.HitTest(new Point(50, 50), null); var result = root.Renderer.HitTest(new Point(50, 50), root, null);
Assert.Equal(new[] { container }, result); Assert.Equal(new[] { container }, result);
} }
@ -404,11 +404,11 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(container.DesiredSize)); root.Arrange(new Rect(container.DesiredSize));
var result = root.Renderer.HitTest(new Point(50, 150), null).First(); var result = root.Renderer.HitTest(new Point(50, 150), root, null).First();
Assert.Equal(item1, result); Assert.Equal(item1, result);
result = root.Renderer.HitTest(new Point(50, 50), null).First(); result = root.Renderer.HitTest(new Point(50, 50), root, null).First();
Assert.Equal(target, result); Assert.Equal(target, result);
@ -419,10 +419,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
container.InvalidateArrange(); container.InvalidateArrange();
container.Arrange(new Rect(container.DesiredSize)); container.Arrange(new Rect(container.DesiredSize));
result = root.Renderer.HitTest(new Point(50, 150), null).First(); result = root.Renderer.HitTest(new Point(50, 150), root, null).First();
Assert.Equal(item2, result); Assert.Equal(item2, result);
result = root.Renderer.HitTest(new Point(50, 50), null).First(); result = root.Renderer.HitTest(new Point(50, 50), root, null).First();
Assert.Equal(target, result); Assert.Equal(target, result);
} }
} }
@ -452,10 +452,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
var context = new DrawingContext(Mock.Of<IDrawingContextImpl>()); var context = new DrawingContext(Mock.Of<IDrawingContextImpl>());
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Equal(new[] { path }, result); Assert.Equal(new[] { path }, result);
result = root.Renderer.HitTest(new Point(10, 10), null); result = root.Renderer.HitTest(new Point(10, 10), root, null);
Assert.Empty(result); Assert.Empty(result);
} }
} }
@ -492,10 +492,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
var context = new DrawingContext(Mock.Of<IDrawingContextImpl>()); var context = new DrawingContext(Mock.Of<IDrawingContextImpl>());
var result = root.Renderer.HitTest(new Point(200, 200), null); var result = root.Renderer.HitTest(new Point(200, 200), root, null);
Assert.Equal(new IVisual[] { canvas, border }, result); Assert.Equal(new IVisual[] { canvas, border }, result);
result = root.Renderer.HitTest(new Point(110, 110), null); result = root.Renderer.HitTest(new Point(110, 110), root, null);
Assert.Empty(result); Assert.Empty(result);
} }
} }

22
tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests_HitTesting.cs

@ -40,7 +40,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Equal(new[] { root.Child, root }, result); Assert.Equal(new[] { root.Child, root }, result);
} }
@ -78,7 +78,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Equal(new[] { root }, result); Assert.Equal(new[] { root }, result);
} }
@ -108,7 +108,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
var result = root.Renderer.HitTest(new Point(10, 10), null); var result = root.Renderer.HitTest(new Point(10, 10), root, null);
Assert.Equal(new[] { root }, result); Assert.Equal(new[] { root }, result);
} }
@ -153,7 +153,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Arrange(new Rect(container.DesiredSize)); root.Arrange(new Rect(container.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Equal(new[] { container.Children[1], container.Children[0], container, root }, result); Assert.Equal(new[] { container.Children[1], container.Children[0], container, root }, result);
} }
@ -208,7 +208,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Arrange(new Rect(container.DesiredSize)); root.Arrange(new Rect(container.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
var result = root.Renderer.HitTest(new Point(100, 100), null); var result = root.Renderer.HitTest(new Point(100, 100), root, null);
Assert.Equal( Assert.Equal(
new[] new[]
@ -267,7 +267,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
container.Arrange(new Rect(container.DesiredSize)); container.Arrange(new Rect(container.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
var result = root.Renderer.HitTest(new Point(120, 120), null); var result = root.Renderer.HitTest(new Point(120, 120), root, null);
Assert.Equal(new IVisual[] { target, container }, result); Assert.Equal(new IVisual[] { target, container }, result);
} }
@ -316,7 +316,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Arrange(new Rect(container.DesiredSize)); root.Arrange(new Rect(container.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
var result = root.Renderer.HitTest(new Point(50, 50), null); var result = root.Renderer.HitTest(new Point(50, 50), root, null);
Assert.Equal(new IVisual[] { container, root }, result); Assert.Equal(new IVisual[] { container, root }, result);
} }
@ -390,11 +390,11 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Arrange(new Rect(container.DesiredSize)); root.Arrange(new Rect(container.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
var result = root.Renderer.HitTest(new Point(50, 150), null).First(); var result = root.Renderer.HitTest(new Point(50, 150), root, null).First();
Assert.Equal(item1, result); Assert.Equal(item1, result);
result = root.Renderer.HitTest(new Point(50, 50), null).First(); result = root.Renderer.HitTest(new Point(50, 50), root, null).First();
Assert.Equal(target, result); Assert.Equal(target, result);
@ -406,10 +406,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
container.Arrange(new Rect(container.DesiredSize)); container.Arrange(new Rect(container.DesiredSize));
root.Renderer.Paint(new Rect(root.ClientSize)); root.Renderer.Paint(new Rect(root.ClientSize));
result = root.Renderer.HitTest(new Point(50, 150), null).First(); result = root.Renderer.HitTest(new Point(50, 150), root, null).First();
Assert.Equal(item2, result); Assert.Equal(item2, result);
result = root.Renderer.HitTest(new Point(50, 50), null).First(); result = root.Renderer.HitTest(new Point(50, 50), root, null).First();
Assert.Equal(target, result); Assert.Equal(target, result);
} }
} }

Loading…
Cancel
Save