From 05d8b84ce3e4f30c6c5c643ce6cbf841c24121d5 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Tue, 3 Jan 2023 23:21:53 +0800 Subject: [PATCH 1/3] feat: Add GeometryConverter --- src/Avalonia.Base/Media/Geometry.cs | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Base/Media/Geometry.cs b/src/Avalonia.Base/Media/Geometry.cs index 2019f54c70..b1fea53289 100644 --- a/src/Avalonia.Base/Media/Geometry.cs +++ b/src/Avalonia.Base/Media/Geometry.cs @@ -1,11 +1,14 @@ using System; using Avalonia.Platform; +using System.ComponentModel; +using System.Globalization; namespace Avalonia.Media { /// /// Defines a geometric shape. - /// + /// + [TypeConverter(typeof(GeometryConverter))] public abstract class Geometry : AvaloniaObject { /// @@ -199,4 +202,32 @@ namespace Avalonia.Media return new CombinedGeometry(combineMode, geometry1, geometry2, transform); } } + + public class GeometryConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + return base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + if (value is null) + { + throw GetConvertFromException(value); + } + string source = value as string; + + if (source != null) + { + return Geometry.Parse(source); + } + + return base.ConvertFrom(context, culture, value); + } + } } From 6e1311c75d16547920b05812fcffa225da2d2893 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Wed, 4 Jan 2023 00:09:51 +0800 Subject: [PATCH 2/3] fix: fix nullable issue. --- src/Avalonia.Base/Media/Geometry.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/Media/Geometry.cs b/src/Avalonia.Base/Media/Geometry.cs index b1fea53289..e2b345df1a 100644 --- a/src/Avalonia.Base/Media/Geometry.cs +++ b/src/Avalonia.Base/Media/Geometry.cs @@ -214,13 +214,13 @@ namespace Avalonia.Media return base.CanConvertFrom(context, sourceType); } - public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) { if (value is null) { throw GetConvertFromException(value); } - string source = value as string; + string? source = value as string; if (source != null) { From 182e469066a3da780bd8c50777127fb0fad8ebf8 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Mon, 9 Jan 2023 23:51:18 +0800 Subject: [PATCH 3/3] feat: add UT for GeometryTypeConverter. --- src/Avalonia.Base/Media/Geometry.cs | 4 +- .../Converters/GeometryTypeConverterTests.cs | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/Avalonia.Markup.Xaml.UnitTests/Converters/GeometryTypeConverterTests.cs diff --git a/src/Avalonia.Base/Media/Geometry.cs b/src/Avalonia.Base/Media/Geometry.cs index e2b345df1a..e62f819b74 100644 --- a/src/Avalonia.Base/Media/Geometry.cs +++ b/src/Avalonia.Base/Media/Geometry.cs @@ -8,7 +8,7 @@ namespace Avalonia.Media /// /// Defines a geometric shape. /// - [TypeConverter(typeof(GeometryConverter))] + [TypeConverter(typeof(GeometryTypeConverter))] public abstract class Geometry : AvaloniaObject { /// @@ -203,7 +203,7 @@ namespace Avalonia.Media } } - public class GeometryConverter : TypeConverter + public class GeometryTypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Converters/GeometryTypeConverterTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/GeometryTypeConverterTests.cs new file mode 100644 index 0000000000..329a14afa6 --- /dev/null +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/GeometryTypeConverterTests.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Avalonia.Controls; +using Avalonia.Controls.Shapes; +using Avalonia.Media; +using Avalonia.UnitTests; +using Xunit; + +namespace Avalonia.Markup.Xaml.UnitTests.Converters +{ + public class GeometryTypeConverterTests: XamlTestBase + { + public class StringDataViewModel + { + public string PathData { get; set; } + } + + public class IntDataViewModel + { + public int PathData { get; set; } + } + + + [Theory] + [MemberData(nameof(Get_GeometryTypeConverter_Data))] + public void GeometryTypeConverter_Value_Work(object vm, bool nullData) + { + using(UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + +"; + var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); + var path = window.FindControl("path"); + window.DataContext = vm; + Assert.Equal(nullData, path.Data is null); + } + } + + public static IEnumerable Get_GeometryTypeConverter_Data() + { + yield return new object[] { new StringDataViewModel { }, true }; + yield return new object[] { new StringDataViewModel { PathData = "M406.39,333.45l205.93,0" }, false }; + yield return new object[] { new IntDataViewModel { }, true }; + yield return new object[] { new IntDataViewModel { PathData = 100 }, true }; + } + } +}