/* MouseEvent.java -- a mouse event
   Copyright (C) 1999, 2002, 2004, 2005  Free Software Foundation, Inc.

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.event;

import gnu.java.awt.EventModifier;

import java.awt.Component;
import java.awt.Point;
import java.awt.PopupMenu;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 * This event is generated for a mouse event. There are three main categories
 * of mouse events: Regular events include pressing, releasing, and clicking
 * buttons, as well as moving over the boundary of the unobscured portion of
 * a component. Motion events include movement and dragging. Wheel events are
 * covered separately by the subclass MouseWheelEvent.
 *
 * <p>A mouse event is tied to the unobstructed visible component that the
 * mouse cursor was over at the time of the action. The button that was
 * most recently pressed is the only one that shows up in
 * <code>getModifiers</code>, and is returned by <code>getButton</code>,
 * while all buttons that are down show up in <code>getModifiersEx</code>.
 *
 * <p>Drag events may be cut short if native drag-and-drop operations steal
 * the event. Likewise, if a mouse drag exceeds the bounds of a window or
 * virtual device, some platforms may clip the path to fit in the bounds of
 * the component.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Eric Blake (ebb9@email.byu.edu)
 * @see MouseAdapter
 * @see MouseListener
 * @see MouseMotionAdapter
 * @see MouseMotionListener
 * @see MouseWheelListener
 * @since 1.1
 * @status updated to 1.4
 */
public class MouseEvent extends InputEvent
{
  /**
   * Compatible with JDK 1.1+.
   */
  private static final long serialVersionUID = -991214153494842848L;

  /** This is the first id in the range of event ids used by this class. */
  public static final int MOUSE_FIRST = 500;

  /** This is the last id in the range of event ids used by this class. */
  public static final int MOUSE_LAST = 507;

  /** This event id indicates that the mouse was clicked. */
  public static final int MOUSE_CLICKED = 500;

  /** This event id indicates that the mouse was pressed. */
  public static final int MOUSE_PRESSED = 501;

  /** This event id indicates that the mouse was released. */
  public static final int MOUSE_RELEASED = 502;

  /** This event id indicates that the mouse was moved. */
  public static final int MOUSE_MOVED = 503;

  /** This event id indicates that the mouse entered a component. */
  public static final int MOUSE_ENTERED = 504;

  /** This event id indicates that the mouse exited a component. */
  public static final int MOUSE_EXITED = 505;

  /**
   * This indicates that no button changed state.
   *
   * @see #getButton()
   * @since 1.4
   */
  public static final int NOBUTTON = 0;

  /**
   * This indicates that button 1 changed state.
   *
   * @see #getButton()
   * @since 1.4
   */
  public static final int BUTTON1 = 1;

  /**
   * This indicates that button 2 changed state.
   *
   * @see #getButton()
   * @since 1.4
   */
  public static final int BUTTON2 = 2;

  /**
   * This indicates that button 3 changed state.
   *
   * @see #getButton()
   * @since 1.4
   */
  public static final int BUTTON3 = 3;

  /** This event id indicates that the mouse was dragged over a component. */
  public static final int MOUSE_DRAGGED = 506;

  /**
   * This event id indicates that the mouse wheel was rotated.
   *
   * @since 1.4
   */
  public static final int MOUSE_WHEEL = 507;

  /**
   * The X coordinate of the mouse cursor at the time of the event.
   *
   * @see #getX()
   * @serial the x coordinate
  */
  private int x;

  /**
   * The Y coordinate of the mouse cursor at the time of the event.
   *
   * @see #getY()
   * @serial the y coordinate
   */
  private int y;

  /**
   * The number of clicks that took place. For MOUSE_CLICKED, MOUSE_PRESSED,
   * and MOUSE_RELEASED, this will be at least 1; otherwise it is 0.
   *
   * see #getClickCount()
   * @serial the number of clicks
   */
  private final int clickCount;

