Browse Source

Added RelativeRectTypeConverter

Wiesław Šoltés 10 years ago
parent
commit
b13b870741

+ 22 - 0
samples/XamlTestApplicationPcl/Views/MainWindow.paml

@@ -245,6 +245,28 @@
                   <Button Grid.Row="1" Grid.Column="1" Content="Animate" HorizontalAlignment="Center"></Button>
               </Grid>
           </TabItem>
+          <TabItem Header="Brushes">
+              <Grid ColumnDefinitions="Auto" RowDefinitions="Auto">
+                  <Border Grid.Row="0" Grid.Column="0" Width="200" Height="200" Margin="10">
+                      <Border.Background>
+                          <VisualBrush TileMode="Tile" Stretch="None" AlignmentX="Left" AlignmentY="Top" SourceRect="0%,0%,100%,100%" DestinationRect="0,0,20,20">
+                              <VisualBrush.Visual>
+                                  <StackPanel Orientation="Horizontal">
+                                      <StackPanel Orientation="Vertical">
+                                          <Rectangle Width="10" Height="10" Fill="DarkGray"/>
+                                          <Rectangle Width="10" Height="10" Fill="LightGray"/>
+                                      </StackPanel>
+                                      <StackPanel Orientation="Vertical">
+                                          <Rectangle Width="10" Height="10" Fill="LightGray"/>
+                                          <Rectangle Width="10" Height="10" Fill="DarkGray"/>
+                                      </StackPanel>
+                                  </StackPanel>
+                              </VisualBrush.Visual>
+                          </VisualBrush>
+                      </Border.Background>
+                  </Border>
+              </Grid>
+          </TabItem>
       </TabControl>
     </Grid>
 </Window>

+ 1 - 0
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()),

+ 32 - 0
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();
+        }
+    }
+}

+ 1 - 0
src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj

@@ -39,6 +39,7 @@
       <Link>Properties\SharedAssemblyInfo.cs</Link>
     </Compile>
     <Compile Include="Converters\PerspexListTypeConverter.cs" />
+    <Compile Include="Converters\RelativeRectTypeConverter.cs" />
     <Compile Include="Data\IXamlBinding.cs" />
     <Compile Include="Data\MultiBinding.cs" />
     <Compile Include="Data\RelativeSource.cs" />

+ 109 - 1
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
 {
     /// <summary>
     /// Defines a rectangle that may be defined relative to a containing element.
     /// </summary>
-    public struct RelativeRect
+    public struct RelativeRect : IEquatable<RelativeRect>
     {
         /// <summary>
         /// A rectangle that represents 100% of an area.
@@ -83,6 +87,63 @@ namespace Perspex
         /// </summary>
         public Rect Rect { get; }
 
+        /// <summary>
+        /// Checks for equality between two <see cref="RelativeRect"/>s.
+        /// </summary>
+        /// <param name="left">The first rectangle.</param>
+        /// <param name="right">The second rectangle.</param>
+        /// <returns>True if the rectangles are equal; otherwise false.</returns>
+        public static bool operator ==(RelativeRect left, RelativeRect right)
+        {
+            return left.Equals(right);
+        }
+
+        /// <summary>
+        /// Checks for unequality between two <see cref="RelativeRect"/>s.
+        /// </summary>
+        /// <param name="left">The first rectangle.</param>
+        /// <param name="right">The second rectangle.</param>
+        /// <returns>True if the rectangles are unequal; otherwise false.</returns>
+        public static bool operator !=(RelativeRect left, RelativeRect right)
+        {
+            return !left.Equals(right);
+        }
+
+        /// <summary>
+        /// Checks if the <see cref="RelativeRect"/> equals another object.
+        /// </summary>
+        /// <param name="obj">The other object.</param>
+        /// <returns>True if the objects are equal, otherwise false.</returns>
+        public override bool Equals(object obj)
+        {
+            return (obj is RelativeRect) ? Equals((RelativeRect)obj) : false;
+        }
+
+        /// <summary>
+        /// Checks if the <see cref="RelativeRect"/> equals another rectangle.
+        /// </summary>
+        /// <param name="p">The other rectangle.</param>
+        /// <returns>True if the objects are equal, otherwise false.</returns>
+        public bool Equals(RelativeRect p)
+        {
+            return Unit == p.Unit && Rect == p.Rect;
+        }
+
+        /// <summary>
+        /// Gets a hashcode for a <see cref="RelativeRect"/>.
+        /// </summary>
+        /// <returns>A hash code.</returns>
+        public override int GetHashCode()
+        {
+            unchecked
+            {
+                int hash = 17;
+                hash = (hash * 23) + Unit.GetHashCode();
+                hash = (hash * 23) + Rect.GetHashCode();
+                return hash;
+            }
+        }
+
         /// <summary>
         /// Converts a <see cref="RelativeRect"/> into pixels.
         /// </summary>
@@ -98,5 +159,52 @@ namespace Perspex
                     Rect.Width * size.Width,
                     Rect.Height * size.Height);
         }
+
+        /// <summary>
+        /// Parses a <see cref="RelativeRect"/> string.
+        /// </summary>
+        /// <param name="s">The string.</param>
+        /// <param name="culture">The current culture.</param>
+        /// <returns>The parsed <see cref="RelativeRect"/>.</returns>
+        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.");
+            }
+        }
     }
 }

+ 1 - 0
tests/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj

@@ -72,6 +72,7 @@
     <Otherwise />
   </Choose>
   <ItemGroup>
+    <Compile Include="RelativeRectTests.cs" />
     <Compile Include="ThicknessTests.cs" />
     <Compile Include="Media\BrushTests.cs" />
     <Compile Include="Media\ColorTests.cs" />

+ 27 - 0
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);
+        }
+    }
+}