Browse Source

Merge branch 'master' into fixes/FontMetrics

pull/4863/head
Benedikt Stebner 6 years ago
committed by GitHub
parent
commit
2d5aea524b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      src/Avalonia.Controls/Shapes/Shape.cs
  2. 17
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
  3. 65
      src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
  4. 9
      tests/Avalonia.Controls.UnitTests/CanvasTests.cs
  5. 15
      tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs
  6. 6
      tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs
  7. 57
      tests/Avalonia.Controls.UnitTests/Shapes/EllipseTests.cs
  8. 144
      tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs
  9. 56
      tests/Avalonia.Controls.UnitTests/Shapes/RectangleTests.cs
  10. 13
      tests/Avalonia.Controls.UnitTests/ViewboxTests.cs
  11. 113
      tests/Avalonia.Layout.UnitTests/ShapeLayoutTests.cs
  12. 2
      tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs

44
src/Avalonia.Controls/Shapes/Shape.cs

@ -62,7 +62,6 @@ namespace Avalonia.Controls.Shapes
private Matrix _transform = Matrix.Identity;
private Geometry? _definingGeometry;
private Geometry? _renderedGeometry;
private bool _calculateTransformOnArrange;
static Shape()
{
@ -248,52 +247,21 @@ namespace Avalonia.Controls.Shapes
protected override Size MeasureOverride(Size availableSize)
{
bool deferCalculateTransform;
switch (Stretch)
if (DefiningGeometry is null)
{
case Stretch.Fill:
case Stretch.UniformToFill:
deferCalculateTransform = double.IsInfinity(availableSize.Width) || double.IsInfinity(availableSize.Height);
break;
case Stretch.Uniform:
deferCalculateTransform = double.IsInfinity(availableSize.Width) && double.IsInfinity(availableSize.Height);
break;
case Stretch.None:
default:
deferCalculateTransform = false;
break;
return default;
}
if (deferCalculateTransform)
{
_calculateTransformOnArrange = true;
return DefiningGeometry?.Bounds.Size ?? Size.Empty;
}
else
{
_calculateTransformOnArrange = false;
return CalculateShapeSizeAndSetTransform(availableSize);
}
return CalculateSizeAndTransform(availableSize, DefiningGeometry.Bounds, Stretch).size;
}
protected override Size ArrangeOverride(Size finalSize)
{
if (_calculateTransformOnArrange)
{
_calculateTransformOnArrange = false;
CalculateShapeSizeAndSetTransform(finalSize);
}
return finalSize;
}
private Size CalculateShapeSizeAndSetTransform(Size availableSize)
{
if (DefiningGeometry != null)
{
// This should probably use GetRenderBounds(strokeThickness) but then the calculations
// will multiply the stroke thickness as well, which isn't correct.
var (size, transform) = CalculateSizeAndTransform(availableSize, DefiningGeometry.Bounds, Stretch);
var (_, transform) = CalculateSizeAndTransform(finalSize, DefiningGeometry.Bounds, Stretch);
if (_transform != transform)
{
@ -301,13 +269,13 @@ namespace Avalonia.Controls.Shapes
_renderedGeometry = null;
}
return size;
return finalSize;
}
return Size.Empty;
}
internal static (Size, Matrix) CalculateSizeAndTransform(Size availableSize, Rect shapeBounds, Stretch Stretch)
internal static (Size size, Matrix transform) CalculateSizeAndTransform(Size availableSize, Rect shapeBounds, Stretch Stretch)
{
Size shapeSize = new Size(shapeBounds.Right, shapeBounds.Bottom);
Matrix translate = Matrix.Identity;

17
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@ -343,16 +343,21 @@ namespace Avalonia.Win32
case WindowsMessage.WM_PAINT:
{
using (_rendererLock.Lock())
using (_rendererLock.Lock())
{
if (BeginPaint(_hwnd, out PAINTSTRUCT ps) != IntPtr.Zero)
{
Paint?.Invoke(default);
var f = RenderScaling;
var r = ps.rcPaint;
Paint?.Invoke(new Rect(r.left / f, r.top / f, (r.right - r.left) / f,
(r.bottom - r.top) / f));
EndPaint(_hwnd, ref ps);
}
ValidateRect(hWnd, IntPtr.Zero);
return IntPtr.Zero;
}
return IntPtr.Zero;
}
case WindowsMessage.WM_SIZE:
{
using (_rendererLock.Lock())

65
src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs

@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using Avalonia.Controls;
using Avalonia.Input;
using static Avalonia.Win32.Interop.UnmanagedMethods;
@ -11,70 +10,78 @@ namespace Avalonia.Win32
public partial class WindowImpl
{
// Hit test the frame for resizing and moving.
HitTestValues HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
private HitTestValues HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
{
// Get the point coordinates for the hit test.
// Get the point coordinates for the hit test (screen space).
var ptMouse = PointFromLParam(lParam);
// Get the window rectangle.
// Get the window rectangle.
GetWindowRect(hWnd, out var rcWindow);
// Get the frame rectangle, adjusted for the style without a caption.
RECT rcFrame = new RECT();
var rcFrame = new RECT();
AdjustWindowRectEx(ref rcFrame, (uint)(WindowStyles.WS_OVERLAPPEDWINDOW & ~WindowStyles.WS_CAPTION), false, 0);
RECT border_thickness = new RECT();
var borderThickness = new RECT();
if (GetStyle().HasFlag(WindowStyles.WS_THICKFRAME))
{
AdjustWindowRectEx(ref border_thickness, (uint)(GetStyle()), false, 0);
border_thickness.left *= -1;
border_thickness.top *= -1;
AdjustWindowRectEx(ref borderThickness, (uint)(GetStyle()), false, 0);
borderThickness.left *= -1;
borderThickness.top *= -1;
}
else if (GetStyle().HasFlag(WindowStyles.WS_BORDER))
{
border_thickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 };
borderThickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 };
}
if (_extendTitleBarHint >= 0)
{
border_thickness.top = (int)(_extendedMargins.Top * RenderScaling);
borderThickness.top = (int)(_extendedMargins.Top * RenderScaling);
}
// Determine if the hit test is for resizing. Default middle (1,1).
ushort uRow = 1;
ushort uCol = 1;
bool fOnResizeBorder = false;
bool onResizeBorder = false;
// Determine if the point is at the top or bottom of the window.
if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + border_thickness.top)
// Determine if the point is at the left or right of the window.
if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + borderThickness.left)
{
fOnResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top));
uRow = 0;
uCol = 0; // left side
}
else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - border_thickness.bottom)
else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - borderThickness.right)
{
uRow = 2;
uCol = 2; // right side
}
// Determine if the point is at the left or right of the window.
if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + border_thickness.left)
// Determine if the point is at the top or bottom of the window.
if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + borderThickness.top)
{
uCol = 0; // left side
onResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top));
// Two cases where we have a valid row 0 hit test:
// - window resize border (top resize border hit)
// - area below resize border that is actual titlebar (caption hit).
if (onResizeBorder || uCol == 1)
{
uRow = 0;
}
}
else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - border_thickness.right)
else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - borderThickness.bottom)
{
uCol = 2; // right side
uRow = 2;
}
// Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
HitTestValues[][] hitTests = new[]
ReadOnlySpan<HitTestValues> hitZones = stackalloc HitTestValues[]
{
new []{ HitTestValues.HTTOPLEFT, fOnResizeBorder ? HitTestValues.HTTOP : HitTestValues.HTCAPTION, HitTestValues.HTTOPRIGHT },
new []{ HitTestValues.HTLEFT, HitTestValues.HTNOWHERE, HitTestValues.HTRIGHT },
new []{ HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT },
HitTestValues.HTTOPLEFT, onResizeBorder ? HitTestValues.HTTOP : HitTestValues.HTCAPTION,
HitTestValues.HTTOPRIGHT, HitTestValues.HTLEFT, HitTestValues.HTNOWHERE, HitTestValues.HTRIGHT,
HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT
};
return hitTests[uRow][uCol];
var zoneIndex = uRow * 3 + uCol;
return hitZones[zoneIndex];
}
protected virtual IntPtr CustomCaptionProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool callDwp)