  /**
   * Indicates which mouse button changed state. Can only be one of
   * {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or
   * {@link #BUTTON3}.
   *
   * @see #getButton()
   * @since 1.4
   */
  private int button;

  /**
   * Whether or not this event should trigger a popup menu.
   *
   * @see PopupMenu
   * @see #isPopupTrigger()
   * @serial true if this is a popup trigger
   */
  private final boolean popupTrigger;

  /**
   * Initializes a new instance of <code>MouseEvent</code> with the specified
   * information. Note that an invalid id leads to unspecified results.
   *
   * @param source the source of the event
   * @param id the event id
   * @param when the timestamp of when the event occurred
   * @param modifiers the modifier keys during the event, in old or new style
   * @param x the X coordinate of the mouse point
   * @param y the Y coordinate of the mouse point
   * @param clickCount the number of mouse clicks for this event
   * @param popupTrigger true if this event triggers a popup menu
   * @param button the most recent mouse button to change state
   * @throws IllegalArgumentException if source is null or button is invalid
   * @since 1.4
   */
  public MouseEvent(Component source, int id, long when, int modifiers,
                    int x, int y, int clickCount, boolean popupTrigger,
                    int button)
  {
    super(source, id, when, modifiers);
    this.x = x;
    this.y = y;
    this.clickCount = clickCount;
    this.popupTrigger = popupTrigger;
    this.button = button;
    if (button < NOBUTTON || button > BUTTON3)
      throw new IllegalArgumentException();
    if ((modifiers & EventModifier.OLD_MASK) != 0)
      {
        if ((modifiers & BUTTON1_MASK) != 0)
          this.button = BUTTON1;
        else if ((modifiers & BUTTON2_MASK) != 0)
          this.button = BUTTON2;
        else if ((modifiers & BUTTON3_MASK) != 0)
          this.button = BUTTON3;
      }
    // clear the mouse button modifier masks if this is a button
    // release event.
    if (id == MOUSE_RELEASED)
      this.modifiersEx &= ~(BUTTON1_DOWN_MASK
			    | BUTTON2_DOWN_MASK
			    | BUTTON3_DOWN_MASK);
  }

  /**
   * Initializes a new instance of <code>MouseEvent</code> with the specified
   * information. Note that an invalid id leads to unspecified results.
   *
   * @param source the source of the event
   * @param id the event id
   * @param when the timestamp of when the event occurred
   * @param modifiers the modifier keys during the event, in old or new style
   * @param x the X coordinate of the mouse point
   * @param y the Y coordinate of the mouse point
   * @param clickCount the number of mouse clicks for this event
   * @param popupTrigger true if this event triggers a popup menu
   * @throws IllegalArgumentException if source is null
   */
  public MouseEvent(Component source, int id, long when, int modifiers,
                    int x, int y, int clickCount, boolean popupTrigger)
  {
    this(source, id, when, modifiers, x, y, clickCount, popupTrigger,
         NOBUTTON);
  }

  /**
   * This method returns the X coordinate of the mouse position. This is
   * relative to the source component.
   *
   * @return the x coordinate
   */
  public int getX()
  {
    return x;
  }

  /**
   * This method returns the Y coordinate of the mouse position. This is
   * relative to the source component.
   *
   * @return the y coordinate
   */
  public int getY()
  {
    return y;
  }

  /**
   * This method returns a <code>Point</code> for the x,y position of
   * the mouse pointer. This is relative to the source component.
   *
   * @return a <code>Point</code> for the event position
   */
  public Point getPoint()
  {
    return new Point(x, y);
  }

  /**
   * Translates the event coordinates by the specified x and y offsets.
   *
   * @param dx the value to add to the X coordinate of this event
   * @param dy the value to add to the Y coordiante of this event
   */
  public void translatePoint(int dx, int dy)
  {
    x += dx;
    y += dy;
  }

