#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