9
tests/Avalonia.Controls.UnitTests/CanvasTests.cs

@ -1,5 +1,6 @@
using System;
using Avalonia.Controls.Shapes;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
@ -9,6 +10,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Left_Property_Should_Work()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
Rectangle rect;
var target = new Canvas
{
@ -34,6 +37,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Top_Property_Should_Work()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
Rectangle rect;
var target = new Canvas
{
@ -59,6 +64,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Right_Property_Should_Work()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
Rectangle rect;
var target = new Canvas
{
@ -84,6 +91,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Bottom_Property_Should_Work()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
Rectangle rect;
var target = new Canvas
{

15
tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs

@ -1,5 +1,6 @@
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
@ -171,6 +172,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_RotateTransform_90_degrees()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
25,
@ -193,6 +196,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_RotateTransform_minus_90_degrees()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
25,
@ -215,6 +220,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_ScaleTransform_x2()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
50,
@ -236,6 +243,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_SkewTransform_45_degrees()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
100,
@ -258,6 +267,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_SkewTransform_minus_45_degrees()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
100,
@ -279,6 +290,8 @@ namespace Avalonia.Controls.UnitTests
private static void TransformMeasureSizeTest(Size size, Transform transform, Size expectedSize)
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
size.Width,
size.Height,
@ -292,6 +305,8 @@ namespace Avalonia.Controls.UnitTests
private static void TransformRootBoundsTest(Size size, Transform transform, Rect expectedBounds)
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(size.Width, size.Height, transform);
Rect outBounds = lt.TransformRoot.Bounds;

6
tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs

@ -1,4 +1,5 @@
using Avalonia.Controls.Shapes;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
@ -8,6 +9,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Lays_Out_1_Child_Next_the_other()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
@ -34,6 +36,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Lays_Out_1_Child_Below_the_other()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
@ -60,6 +63,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void RelativePanel_Can_Center()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
@ -86,6 +90,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void LeftOf_Measures_Correctly()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
@ -111,6 +116,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Above_Measures_Correctly()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };

57
tests/Avalonia.Controls.UnitTests/Shapes/EllipseTests.cs

@ -0,0 +1,57 @@
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests.Shapes
{
public class EllipseTests
{
[Fact]
public void Measure_Does_Not_Set_RenderedGeometry_Rect()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Ellipse();
target.Measure(new Size(100, 100));
var geometry = Assert.IsType<EllipseGeometry>(target.RenderedGeometry);
Assert.Equal(default, geometry.Rect);
}
[Fact]
public void Arrange_Sets_RenderedGeometry_Properties()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Ellipse();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
var geometry = Assert.IsType<EllipseGeometry>(target.RenderedGeometry);
Assert.Equal(new Rect(0, 0, 100, 100), geometry.Rect);
}
[Fact]
public void Rearranging_Updates_RenderedGeometry_Rect()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Ellipse();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
var geometry = Assert.IsType<EllipseGeometry>(target.RenderedGeometry);
Assert.Equal(new Rect(0, 0, 100, 100), geometry.Rect);
target.Measure(new Size(200, 200));
target.Arrange(new Rect(0, 0, 200, 200));
geometry = Assert.IsType<EllipseGeometry>(target.RenderedGeometry);
Assert.Equal(new Rect(0, 0, 200, 200), geometry.Rect);
}
}
}

