#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2010 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
namespace Nuclex.UserInterface {
///
/// Two-dimensional rectangle of combined fraction and offset coordinates
///
public struct UniRectangle {
/// An empty unified rectangle
public static readonly UniRectangle Empty = new UniRectangle();
/// Initializes a new rectangle from a location and a size
/// Location of the rectangle's upper left corner
/// Size of the area covered by the rectangle
public UniRectangle(UniVector location, UniVector size) {
this.Location = location;
this.Size = size;
}
///
/// Initializes a new rectangle from the provided individual coordinates
///
/// X coordinate of the rectangle's left border
/// Y coordinate of the rectangle's upper border
/// Width of the area covered by the rectangle
/// Height of the area covered by the rectangle
public UniRectangle(UniScalar x, UniScalar y, UniScalar width, UniScalar height) {
this.Location = new UniVector(x, y);
this.Size = new UniVector(width, height);
}
/// Converts the rectangle into pure offset coordinates
///
/// Dimensions of the container the fractional part of the rectangle count for
///
/// A rectangle with the pure offset coordinates of the rectangle
public RectangleF ToOffset(Vector2 containerSize) {
return ToOffset(containerSize.X, containerSize.Y);
}
/// Converts the rectangle into pure offset coordinates
///
/// Width of the container the fractional part of the rectangle counts for
///
///
/// Height of the container the fractional part of the rectangle counts for
///
/// A rectangle with the pure offset coordinates of the rectangle
public RectangleF ToOffset(float containerWidth, float containerHeight) {
float leftOffset = this.Left.Fraction * containerWidth + this.Left.Offset;
float topOffset = this.Top.Fraction * containerHeight + this.Top.Offset;
return new RectangleF(
leftOffset,
topOffset,
(this.Right.Fraction * containerWidth + this.Right.Offset) - leftOffset,
(this.Bottom.Fraction * containerHeight + this.Bottom.Offset) - topOffset
);
}
/// X coordinate of the rectangle's left border
public UniScalar Left {
get { return this.Location.X; }
set { this.Location.X = value; }
}
/// Y coordinate of the rectangle's upper border
public UniScalar Top {
get { return this.Location.Y; }
set { this.Location.Y = value; }
}
/// X coordinate of the rectangle's right border
public UniScalar Right {
get { return this.Location.X + this.Size.X; }
set { this.Size.X = value - this.Location.X; }
}
/// Y coordinate of the rectangle's lower border
public UniScalar Bottom {
get { return this.Location.Y + this.Size.Y; }
set { this.Size.Y = value - this.Location.Y; }
}
/// Point consisting of the lesser coordinates of the rectangle
public UniVector Min {
get { return this.Location; }
set {
// In short: this.Size += this.Location - value;
// Done for performance reasons
this.Size.X.Fraction += this.Location.X.Fraction - value.X.Fraction;
this.Size.X.Offset += this.Location.X.Offset - value.X.Offset;
this.Size.Y.Fraction += this.Location.Y.Fraction - value.Y.Fraction;
this.Size.Y.Offset += this.Location.Y.Offset - value.Y.Offset;
this.Location = value;
}
}
/// Point consisting of the greater coordinates of the rectangle
public UniVector Max {
get { return this.Location + this.Size; }
set {
// In short: this.Size = value - this.Location;
// Done for performance reasons
this.Size.X.Fraction = value.X.Fraction - this.Location.X.Fraction;
this.Size.X.Offset = value.X.Offset - this.Location.X.Offset;
this.Size.Y.Fraction = value.Y.Fraction - this.Location.X.Fraction;
this.Size.Y.Offset = value.Y.Offset - this.Location.Y.Offset;
}
}
/// Checks two rectangles for inequality
/// First rectangle to be compared
/// Second rectangle to be compared
/// True if the instances differ or exactly one reference is set to null
public static bool operator !=(UniRectangle first, UniRectangle second) {
return !(first == second);
}
/// Checks two rectangles for equality
/// First rectangle to be compared
/// Second rectangle to be compared
/// True if both instances are equal or both references are null
public static bool operator ==(UniRectangle first, UniRectangle second) {
// For a struct, neither 'first' nor 'second' can be null
return first.Equals(second);
}
/// Checks whether another instance is equal to this instance
/// Other instance to compare to this instance
/// True if the other instance is equal to this instance
public override bool Equals(object other) {
if(!(other is UniRectangle))
return false;
return Equals((UniRectangle)other);
}
/// Checks whether another instance is equal to this instance
/// Other instance to compare to this instance
/// True if the other instance is equal to this instance
public bool Equals(UniRectangle other) {
// For a struct, 'other' cannot be null
return (this.Location == other.Location) && (this.Size == other.Size);
}
/// Obtains a hash code of this instance
/// The hash code of the instance
public override int GetHashCode() {
return this.Location.GetHashCode() ^ this.Size.GetHashCode();
}
///
/// Returns a human-readable string representation for the unified rectangle
///
/// The human-readable string representation of the unified rectangle
public override string ToString() {
return string.Format(
"{{Location:{0}, Size:{1}}}",
this.Location.ToString(),
this.Size.ToString()
);
}
/// The location of the rectangle's upper left corner
public UniVector Location;
/// The size of the rectangle
public UniVector Size;
}
} // namespace Nuclex.UserInterface