csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
7.9 KiB
211 lines
7.9 KiB
// Copyright (c) The Avalonia 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 Avalonia.Utilities;
|
|
|
|
namespace Avalonia
|
|
{
|
|
/// <summary>
|
|
/// Defines a rectangle that may be defined relative to a containing element.
|
|
/// </summary>
|
|
public readonly struct RelativeRect : IEquatable<RelativeRect>
|
|
{
|
|
private static readonly char[] PercentChar = { '%' };
|
|
|
|
/// <summary>
|
|
/// A rectangle that represents 100% of an area.
|
|
/// </summary>
|
|
public static readonly RelativeRect Fill = new RelativeRect(0, 0, 1, 1, RelativeUnit.Relative);
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RelativeRect"/> structure.
|
|
/// </summary>
|
|
/// <param name="x">The X position.</param>
|
|
/// <param name="y">The Y position.</param>
|
|
/// <param name="width">The width.</param>
|
|
/// <param name="height">The height.</param>
|
|
/// <param name="unit">The unit of the rect.</param>
|
|
public RelativeRect(double x, double y, double width, double height, RelativeUnit unit)
|
|
{
|
|
Rect = new Rect(x, y, width, height);
|
|
Unit = unit;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RelativeRect"/> structure.
|
|
/// </summary>
|
|
/// <param name="rect">The rectangle.</param>
|
|
/// <param name="unit">The unit of the rect.</param>
|
|
public RelativeRect(Rect rect, RelativeUnit unit)
|
|
{
|
|
Rect = rect;
|
|
Unit = unit;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RelativeRect"/> structure.
|
|
/// </summary>
|
|
/// <param name="size">The size of the rectangle.</param>
|
|
/// <param name="unit">The unit of the rect.</param>
|
|
public RelativeRect(Size size, RelativeUnit unit)
|
|
{
|
|
Rect = new Rect(size);
|
|
Unit = unit;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RelativeRect"/> structure.
|
|
/// </summary>
|
|
/// <param name="position">The position of the rectangle.</param>
|
|
/// <param name="size">The size of the rectangle.</param>
|
|
/// <param name="unit">The unit of the rect.</param>
|
|
public RelativeRect(Point position, Size size, RelativeUnit unit)
|
|
{
|
|
Rect = new Rect(position, size);
|
|
Unit = unit;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RelativeRect"/> structure.
|
|
/// </summary>
|
|
/// <param name="topLeft">The top left position of the rectangle.</param>
|
|
/// <param name="bottomRight">The bottom right position of the rectangle.</param>
|
|
/// <param name="unit">The unit of the rect.</param>
|
|
public RelativeRect(Point topLeft, Point bottomRight, RelativeUnit unit)
|
|
{
|
|
Rect = new Rect(topLeft, bottomRight);
|
|
Unit = unit;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the unit of the rectangle.
|
|
/// </summary>
|
|
public RelativeUnit Unit { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the rectangle.
|
|
/// </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 inequality 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);
|
|
}
|
|
|
|
/// <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>
|
|
/// <param name="size">The size of the visual.</param>
|
|
/// <returns>The origin point in pixels.</returns>
|
|
public Rect ToPixels(Size size)
|
|
{
|
|
return Unit == RelativeUnit.Absolute ?
|
|
Rect :
|
|
new Rect(
|
|
Rect.X * size.Width,
|
|
Rect.Y * size.Height,
|
|
Rect.Width * size.Width,
|
|
Rect.Height * size.Height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses a <see cref="RelativeRect"/> string.
|
|
/// </summary>
|
|
/// <param name="s">The string.</param>
|
|
/// <returns>The parsed <see cref="RelativeRect"/>.</returns>
|
|
public static RelativeRect Parse(string s)
|
|
{
|
|
using (var tokenizer = new StringTokenizer(s, exceptionMessage: "Invalid RelativeRect"))
|
|
{
|
|
var x = tokenizer.ReadString();
|
|
var y = tokenizer.ReadString();
|
|
var width = tokenizer.ReadString();
|
|
var height = tokenizer.ReadString();
|
|
|
|
var unit = RelativeUnit.Absolute;
|
|
var scale = 1.0;
|
|
|
|
var xRelative = x.EndsWith("%", StringComparison.Ordinal);
|
|
var yRelative = y.EndsWith("%", StringComparison.Ordinal);
|
|
var widthRelative = width.EndsWith("%", StringComparison.Ordinal);
|
|
var heightRelative = height.EndsWith("%", StringComparison.Ordinal);
|
|
|
|
if (xRelative && yRelative && widthRelative && heightRelative)
|
|
{
|
|
x = x.TrimEnd(PercentChar);
|
|
y = y.TrimEnd(PercentChar);
|
|
width = width.TrimEnd(PercentChar);
|
|
height = height.TrimEnd(PercentChar);
|
|
|
|
unit = RelativeUnit.Relative;
|
|
scale = 0.01;
|
|
}
|
|
else if (xRelative || yRelative || widthRelative || heightRelative)
|
|
{
|
|
throw new FormatException("If one coordinate is relative, all must be.");
|
|
}
|
|
|
|
return new RelativeRect(
|
|
double.Parse(x, CultureInfo.InvariantCulture) * scale,
|
|
double.Parse(y, CultureInfo.InvariantCulture) * scale,
|
|
double.Parse(width, CultureInfo.InvariantCulture) * scale,
|
|
double.Parse(height, CultureInfo.InvariantCulture) * scale,
|
|
unit);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|