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; } }