/* Point.java -- represents a point in 2-D space
   Copyright (C) 1999, 2002 Free Software Foundation

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.awt;

import java.awt.geom.Point2D;
import java.io.Serializable;

/**
 * This class represents a point on the screen using cartesian coordinates.
 * Remember that in screen coordinates, increasing x values go from left to
 * right, and increasing y values go from top to bottom.
 *
 * <p>There are some public fields; if you mess with them in an inconsistent
 * manner, it is your own fault when you get invalid results. Also, this
 * class is not threadsafe.
 *
 * @author Per Bothner (bothner@cygnus.com)
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Eric Blake (ebb9@email.byu.edu)
 * @since 1.0
 * @status updated to 1.4
 */
public class Point extends Point2D implements Serializable
{
  /**
   * Compatible with JDK 1.0+.
   */
  private static final long serialVersionUID = -5276940640259749850L;

  /**
   * The x coordinate.
   *
   * @see #getLocation()
   * @see #move(int, int)
   * @serial the X coordinate of the point
   */
  public int x;

  /**
   * The y coordinate.
   *
   * @see #getLocation()
   * @see #move(int, int)
   * @serial The Y coordinate of the point
   */
  public int y;

  /**
   * Initializes a new instance of <code>Point</code> representing the
   * coordiates (0,0).
   *
   * @since 1.1
   */
  public Point()
  {
  }

  /**
   * Initializes a new instance of <code>Point</code> with coordinates
   * identical to the coordinates of the specified points.
   *
   * @param p the point to copy the coordinates from
   * @throws NullPointerException if p is null
   */
  public Point(Point p)
  {
    x = p.x;
    y = p.y;
  }

  /**
   * Initializes a new instance of <code>Point</code> with the specified
   * coordinates.
   *
   * @param x the X coordinate
   * @param y the Y coordinate
   */
  public Point(int x, int y)
  {
    this.x = x;
    this.y = y;
  }

  /**
   * Get the x coordinate.
   *
   * @return the value of x, as a double
   */
  public double getX()
  {
    return x;
  }

  /**
   * Get the y coordinate.
   *
   * @return the value of y, as a double
   */
  public double getY()
  {
    return y;
  }

  /**
   * Returns the location of this point. A pretty useless method, as this
   * is already a point.
   *
   * @return a copy of this point
   * @see #setLocation(Point)
   * @since 1.1
   */
  public Point getLocation()
  {
    return new Point(x, y);
  }

  /**
   * Sets this object's coordinates to match those of the specified point.
   *
   * @param p the point to copy the coordinates from
   * @throws NullPointerException if p is null
   * @since 1.1
   */
  public void setLocation(Point p)
  {
    x = p.x;
    y = p.y;
  }

  /**
   * Sets this object's coordinates to the specified values.  This method
   * is identical to the <code>move()</code> method.
   *
   * @param x the new X coordinate
   * @param y the new Y coordinate
   */
  public void setLocation(int x, int y)
  {
    this.x = x;
    this.y = y;
  }

  /**
   * Sets this object's coordinates to the specified values.  This method
   * performs normal casting from double to int, so you may lose precision.
   *
   * @param x the new X coordinate
   * @param y the new Y coordinate
   */
  public void setLocation(double x, double y)
  {
    this.x = (int) x;
    this.y = (int) y;
  }

  /**
   * Sets this object's coordinates to the specified values.  This method
   * is identical to the <code>setLocation(int, int)</code> method.
   *
   * @param x the new X coordinate
   * @param y the new Y coordinate
   */
  public void move(int x, int y)
  {
    this.x = x;
    this.y = y;
  }

  /**
   * Changes the coordinates of this point such that the specified
   * <code>dx</code> parameter is added to the existing X coordinate and
   * <code>dy</code> is added to the existing Y coordinate.
   *
   * @param dx the amount to add to the X coordinate
   * @param dy the amount to add to the Y coordinate
   */
  public void translate(int dx, int dy)
  {
    x += dx;
    y += dy;
  }

  /**
   * Tests whether or not this object is equal to the specified object.
   * This will be true if and only if the specified object is an instance
   * of Point2D and has the same X and Y coordinates.
   *
   * @param obj the object to test against for equality
   * @return true if the specified object is equal
  */
  public boolean equals(Object obj)
  {
    // NOTE: No special hashCode() method is required for this class,
    // as this equals() implementation is functionally equivalent to
    // super.equals(), which does define a proper hashCode().

    if (! (obj instanceof Point2D))
      return false;
    Point2D p = (Point2D) obj;
    return x == p.getX() && y == p.getY();
  }

  /**
   * Returns a string representation of this object. The format is:
   * <code>getClass().getName() + "[x=" + x + ",y=" + y + ']'</code>.
   *
   * @return a string representation of this object
   */
  public String toString()
  {
    return getClass().getName() + "[x=" + x + ",y=" + y + ']';
  }
} // class Point