144
tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs

@ -34,5 +34,149 @@ namespace Avalonia.Controls.UnitTests.Shapes
root.Child = null;
}
[Theory]
[InlineData(Stretch.None, 100, 200)]
[InlineData(Stretch.Fill, 500, 500)]
[InlineData(Stretch.Uniform, 250, 500)]
[InlineData(Stretch.UniformToFill, 500, 500)]
public void Calculates_Correct_DesiredSize_For_Finite_Bounds(Stretch stretch, double expectedWidth, double expectedHeight)
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Path()
{
Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
Stretch = stretch,
};
target.Measure(new Size(500, 500));
Assert.Equal(new Size(expectedWidth, expectedHeight), target.DesiredSize);
}
[Theory]
[InlineData(Stretch.None)]
[InlineData(Stretch.Fill)]
[InlineData(Stretch.Uniform)]
[InlineData(Stretch.UniformToFill)]
public void Calculates_Correct_DesiredSize_For_Infinite_Bounds(Stretch stretch)
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Path()
{
Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
Stretch = stretch,
};
target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Assert.Equal(new Size(100, 200), target.DesiredSize);
}
[Fact]
public void Measure_Does_Not_Update_RenderedGeometry_Transform()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Path
{
Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
Stretch = Stretch.Fill,
};
target.Measure(new Size(500, 500));
Assert.Null(target.RenderedGeometry.Transform);
}
[Theory]
[InlineData(Stretch.None, 1, 1)]
[InlineData(Stretch.Fill, 5, 2.5)]
[InlineData(Stretch.Uniform, 2.5, 2.5)]
[InlineData(Stretch.UniformToFill, 5, 5)]
public void Arrange_Updates_RenderedGeometry_Transform(Stretch stretch, double expectedScaleX, double expectedScaleY)
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Path
{
Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
Stretch = stretch,
};
target.Measure(new Size(500, 500));
target.Arrange(new Rect(0, 0, 500, 500));
if (expectedScaleX == 1 && expectedScaleY == 1)
{
Assert.Null(target.RenderedGeometry.Transform);
}
else
{
Assert.Equal(Matrix.CreateScale(expectedScaleX, expectedScaleY), target.RenderedGeometry.Transform.Value);
}
}
[Fact]
public void Arrange_Reserves_All_Of_Arrange_Rect()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
RectangleGeometry geometry;
var target = new Path
{
Data = geometry = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
Stretch = Stretch.Uniform,
};
target.Measure(new Size(400, 400));
target.Arrange(new Rect(0, 0, 400, 400));
Assert.Equal(new Rect(0, 0, 100, 200), geometry.Rect);
Assert.Equal(Matrix.CreateScale(2, 2), target.RenderedGeometry.Transform.Value);
Assert.Equal(new Rect(0, 0, 400, 400), target.Bounds);
}
[Fact]
public void Measure_Without_Arrange_Does_Not_Clear_RenderedGeometry_Transform()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Path
{
Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 100) },
Stretch = Stretch.Fill,
};
target.Measure(new Size(200, 200));
target.Arrange(new Rect(0, 0, 200, 200));
Assert.Equal(Matrix.CreateScale(2, 2), target.RenderedGeometry.Transform.Value);
target.Measure(new Size(300, 300));
Assert.Equal(Matrix.CreateScale(2, 2), target.RenderedGeometry.Transform.Value);
}
[Fact]
public void Arrange_Without_Measure_Updates_RenderedGeometry_Transform()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Path
{
Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 100) },
Stretch = Stretch.Fill,
};
target.Measure(new Size(200, 200));
target.Arrange(new Rect(0, 0, 200, 200));
Assert.Equal(Matrix.CreateScale(2, 2), target.RenderedGeometry.Transform.Value);
target.Arrange(new Rect(0, 0, 300, 300));
Assert.Equal(Matrix.CreateScale(3, 3), target.RenderedGeometry.Transform.Value);
}
}
}

