Browse Source

Merge branch 'master' into fixes/Warnings/ControlCatalog/CS8767

pull/8914/head
Max Katz 4 years ago
committed by GitHub
parent
commit
e3dc549e50
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      src/Avalonia.Base/Layout/LayoutHelper.cs
  2. 35
      src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs
  3. 3
      src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
  4. 2
      src/Avalonia.Controls/Utils/BorderRenderHelper.cs
  5. 57
      tests/Avalonia.Controls.UnitTests/BorderTests.cs

11
src/Avalonia.Base/Layout/LayoutHelper.cs

@ -251,6 +251,17 @@ namespace Avalonia.Layout
{
double newValue;
// Round the value to avoid FP errors. This is needed because if `value` has a floating
// point precision error (e.g. 79.333333333333343) then when it's multiplied by
// `dpiScale` and rounded up, it will be rounded up to a value one greater than it
// should be.
#if NET6_0_OR_GREATER
value = Math.Round(value, 8, MidpointRounding.ToZero);
#else
// MidpointRounding.ToZero isn't available in netstandard2.0.
value = Math.Truncate(value * 1e8) / 1e8;
#endif
// If DPI == 1, don't use DPI-aware rounding.
if (!MathUtilities.IsOne(dpiScale))
{

35
src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs

@ -0,0 +1,35 @@
using System;
using System.Globalization;
using Avalonia.Data;
using Avalonia.Data.Converters;
namespace Avalonia.Controls.Converters
{
/// <summary>
/// Converter that will do nothing (not update bound values) when a null value is encountered.
/// This converter enables binding nullable with non-nullable properties in some scenarios.
/// </summary>
public class DoNothingForNullConverter : IValueConverter
{
/// <inheritdoc/>
public object? Convert(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
return value ?? BindingOperations.DoNothing;
}
/// <inheritdoc/>
public object? ConvertBack(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
return value ?? BindingOperations.DoNothing;
}
}
}

3
src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml

@ -11,6 +11,7 @@
<pc:ThirdComponentConverter x:Key="ThirdComponentConverter" />
<converters:ColorToDisplayNameConverter x:Key="ColorToDisplayNameConverter" />
<converters:ColorToHexConverter x:Key="ColorToHexConverter" />
<converters:DoNothingForNullConverter x:Key="DoNothingForNullConverter" />
<globalization:NumberFormatInfo x:Key="ColorViewComponentNumberFormat" NumberDecimalDigits="0" />
<x:Double x:Key="ColorViewTabStripHeight">48</x:Double>
<x:Double x:Key="ColorViewComponentLabelWidth">30</x:Double>
@ -205,7 +206,7 @@
</Border>
</TabItem.Header>
<ListBox Items="{TemplateBinding PaletteColors}"
SelectedItem="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
SelectedItem="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource DoNothingForNullConverter}, Mode=TwoWay}"
UseLayoutRounding="False"
Margin="12">
<ListBox.Styles>

2
src/Avalonia.Controls/Utils/BorderRenderHelper.cs

@ -61,7 +61,7 @@ namespace Avalonia.Controls.Utils
_backgroundGeometryCache = null;
}
if (boundRect.Width != 0 && innerRect.Height != 0)
if (boundRect.Width != 0 && boundRect.Height != 0)
{
var borderGeometryKeypoints =
new BorderGeometryKeypoints(boundRect, borderThickness, cornerRadius, false);

57
tests/Avalonia.Controls.UnitTests/BorderTests.cs

@ -78,7 +78,7 @@ namespace Avalonia.Controls.UnitTests
}
};
var root = CreatedRoot(1.5, target);
var root = CreateRoot(1.5, target);
root.LayoutManager.ExecuteInitialLayoutPass();
@ -101,7 +101,7 @@ namespace Avalonia.Controls.UnitTests
}
};
var root = CreatedRoot(1.5, target);
var root = CreateRoot(1.5, target);
root.LayoutManager.ExecuteInitialLayoutPass();
@ -111,7 +111,58 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Size(104, 104), target.DesiredSize);
}
private static TestRoot CreatedRoot(
[Fact]
public void Measure_Arranges_Child_To_Rounded_BorderThickness()
{
Canvas child;
var target = new Border
{
BorderThickness = new Thickness(1),
Width = 82,
Height = 82,
Child = child = new Canvas(),
};
var root = CreateRoot(1.5, target);
root.LayoutManager.ExecuteInitialLayoutPass();
// - 1 pixel border thickness is rounded up to 1.3333; for both sides it is 2.6666
// - Size of 82 needs no rounding
// - Minus border thickness, space for child is 82 - 2.6666 = 79.3333
Assert.Equal(1.3333, child.Bounds.Left, 3);
Assert.Equal(1.3333, child.Bounds.Top, 3);
Assert.Equal(79.3333, child.Bounds.Width, 3);
Assert.Equal(79.3333, child.Bounds.Height, 3);
}
[Fact]
public void Measure_Arranges_Child_With_Rounded_Margin()
{
Border child;
var target = new Border
{
Width = 220,
Height = 220,
Child = child = new Border
{
Margin = new Thickness(0, 25, 25, 25),
},
};
var root = CreateRoot(1.5, target);
root.LayoutManager.ExecuteInitialLayoutPass();
// - 25 margin gets rounded up to 25.3333
// - Size of 220 needs no rounding
Assert.Equal(0, child.Bounds.Left, 3);
Assert.Equal(25.3333, child.Bounds.Top, 3);
Assert.Equal(194.6666, child.Bounds.Width, 3);
Assert.Equal(169.3333, child.Bounds.Height, 3);
}
private static TestRoot CreateRoot(
double scaling,
Control child,
Size? constraint = null)

Loading…
Cancel
Save