From a38487ca0f40b4d04fc601925bd536f052a1906c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Fri, 12 Apr 2024 00:31:52 +0200 Subject: [PATCH] Add FuncValueConverter with parameter support (#15323) * Add FuncValueConverter with parameter support * Fix summary comment * Fix summary comment * Add Equal and NotEqual converters to a ObjectConverters class * Fix condition for Equal * Added ObjectConverters unit tests --- .../Data/Converters/FuncValueConverter.cs | 42 ++++++++++++++++- .../Data/Converters/ObjectConverters.cs | 12 +++++ .../Data/ObjectConvertersTests_Eqaul.cs | 45 +++++++++++++++++++ .../Data/ObjectConvertersTests_IsNotNull.cs | 26 +++++++++++ .../Data/ObjectConvertersTests_IsNull.cs | 26 +++++++++++ .../Data/ObjectConvertersTests_NotEqaul.cs | 45 +++++++++++++++++++ 6 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_Eqaul.cs create mode 100644 tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_IsNotNull.cs create mode 100644 tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_IsNull.cs create mode 100644 tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_NotEqaul.cs diff --git a/src/Avalonia.Base/Data/Converters/FuncValueConverter.cs b/src/Avalonia.Base/Data/Converters/FuncValueConverter.cs index 8a1f032593..0d446d0729 100644 --- a/src/Avalonia.Base/Data/Converters/FuncValueConverter.cs +++ b/src/Avalonia.Base/Data/Converters/FuncValueConverter.cs @@ -5,7 +5,7 @@ using Avalonia.Utilities; namespace Avalonia.Data.Converters { /// - /// A general purpose that uses a + /// A general purpose that uses a /// to provide the converter logic. /// /// The input type. @@ -42,4 +42,44 @@ namespace Avalonia.Data.Converters throw new NotImplementedException(); } } + + /// + /// A general purpose that uses a + /// to provide the converter logic. + /// + /// The input type. + /// The param type. + /// The output type. + public class FuncValueConverter : IValueConverter + { + private readonly Func _convert; + + /// + /// Initializes a new instance of the class. + /// + /// The convert function. + public FuncValueConverter(Func convert) + { + _convert = convert; + } + + /// + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (TypeUtilities.CanCast(value) && TypeUtilities.CanCast(parameter)) + { + return _convert((TIn?)value, (TParam?)parameter); + } + else + { + return AvaloniaProperty.UnsetValue; + } + } + + /// + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } } diff --git a/src/Avalonia.Base/Data/Converters/ObjectConverters.cs b/src/Avalonia.Base/Data/Converters/ObjectConverters.cs index 6796a1793e..8496ee1ae6 100644 --- a/src/Avalonia.Base/Data/Converters/ObjectConverters.cs +++ b/src/Avalonia.Base/Data/Converters/ObjectConverters.cs @@ -16,5 +16,17 @@ namespace Avalonia.Data.Converters /// public static readonly IValueConverter IsNotNull = new FuncValueConverter(x => x is not null); + + /// + /// A value converter that returns true if the input object is equal to a parameter object. + /// + public static readonly IValueConverter Equal = + new FuncValueConverter((a, b) => a?.Equals(b) ?? b is null); + + /// + /// A value converter that returns true if the input object is not equal to a parameter object. + /// + public static readonly IValueConverter NotEqual = + new FuncValueConverter((a, b) => !a?.Equals(b) ?? b is not null); } } diff --git a/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_Eqaul.cs b/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_Eqaul.cs new file mode 100644 index 0000000000..a3782bfba7 --- /dev/null +++ b/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_Eqaul.cs @@ -0,0 +1,45 @@ +using System.Globalization; +using Avalonia.Data.Converters; +using Xunit; + +namespace Avalonia.Base.UnitTests.Data; + +public class ObjectConvertersTests_Equal +{ + [Fact] + public void Returns_True_If_Value_And_Parameter_Are_Null() + { + var result = ObjectConverters.Equal.Convert(null, typeof(object), null, CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is true); + } + + [Fact] + public void Returns_False_If_Value_Is_Null_And_Parameter_Is_Not_Null() + { + var result = ObjectConverters.Equal.Convert(null, typeof(object), new object(), CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is false); + } + + [Fact] + public void Returns_False_If_Value_And_Parameter_Are_Different_Objects() + { + var result = ObjectConverters.Equal.Convert(new object(), typeof(object), new object(), CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is false); + } + + [Fact] + public void Returns_True_If_Value_And_Parameter_Are_Same_Object() + { + var target = new object(); + var result = ObjectConverters.Equal.Convert(target, typeof(object), target, CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is true); + } +} diff --git a/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_IsNotNull.cs b/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_IsNotNull.cs new file mode 100644 index 0000000000..b4b8f1466c --- /dev/null +++ b/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_IsNotNull.cs @@ -0,0 +1,26 @@ +using System.Globalization; +using Avalonia.Data.Converters; +using Xunit; + +namespace Avalonia.Base.UnitTests.Data; + +public class ObjectConvertersTests_IsNull +{ + [Fact] + public void Returns_True_If_Value_Is_Null() + { + var result = ObjectConverters.IsNull.Convert(null, typeof(object), null, CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is true); + } + + [Fact] + public void Returns_False_If_Value_Is_Not_Null() + { + var result = ObjectConverters.IsNull.Convert(new object(), typeof(object), null, CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is false); + } +} diff --git a/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_IsNull.cs b/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_IsNull.cs new file mode 100644 index 0000000000..b6f9b9ac27 --- /dev/null +++ b/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_IsNull.cs @@ -0,0 +1,26 @@ +using System.Globalization; +using Avalonia.Data.Converters; +using Xunit; + +namespace Avalonia.Base.UnitTests.Data; + +public class ObjectConvertersTests_IsNotNull +{ + [Fact] + public void Returns_True_If_Value_Is_Not_Null() + { + var result = ObjectConverters.IsNotNull.Convert(new object(), typeof(object), null, CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is true); + } + + [Fact] + public void Returns_False_If_Value_Is_Null() + { + var result = ObjectConverters.IsNotNull.Convert(null, typeof(object), null, CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is false); + } +} diff --git a/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_NotEqaul.cs b/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_NotEqaul.cs new file mode 100644 index 0000000000..c27f9db93d --- /dev/null +++ b/tests/Avalonia.Base.UnitTests/Data/ObjectConvertersTests_NotEqaul.cs @@ -0,0 +1,45 @@ +using System.Globalization; +using Avalonia.Data.Converters; +using Xunit; + +namespace Avalonia.Base.UnitTests.Data; + +public class ObjectConvertersTests_NotEqual +{ + [Fact] + public void Returns_False_If_Value_And_Parameter_Are_Null() + { + var result = ObjectConverters.NotEqual.Convert(null, typeof(object), null, CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is false); + } + + [Fact] + public void Returns_True_If_Value_Is_Null_And_Parameter_Is_Not_Null() + { + var result = ObjectConverters.NotEqual.Convert(null, typeof(object), new object(), CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is true); + } + + [Fact] + public void Returns_True_If_Value_And_Parameter_Are_Different_Objects() + { + var result = ObjectConverters.NotEqual.Convert(new object(), typeof(object), new object(), CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is true); + } + + [Fact] + public void Returns_False_If_Value_And_Parameter_Are_Same_Object() + { + var target = new object(); + var result = ObjectConverters.NotEqual.Convert(target, typeof(object), target, CultureInfo.InvariantCulture); + + Assert.IsType(result); + Assert.True(result is false); + } +}