|
|
@@ -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.");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|