Location.java
package swingtree.layout;
import com.google.errorprone.annotations.Immutable;
import java.awt.Point;
import java.util.Objects;
/**
* An immutable value based class that represents a location in a two-dimensional
* coordinate system specified in float precision and specifically designed
* for Swing components.
* It can be used as an alternative to the AWT {@link Point} class,
* but in situations where immutability is desired (which should be most cases).
* <p>
* Use the {@link #of(float, float)} factory method to create a new instance
* or {@link #withX(int)} and {@link #withY(int)} to create a new instance
* with a modified value.
*/
@Immutable
public final class Location
{
private final static Location ORIGIN = new Location( 0, 0 );
/**
* A factory method that creates a new location with the specified x- and y-coordinates
* or returns the {@link #origin()} constant if both coordinates are zero.
*
* @param x The x-coordinate of the location to create.
* @param y The y-coordinate of the location to create.
* @return A new location with the specified x- and y-coordinates.
* If both coordinates are zero, the {@link #origin()} is returned.
*/
public static Location of( float x, float y ) {
if ( x == 0 && y == 0 )
return ORIGIN;
return new Location(x, y);
}
/**
* A factory method that creates a new location from the supplied AWT {@link Point}.
* If the point is null, a {@link NullPointerException} is thrown.
*
* @param p The point to create a location from.
* @return A new location with the x- and y-coordinates of the specified point.
* If both coordinates are zero, the {@link #origin()} is returned.
*/
public static Location of( Point p ) {
Objects.requireNonNull(p);
return of( p.x, p.y );
}
public static Location origin() {
return ORIGIN;
}
final float _x;
final float _y;
private Location( float x, float y ) {
_x = x;
_y = y;
}
/**
* Exposes the x coordinate of this location in the form of a float,
* which describes the horizontal position in a two-dimensional coordinate system.
* So the larger the x value of the location, the further to the right it is.
*
* @return The x-coordinate of this location.
*/
public float x() {
return _x;
}
/**
* Exposes the y coordinate of this location in the form of a float,
* which describes the vertical position in a two-dimensional coordinate system.
* So the larger the y value of the location, the further down it is.
*
* @return The y-coordinate of this location.
*/
public float y() {
return _y;
}
/**
* Allows you to create an updated version of this location with the
* specified y-coordinate and the same x-coordinate
* as this location instance.
*
* @param y The y-coordinate of the location to create.
* @return A new location with the same x-coordinate as this location
* and the specified y-coordinate.
*/
public Location withY( int y ) {
return of( _x, y );
}
/**
* Allows you to create an updated version of this location with the
* specified x-coordinate and the same y-coordinate
* as this location instance.
*
* @param x The x-coordinate of the location to create.
* @return A new location with the same y-coordinate as this location
* and the specified x-coordinate.
*/
public Location withX( int x ) {
return of( x, _y );
}
/**
* A {@link Location} consists of two x and y coordinates in 2D space, which is
* why this convenience method allows you to transform this
* {@link Location} object to an AWT {@link Point}.
*
* @return A new AWT {@link Point} with the same x- and y-coordinates as this location.
*/
public Point toPoint() {
return new Point( (int) _x, (int) _y);
}
@Override
public String toString() {
return this.getClass().getSimpleName()+"[" +
"x=" + _x + ", "+
"y=" + _y +
"]";
}
@Override
public boolean equals( Object o ) {
if ( o == this ) return true;
if ( o == null ) return false;
if ( o.getClass() != this.getClass() ) return false;
Location other = (Location) o;
return _x == other._x && _y == other._y;
}
@Override
public int hashCode() {
return Float.hashCode(_x) ^ Float.hashCode(_y);
}
}