#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; namespace Nuclex.UserInterface { /// Stores a size or location on one axis /// /// /// Any position or size in Nuclex.UserInterface uses a combined position consisting /// of a fraction and an offset. The fraction specifies the position or size as a /// fraction of the parent frame's bounds and usually is in the range between 0.0 and /// 1.0. The offset simply is the number of pixels to divert from the thusly /// determined location. /// /// /// Through the use of both fraction and offset, any kind of anchoring behavior can be /// achieved that normally would require a complex anchoring and docking system as can /// be seen in System.Windows.Forms. /// /// /// If you, for example, wanted to always place a control 20 pixels from the right /// border of its parent container, set the fraction of its position to 1.0 (always /// on the right border) and the offset to -20.0 (go 20 units to the left from there). /// /// /// You can achieve traditional absolute positioning by leaving the fraction at 0.0, /// which is equivalent to the upper or left border of the parent container. /// /// public struct UniScalar { /// A scalar that has been initialized to zero public static readonly UniScalar Zero = new UniScalar(); /// Initializes a new scalar from an offset only /// Offset in pixels this scalar indicates public UniScalar(float offset) : this(0.0f, offset) { } /// Initializes a new dimension from an absolute and a relative part /// Fractional position within the parent frame /// Offset in pixels from the fractional position public UniScalar(float fraction, float offset) { this.Fraction = fraction; this.Offset = offset; } /// Implicitely constructs a scalar using a float as the absolute part /// Float that will be used for the scalar's absolute value /// /// A new scalar constructed with the original float as its absolute part /// public static implicit operator UniScalar(float offset) { return new UniScalar(offset); } /// Converts the scalar into a pure offset position /// /// Absolute dimension of the parent that the relative coordinate relates to /// /// /// The absolute position in the parent container denoted by the dimension /// public float ToOffset(float containerSize) { return this.Fraction * containerSize + this.Offset; } /// Adds one scalar to another /// Base scalar to add to /// Scalar to add to the base /// The result of the addition public static UniScalar operator +(UniScalar scalar, UniScalar summand) { return new UniScalar( scalar.Fraction + summand.Fraction, scalar.Offset + summand.Offset ); } /// Subtracts one scalar from another /// Base scalar to subtract from /// Scalar to subtract from the base /// The result of the subtraction public static UniScalar operator -(UniScalar scalar, UniScalar subtrahend) { return new UniScalar( scalar.Fraction - subtrahend.Fraction, scalar.Offset - subtrahend.Offset ); } /// Divides one scalar by another /// Base scalar to be divided /// Divisor to divide by /// The result of the division public static UniScalar operator /(UniScalar scalar, UniScalar divisor) { return new UniScalar( scalar.Fraction / divisor.Fraction, scalar.Offset / divisor.Offset ); } /// Multiplies one scalar with another /// Base scalar to be multiplied /// Factor to multiply by /// The result of the multiplication public static UniScalar operator *(UniScalar scalar, UniScalar factor) { return new UniScalar( scalar.Fraction * factor.Fraction, scalar.Offset * factor.Offset ); } /// Checks two scalars for inequality /// First scalar to be compared /// Second scalar to be compared /// True if the instances differ or exactly one reference is set to null public static bool operator !=(UniScalar first, UniScalar second) { return !(first == second); } /// Checks two scalars for equality /// First scalar to be compared /// Second scalar to be compared /// True if both instances are equal or both references are null public static bool operator ==(UniScalar first, UniScalar 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 UniScalar)) return false; return Equals((UniScalar)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(UniScalar other) { // For a struct, 'other' cannot be null return (this.Fraction == other.Fraction) && (this.Offset == other.Offset); } /// Obtains a hash code of this instance /// The hash code of the instance public override int GetHashCode() { return this.Fraction.GetHashCode() ^ this.Offset.GetHashCode(); } /// /// Returns a human-readable string representation for the unified scalar /// /// The human-readable string representation of the unified scalar public override string ToString() { return string.Format( "{{{0}% {1}{2}}}", this.Fraction * 100.0f, (this.Offset >= 0.0f) ? "+" : string.Empty, this.Offset ); } /// Position of the scalar as fraction of the parent frame's bounds /// /// The relative part is normally in the 0.0 .. 1.0 range, denoting the /// fraction of the parent container's size the scalar will indicate. /// public float Fraction; /// Offset of the scalar in pixels relative to its fractional position /// /// This part is taken literally without paying attention to the size of /// the parent container the coordinate is used in. /// public float Offset; } } // namespace Nuclex.UserInterface