  /**
   * This method returns the number of mouse clicks associated with this
   * event.
   *
   * @return the number of mouse clicks for this event
   */
  public int getClickCount()
  {
    return clickCount;
  }

  /**
   * Returns which button, if any, was the most recent to change state. This
   * will be one of {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or
   * {@link #BUTTON3}.
   *
   * @return the button that changed state
   * @since 1.4
   */
  public int getButton()
  {
    return button;
  }

  /**
   * This method tests whether or not the event is a popup menu trigger. This
   * should be checked in both MousePressed and MouseReleased to be
   * cross-platform compatible, as different systems have different popup
   * triggers.
   *
   * @return true if the event is a popup menu trigger
   */
  public boolean isPopupTrigger()
  {
    return popupTrigger;
  }

  /**
   * Returns a string describing the modifiers, such as "Shift" or
   * "Ctrl+Button1".
   *
   * XXX Sun claims this can be localized via the awt.properties file - how
   * do we implement that?
   *
   * @param modifiers the old-style modifiers to convert to text
   * @return a string representation of the modifiers in this bitmask
   */
  public static String getMouseModifiersText(int modifiers)
  {
    modifiers &= EventModifier.OLD_MASK;
    if ((modifiers & BUTTON2_MASK) != 0)
      modifiers |= BUTTON2_DOWN_MASK;
    if ((modifiers & BUTTON3_MASK) != 0)
      modifiers |= BUTTON3_DOWN_MASK;
    return getModifiersExText(EventModifier.extend(modifiers));
  }

  /**
   * Returns a string identifying this event. This is formatted as the field
   * name of the id type, followed by the (x,y) point, the most recent button
   * changed, modifiers (if any), extModifiers (if any), and clickCount.
   *
   * @return a string identifying this event
   */
  public String paramString()
  {
    StringBuffer s = new StringBuffer();
    switch (id)
      {
      case MOUSE_CLICKED:
        s.append("MOUSE_CLICKED,(");
        break;
      case MOUSE_PRESSED:
        s.append("MOUSE_PRESSED,(");
        break;
      case MOUSE_RELEASED:
        s.append("MOUSE_RELEASED,(");
        break;
      case MOUSE_MOVED:
        s.append("MOUSE_MOVED,(");
        break;
      case MOUSE_ENTERED:
        s.append("MOUSE_ENTERED,(");
        break;
      case MOUSE_EXITED:
        s.append("MOUSE_EXITED,(");
        break;
      case MOUSE_DRAGGED:
        s.append("MOUSE_DRAGGED,(");
        break;
      case MOUSE_WHEEL:
        s.append("MOUSE_WHEEL,(");
        break;
      default:
        s.append("unknown type,(");
      }
    s.append(x).append(',').append(y).append("),button=").append(button);
    // FIXME: need a mauve test for this method
    if (modifiersEx != 0)
      s.append(",extModifiers=").append(getModifiersExText(modifiersEx));
    
    s.append(",clickCount=").append(clickCount);
    s.append(",consumed=").append(consumed);
    
    return s.toString();
  }

  /**
   * Reads in the object from a serial stream.
   *
   * @param s the stream to read from
   * @throws IOException if deserialization fails
   * @throws ClassNotFoundException if deserialization fails
   * @serialData default, except that the modifiers are converted to new style
   */
  private void readObject(ObjectInputStream s)
    throws IOException, ClassNotFoundException
  {
    s.defaultReadObject();
    if ((modifiers & EventModifier.OLD_MASK) != 0)
      {
        if ((modifiers & BUTTON1_MASK) != 0)
          button = BUTTON1;
        else if ((modifiers & BUTTON2_MASK) != 0)
          button = BUTTON2;
        else if ((modifiers & BUTTON3_MASK) != 0)
          button = BUTTON3;
        modifiersEx = EventModifier.extend(modifiers) & EventModifier.NEW_MASK;
      }
  }
} // class MouseEvent
