using System.Diagnostics.CodeAnalysis;
namespace RhythmBase.Components
{
///
/// Represents a rectangle defined by four expressions: left, top, right, and bottom.
///
/// The left expression of the rectangle.
/// The top expression of the rectangle.
/// The right expression of the rectangle.
/// The bottom expression of the rectangle.
public struct RDRectE(RDExpression? left, RDExpression? top, RDExpression? right, RDExpression? bottom) : IEquatable
{
///
/// Gets or sets the left expression of the rectangle.
///
public RDExpression? Left { get; set; } = left;
///
/// Gets or sets the right expression of the rectangle.
///
public RDExpression? Right { get; set; } = right;
///
/// Gets or sets the top expression of the rectangle.
///
public RDExpression? Top { get; set; } = top;
///
/// Gets or sets the bottom expression of the rectangle.
///
public RDExpression? Bottom { get; set; } = bottom;
///
/// Gets the left-bottom point of the rectangle.
///
public readonly RDPointE LeftBottom => new(Left, Bottom);
///
/// Gets the right-bottom point of the rectangle.
///
public readonly RDPointE RightBottom => new(Right, Bottom);
///
/// Gets the left-top point of the rectangle.
///
public readonly RDPointE LeftTop => new(Left, Top);
///
/// Gets the right-top point of the rectangle.
///
public readonly RDPointE RightTop => new(Right, Top);
///
/// Gets the width of the rectangle.
///
public readonly RDExpression? Width => Right - Left;
///
/// Gets the height of the rectangle.
///
public readonly RDExpression? Height => Top - Bottom;
///
/// Initializes a new instance of the struct with the specified location and size.
///
/// The location of the rectangle.
/// The size of the rectangle.
public RDRectE(RDPointE? location, RDSizeE? size) : this(location?.X, location?.Y + size?.Height, location?.X + size?.Width, location?.Y) { }
///
/// Initializes a new instance of the struct with the specified size.
///
/// The size of the rectangle.
public RDRectE(RDSizeE size) : this(new RDExpression?(0f), size.Height, size.Width, new RDExpression?(0f)) { }
///
/// Initializes a new instance of the struct with the specified width and height.
///
/// The width of the rectangle.
/// The height of the rectangle.
public RDRectE(RDExpression? width, RDExpression? height) : this(new RDExpression?(0f), height, width, new RDExpression?(0f)) { }
///
/// Gets the location of the rectangle.
///
public readonly RDPointE Location => new(Left, Bottom);
///
/// Gets the size of the rectangle.
///
public readonly RDSizeE Size => new(Width, Height);
///
/// Inflates the specified rectangle by the specified size.
///
/// The rectangle to inflate.
/// The size to inflate by.
/// The inflated rectangle.
public static RDRectE Inflate(RDRectE rect, RDSizeE size)
{
RDRectE result = new(rect.Left, rect.Top, rect.Right, rect.Bottom);
result.Inflate(size);
return result;
}
///
/// Inflates the specified rectangle by the specified width and height.
///
/// The rectangle to inflate.
/// The width to inflate by.
/// The height to inflate by.
/// The inflated rectangle.
public static RDRectE Inflate(RDRectE rect, RDExpression? x, RDExpression? y)
{
RDRectE result = new(rect.Left, rect.Top, rect.Right, rect.Bottom);
result.Inflate(x, y);
return result;
}
///
/// Truncates the specified rectangle.
///
/// The rectangle to truncate.
/// The truncated rectangle.
public static RDRectE Truncate(RDRectE rect) => new(rect.Left, rect.Top, rect.Right, rect.Bottom);
///
/// Offsets the rectangle by the specified width and height.
///
/// The width to offset by.
/// The height to offset by.
public void Offset(RDExpression? x, RDExpression? y)
{
Left += x;
Top += y;
Right += x;
Bottom += y;
}
///
/// Offsets the rectangle by the specified point.
///
/// The point to offset by.
public void Offset(RDPointE p) => Offset(p.X, p.Y);
///
/// Inflates the rectangle by the specified size.
///
/// The size to inflate by.
public void Inflate(RDSizeE size)
{
Left -= size.Width;
Top += size.Height;
Right += size.Width;
Bottom -= size.Height;
}
///
/// Inflates the rectangle by the specified width and height.
///
/// The width to inflate by.
/// The height to inflate by.
public void Inflate(RDExpression? width, RDExpression? height)
{
Left -= width;
Top += height;
Right += width;
Bottom -= height;
}
///
public static bool operator ==(RDRectE rect1, RDRectE rect2) => rect1.Equals(rect2);
///
public static bool operator !=(RDRectE rect1, RDRectE rect2) => !rect1.Equals(rect2);
///
public override readonly bool Equals([NotNullWhen(true)] object? obj) => obj is RDRectE e && Equals(e);
///
public override readonly int GetHashCode() => HashCode.Combine(Left, Top, Right, Bottom);
///
public override readonly string ToString() => $"{{Location=[{Left},{Bottom}],Size=[{Width},{Height}]}}";
///
public readonly bool Equals(RDRectE other) => Left == other.Left && Top == other.Top && Right == other.Right && Bottom == other.Bottom;
}
}