56
tests/Avalonia.Controls.UnitTests/Shapes/RectangleTests.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.UnitTests;
using Moq;
@ -11,6 +8,53 @@ namespace Avalonia.Controls.UnitTests.Shapes
{
public class RectangleTests
{
[Fact]
public void Measure_Does_Not_Set_RenderedGeometry_Rect()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Rectangle();
target.Measure(new Size(100, 100));
var geometry = Assert.IsType<RectangleGeometry>(target.RenderedGeometry);
Assert.Equal(Rect.Empty, geometry.Rect);
}
[Fact]
public void Arrange_Sets_RenderedGeometry_Rect()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Rectangle();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
var geometry = Assert.IsType<RectangleGeometry>(target.RenderedGeometry);
Assert.Equal(new Rect(0, 0, 100, 100), geometry.Rect);
}
[Fact]
public void Rearranging_Updates_RenderedGeometry_Rect()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Rectangle();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
var geometry = Assert.IsType<RectangleGeometry>(target.RenderedGeometry);
Assert.Equal(new Rect(0, 0, 100, 100), geometry.Rect);
target.Measure(new Size(200, 200));
target.Arrange(new Rect(0, 0, 200, 200));
geometry = Assert.IsType<RectangleGeometry>(target.RenderedGeometry);
Assert.Equal(new Rect(0, 0, 200, 200), geometry.Rect);
}
[Fact]
public void Changing_Fill_Brush_Color_Should_Invalidate_Visual()
{
@ -21,7 +65,7 @@ namespace Avalonia.Controls.UnitTests.Shapes
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
renderer.ResetCalls();
renderer.Invocations.Clear();
((SolidColorBrush)target.Fill).Color = Colors.Green;
@ -38,7 +82,7 @@ namespace Avalonia.Controls.UnitTests.Shapes
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
renderer.ResetCalls();
renderer.Invocations.Clear();
((SolidColorBrush)target.Stroke).Color = Colors.Green;

13
tests/Avalonia.Controls.UnitTests/ViewboxTests.cs

@ -1,5 +1,6 @@
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
@ -9,6 +10,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_Uniform_Child()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Viewbox() { Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, 200));
@ -25,6 +28,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_None_Child()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Viewbox() { Stretch = Stretch.None, Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, 200));
@ -41,6 +46,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_Fill_Child()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Viewbox() { Stretch = Stretch.Fill, Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, 200));
@ -57,6 +64,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_UniformToFill_Child()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Viewbox() { Stretch = Stretch.UniformToFill, Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, 200));
@ -73,6 +82,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_Uniform_Child_With_Unrestricted_Width()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Viewbox() { Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(double.PositiveInfinity, 200));
@ -89,6 +100,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_Uniform_Child_With_Unrestricted_Height()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new Viewbox() { Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, double.PositiveInfinity));

