From b13b870741aefe63f3f7c7c83ae50cd256209be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 4 Nov 2015 00:48:03 +0100 Subject: [PATCH] Added RelativeRectTypeConverter --- .../Views/MainWindow.paml | 22 ++++ .../Context/PerspexWiringContext.cs | 1 + .../Converters/RelativeRectTypeConverter.cs | 32 +++++ .../Perspex.Markup.Xaml.csproj | 1 + src/Perspex.SceneGraph/RelativeRect.cs | 110 +++++++++++++++++- .../Perspex.SceneGraph.UnitTests.csproj | 1 + .../RelativeRectTests.cs | 27 +++++ 7 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 src/Markup/Perspex.Markup.Xaml/Converters/RelativeRectTypeConverter.cs create mode 100644 tests/Perspex.SceneGraph.UnitTests/RelativeRectTests.cs diff --git a/samples/XamlTestApplicationPcl/Views/MainWindow.paml b/samples/XamlTestApplicationPcl/Views/MainWindow.paml index c3e2b458ec..64723719fc 100644 --- a/samples/XamlTestApplicationPcl/Views/MainWindow.paml +++ b/samples/XamlTestApplicationPcl/Views/MainWindow.paml @@ -245,6 +245,28 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs index 9597cf1128..30f2b5ca7c 100644 --- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs +++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs @@ -106,6 +106,7 @@ namespace Perspex.Markup.Xaml.Context new TypeConverterRegistration(typeof(Point), new PointTypeConverter()), new TypeConverterRegistration(typeof(PerspexProperty), new PerspexPropertyTypeConverter()), new TypeConverterRegistration(typeof(RelativePoint), new RelativePointTypeConverter()), + new TypeConverterRegistration(typeof(RelativeRect), new RelativeRectTypeConverter()), new TypeConverterRegistration(typeof(RowDefinitions), new RowDefinitionsTypeConverter()), new TypeConverterRegistration(typeof(Selector), new SelectorTypeConverter()), new TypeConverterRegistration(typeof(Thickness), new ThicknessTypeConverter()), diff --git a/src/Markup/Perspex.Markup.Xaml/Converters/RelativeRectTypeConverter.cs b/src/Markup/Perspex.Markup.Xaml/Converters/RelativeRectTypeConverter.cs new file mode 100644 index 0000000000..e3f8af7a1d --- /dev/null +++ b/src/Markup/Perspex.Markup.Xaml/Converters/RelativeRectTypeConverter.cs @@ -0,0 +1,32 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using System.Globalization; +using OmniXaml.TypeConversion; + +namespace Perspex.Markup.Xaml.Converters +{ + public class RelativeRectTypeConverter : ITypeConverter + { + public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType) + { + return sourceType == typeof(string); + } + + public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType) + { + return false; + } + + public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value) + { + return RelativeRect.Parse((string)value, culture); + } + + public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj b/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj index aea7b0b04e..cebb76826f 100644 --- a/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj +++ b/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj @@ -39,6 +39,7 @@ Properties\SharedAssemblyInfo.cs + diff --git a/src/Perspex.SceneGraph/RelativeRect.cs b/src/Perspex.SceneGraph/RelativeRect.cs index 5dedbdf00d..5ededd2e52 100644 --- a/src/Perspex.SceneGraph/RelativeRect.cs +++ b/src/Perspex.SceneGraph/RelativeRect.cs @@ -1,12 +1,16 @@ // Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using System; +using System.Globalization; +using System.Linq; + namespace Perspex { /// /// Defines a rectangle that may be defined relative to a containing element. /// - public struct RelativeRect + public struct RelativeRect : IEquatable { /// /// A rectangle that represents 100% of an area. @@ -83,6 +87,63 @@ namespace Perspex /// public Rect Rect { get; } + /// + /// Checks for equality between two s. + /// + /// The first rectangle. + /// The second rectangle. + /// True if the rectangles are equal; otherwise false. + public static bool operator ==(RelativeRect left, RelativeRect right) + { + return left.Equals(right); + } + + /// + /// Checks for unequality between two s. + /// + /// The first rectangle. + /// The second rectangle. + /// True if the rectangles are unequal; otherwise false. + public static bool operator !=(RelativeRect left, RelativeRect right) + { + return !left.Equals(right); + } + + /// + /// Checks if the equals another object. + /// + /// The other object. + /// True if the objects are equal, otherwise false. + public override bool Equals(object obj) + { + return (obj is RelativeRect) ? Equals((RelativeRect)obj) : false; + } + + /// + /// Checks if the equals another rectangle. + /// + /// The other rectangle. + /// True if the objects are equal, otherwise false. + public bool Equals(RelativeRect p) + { + return Unit == p.Unit && Rect == p.Rect; + } + + /// + /// Gets a hashcode for a . + /// + /// A hash code. + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = (hash * 23) + Unit.GetHashCode(); + hash = (hash * 23) + Rect.GetHashCode(); + return hash; + } + } + /// /// Converts a into pixels. /// @@ -98,5 +159,52 @@ namespace Perspex Rect.Width * size.Width, Rect.Height * size.Height); } + + /// + /// Parses a string. + /// + /// The string. + /// The current culture. + /// The parsed . + public static RelativeRect Parse(string s, CultureInfo culture) + { + var parts = s.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) + .Select(x => x.Trim()) + .ToList(); + + if (parts.Count == 4) + { + var unit = RelativeUnit.Absolute; + var scale = 1.0; + + if (parts[0].EndsWith("%")) + { + if (!parts[1].EndsWith("%") + || !parts[2].EndsWith("%") + || !parts[3].EndsWith("%")) + { + throw new FormatException("If one coordinate is relative, all other must be too."); + } + + parts[0] = parts[0].TrimEnd('%'); + parts[1] = parts[1].TrimEnd('%'); + parts[2] = parts[2].TrimEnd('%'); + parts[3] = parts[3].TrimEnd('%'); + unit = RelativeUnit.Relative; + scale = 0.01; + } + + return new RelativeRect( + double.Parse(parts[0], culture) * scale, + double.Parse(parts[1], culture) * scale, + double.Parse(parts[2], culture) * scale, + double.Parse(parts[3], culture) * scale, + unit); + } + else + { + throw new FormatException("Invalid Rect."); + } + } } } diff --git a/tests/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj b/tests/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj index e48d6ac73b..7c4daf0867 100644 --- a/tests/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj +++ b/tests/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj @@ -72,6 +72,7 @@ + diff --git a/tests/Perspex.SceneGraph.UnitTests/RelativeRectTests.cs b/tests/Perspex.SceneGraph.UnitTests/RelativeRectTests.cs new file mode 100644 index 0000000000..9ee4e37e3f --- /dev/null +++ b/tests/Perspex.SceneGraph.UnitTests/RelativeRectTests.cs @@ -0,0 +1,27 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System.Globalization; +using Xunit; + +namespace Perspex.SceneGraph.UnitTests +{ + public class RelativeRectTests + { + [Fact] + public void Parse_Should_Accept_Absolute_Value() + { + var result = RelativeRect.Parse("4,5,50,60", CultureInfo.InvariantCulture); + + Assert.Equal(new RelativeRect(4, 5, 50, 60, RelativeUnit.Absolute), result); + } + + [Fact] + public void Parse_Should_Accept_Relative_Value() + { + var result = RelativeRect.Parse("10%, 20%, 40%, 70%", CultureInfo.InvariantCulture); + + Assert.Equal(new RelativeRect(0.1, 0.2, 0.4, 0.7, RelativeUnit.Relative), result); + } + } +}