From 3b1c1f4234d9efccca099e57c5c9d83df790e32d Mon Sep 17 00:00:00 2001 From: Tom Edwards <109803929+TomEdwardsEnscape@users.noreply.github.com> Date: Mon, 19 Aug 2024 23:54:29 +0200 Subject: [PATCH] Validate all width/height properties of Layoutable when they are set (#15753) --- src/Avalonia.Base/Layout/Layoutable.cs | 16 ++++++++----- .../Layout/LayoutableTests.cs | 24 +++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Base/Layout/Layoutable.cs b/src/Avalonia.Base/Layout/Layoutable.cs index b237c10e63..73c9e1ba0f 100644 --- a/src/Avalonia.Base/Layout/Layoutable.cs +++ b/src/Avalonia.Base/Layout/Layoutable.cs @@ -74,37 +74,37 @@ namespace Avalonia.Layout /// Defines the property. /// public static readonly StyledProperty WidthProperty = - AvaloniaProperty.Register(nameof(Width), double.NaN); + AvaloniaProperty.Register(nameof(Width), double.NaN, validate: ValidateDimension); /// /// Defines the property. /// public static readonly StyledProperty HeightProperty = - AvaloniaProperty.Register(nameof(Height), double.NaN); + AvaloniaProperty.Register(nameof(Height), double.NaN, validate: ValidateDimension); /// /// Defines the property. /// public static readonly StyledProperty MinWidthProperty = - AvaloniaProperty.Register(nameof(MinWidth)); + AvaloniaProperty.Register(nameof(MinWidth), validate: ValidateMinimumDimension); /// /// Defines the property. /// public static readonly StyledProperty MaxWidthProperty = - AvaloniaProperty.Register(nameof(MaxWidth), double.PositiveInfinity); + AvaloniaProperty.Register(nameof(MaxWidth), double.PositiveInfinity, validate: ValidateMaximumDimension); /// /// Defines the property. /// public static readonly StyledProperty MinHeightProperty = - AvaloniaProperty.Register(nameof(MinHeight)); + AvaloniaProperty.Register(nameof(MinHeight), validate: ValidateMinimumDimension); /// /// Defines the property. /// public static readonly StyledProperty MaxHeightProperty = - AvaloniaProperty.Register(nameof(MaxHeight), double.PositiveInfinity); + AvaloniaProperty.Register(nameof(MaxHeight), double.PositiveInfinity, validate: ValidateMaximumDimension); /// /// Defines the property. @@ -153,6 +153,10 @@ namespace Avalonia.Layout VerticalAlignmentProperty); } + private static bool ValidateDimension(double value) => double.IsNaN(value) || ValidateMinimumDimension(value); + private static bool ValidateMinimumDimension(double value) => !double.IsPositiveInfinity(value) && ValidateMaximumDimension(value); + private static bool ValidateMaximumDimension(double value) => value >= 0; + /// /// Occurs when the element's effective viewport changes. /// diff --git a/tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs b/tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs index c4b0795022..ab1c036b72 100644 --- a/tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs +++ b/tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Avalonia.Controls; using Avalonia.Layout; using Avalonia.UnitTests; @@ -387,6 +388,29 @@ namespace Avalonia.Base.UnitTests.Layout Assert.Equal(default, child.DesiredSize); } + [Fact] + public void Size_Properties_Reject_Invalid_Values() + { + var target = new Layoutable(); + + Assert.Multiple(() => + { + SetShouldThrow([Layoutable.WidthProperty, Layoutable.HeightProperty], double.PositiveInfinity); + SetShouldThrow([Layoutable.WidthProperty, Layoutable.HeightProperty], -10); + + SetShouldThrow([Layoutable.MinWidthProperty, Layoutable.MinHeightProperty], double.PositiveInfinity); + SetShouldThrow([Layoutable.MinWidthProperty, Layoutable.MinHeightProperty], -10); + + SetShouldThrow([Layoutable.MaxWidthProperty, Layoutable.MaxHeightProperty], -10); + + void SetShouldThrow(IEnumerable> properies, double value) + { + foreach (var prop in properies) + Assert.Throws(() => target.SetValue(prop, value)); + } + }); + } + private class TestLayoutable : Layoutable { public Size ArrangeSize { get; private set; }