113
tests/Avalonia.Layout.UnitTests/ShapeLayoutTests.cs

@ -1,113 +0,0 @@
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Layout.UnitTests
{
public class ShapeLayoutTests : TestWithServicesBase
{
public ShapeLayoutTests()
{
AvaloniaLocator.CurrentMutable
.Bind<IPlatformRenderInterface>().ToSingleton<MockPlatformRenderInterface>();
}
[Fact]
public void Shape_Transformation_Calculation_Should_Be_Deferred_To_Arrange_When_Strech_Is_Fill_And_Aviable_Size_Is_Infinite()
{
var shape = new Polygon()
{
Points = new List<Point>
{
new Point(0, 0),
new Point(10, 5),
new Point(0, 10)
},
Stretch = Stretch.Fill
};
var availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
shape.Measure(availableSize);
Geometry postMeasureGeometry = shape.RenderedGeometry;
Transform postMeasureTransform = postMeasureGeometry.Transform;
var finalSize = new Size(100, 50);
var finalRect = new Rect(finalSize);
shape.Arrange(finalRect);
Geometry postArrangeGeometry = shape.RenderedGeometry;
Transform postArrangeTransform = postArrangeGeometry.Transform;
Assert.NotEqual(postMeasureGeometry, postArrangeGeometry);
Assert.NotEqual(postMeasureTransform, postArrangeTransform);
Assert.Equal(finalSize, shape.Bounds.Size);
}
[Fact]
public void Shape_Transformation_Calculation_Should_Not_Be_Deferred_To_Arrange_When_Strech_Is_Fill_And_Aviable_Size_Is_Finite()
{
var shape = new Polygon()
{
Points = new List<Point>
{
new Point(0, 0),
new Point(10, 5),
new Point(0, 10)
},
Stretch = Stretch.Fill
};
var availableSize = new Size(100, 50);
shape.Measure(availableSize);
Geometry postMeasureGeometry = shape.RenderedGeometry;
Transform postMeasureTransform = postMeasureGeometry.Transform;
var finalRect = new Rect(availableSize);
shape.Arrange(finalRect);
Geometry postArrangeGeometry = shape.RenderedGeometry;
Transform postArrangeTransform = postArrangeGeometry.Transform;
Assert.Equal(postMeasureGeometry, postArrangeGeometry);
Assert.Equal(postMeasureTransform, postArrangeTransform);
Assert.Equal(availableSize, shape.Bounds.Size);
}
[Fact]
public void Shape_Transformation_Calculation_Should_Not_Be_Deferred_To_Arrange_When_Strech_Is_None()
{
var shape = new Polygon()
{
Points = new List<Point>
{
new Point(0, 0),
new Point(10, 5),
new Point(0, 10)
},
Stretch = Stretch.None
};
var availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
shape.Measure(availableSize);
Geometry postMeasureGeometry = shape.RenderedGeometry;
Transform postMeasureTransform = postMeasureGeometry.Transform;
var finalSize = new Size(100, 50);
var finalRect = new Rect(finalSize);
shape.Arrange(finalRect);
Geometry postArrangeGeometry = shape.RenderedGeometry;
Transform postArrangeTransform = postArrangeGeometry.Transform;
Assert.Equal(postMeasureGeometry, postArrangeGeometry);
Assert.Equal(postMeasureTransform, postArrangeTransform);
Assert.Equal(finalSize, shape.Bounds.Size);
}
}
}

2
tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs

@ -34,7 +34,7 @@ namespace Avalonia.UnitTests
public IGeometryImpl CreateRectangleGeometry(Rect rect)
{
return Mock.Of<IGeometryImpl>();
return Mock.Of<IGeometryImpl>(x => x.Bounds == rect);
}
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces)

Loading…
Cancel
Save