/* LightweightDispatcher.java -- Dispatches mouse events to lightweights
   Copyright (C) 2006 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;

import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.peer.LightweightPeer;
import java.util.WeakHashMap;

/**
 * Redispatches mouse events to lightweight components. The native peers know
 * nothing about the lightweight components and thus mouse events are always
 * targetted at Windows or heavyweight components. This class listenes directly
 * on the eventqueue and dispatches mouse events to lightweight components.
 *
 * @author Roman Kennke (kennke@aicas.com)
 */
final class LightweightDispatcher
{

  /**
   * Maps thread groups to lightweight dispatcher instances. We need to
   * have one instance per thread group so that 2 or more applets or otherwise
   * separated applications (like in OSGI) do not interfer with each other.
   */
  private static WeakHashMap instances = new WeakHashMap();

  /**
   * The last mouse event target. If the target changes, additional
   * MOUSE_ENTERED and MOUSE_EXITED events must be dispatched.
   */
  private Component lastTarget;

  /**
   * The current mouseEventTarget.
   */
  private Component mouseEventTarget;

  /**
   * Returns an instance of LightweightDispatcher for the current thread's
   * thread group.
   *
   * @return an instance of LightweightDispatcher for the current thread's
   *         thread group
   */
  static LightweightDispatcher getInstance()
  {
    Thread t = Thread.currentThread();
    ThreadGroup tg = t.getThreadGroup();
    LightweightDispatcher instance = (LightweightDispatcher) instances.get(tg);
    if (instance == null)
      {
        instance = new LightweightDispatcher();
        instances.put(tg, instance);
      }
    return instance;
  }

  /**
   * Creates a new LightweightDispatcher. This is private to prevent access
   * from outside. Use {@link #getInstance()} instead.
   */
  private LightweightDispatcher()
  {
    // Nothing to do here.
  }
  
  /**
   * Receives notification if a mouse event passes along the eventqueue.
   *
   * @param event the event
   */
  public boolean dispatchEvent(final AWTEvent event)
  {
    if (event instanceof MouseEvent)
      {
        MouseEvent mouseEvent = (MouseEvent) event;
        return handleMouseEvent(mouseEvent);
      }
    return false;
  }

  /**
   * Handles all mouse events that are targetted at toplevel containers
   * (Window instances) and dispatches them to the correct lightweight child.
   * 
   * @param ev the mouse event
   * @return whether or not we found a lightweight that handled the event.
   */
  private boolean handleMouseEvent(final MouseEvent ev)
  {
    Container container = (Container) ev.getSource();
    Component target = findTarget(container, ev.getX(), ev.getY());
    trackEnterExit(target, ev);
    int id = ev.getID();

    // Dont update the mouseEventTarget when dragging. Also, MOUSE_CLICKED
    // must be dispatched to the original target of MOUSE_PRESSED, so don't
    // update in this case either.
    if (! isDragging(ev) && id != MouseEvent.MOUSE_CLICKED)
      mouseEventTarget = (target != container) ? target : null;

    if (mouseEventTarget != null)
      {
        switch (id)
          {
          case MouseEvent.MOUSE_ENTERED:
          case MouseEvent.MOUSE_EXITED:
            // This is already handled in trackEnterExit().
            break;
          case MouseEvent.MOUSE_PRESSED:
          case MouseEvent.MOUSE_RELEASED:
          case MouseEvent.MOUSE_MOVED:
            redispatch(ev, mouseEventTarget, id);
            break;
          case MouseEvent.MOUSE_CLICKED:
            // MOUSE_CLICKED must be dispatched to the original target of
            // MOUSE_PRESSED.
            if (target == mouseEventTarget)
              redispatch(ev, mouseEventTarget, id);
            break;
          case MouseEvent.MOUSE_DRAGGED:
            if (isDragging(ev))
              redispatch(ev, mouseEventTarget, id);
            break;
          case MouseEvent.MOUSE_WHEEL:
            redispatch(ev, mouseEventTarget, id);
          }
        ev.consume();
      }

    return ev.isConsumed();
  }

  /**
   * Finds the actual target for a mouseevent, starting at <code>c</code>.
   * This searches through the children of the container and finds the first
   * one which is showing, at the location from the mouse event and has
   * a MouseListener or MouseMotionListener attached. If no such child component
   * is found, null is returned.
   *
   * @param c the container to search through
   * @param loc the mouse event point
   *
   * @return the actual receiver of the mouse event, or null, if no such
   *         component has been found
   */
  private Component findTarget(final Container c, final int x, final int y)
  {
    Component target = null;

    // First we check the children of the container.

    // Note: It is important that we use the package private Container
    // fields ncomponents and component here. There are applications
    // that override getComponentCount()
    // and getComponent() to hide internal components, which makes
    // the LightweightDispatcher not work correctly in these cases.
    // As a positive sideeffect this is slightly more efficient.
    int nChildren = c.ncomponents;
    for (int i = 0; i < nChildren && target == null; i++)
      {
        Component child = c.component[i];
        int childX = x - child.x;
        int childY = y - child.y;
        if (child != null && child.visible
            && child.peer instanceof LightweightPeer
            && child.contains(childX, childY))
          {
            // Check if there's a deeper possible target.
            if (child instanceof Container)
              {
                Component deeper = findTarget((Container) child,
                                              childX, childY);
                if (deeper != null)
                  target = deeper;
              }
            // Check if the child itself is interested in mouse events.
            else if (isMouseListening(child))
              target = child;
          }
      }

    // Check the container itself, if we didn't find a target yet.
    if (target == null  && c.contains(x, y) && isMouseListening(c))
      target = c;

    return target;
  }

  /**
   * Checks if the specified component would be interested in a mouse event.
   *
   * @param c the component to check
   *
   * @return <code>true</code> if the component has mouse listeners installed,
   *         <code>false</code> otherwise
   */
  private boolean isMouseListening(final Component c)
  {
    // Note: It is important to NOT check if the component is listening
    // for a specific event (for instance, mouse motion events). The event
    // gets dispatched to the component if the component is listening
    // for ANY mouse event, even when the component is not listening for the
    // specific type of event. There are applications that depend on this
    // (sadly).
    return c.mouseListener != null
           || c.mouseMotionListener != null
           || c.mouseWheelListener != null
           || (c.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
           || (c.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
           || (c.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0;
  }

  /**
   * Tracks MOUSE_ENTERED and MOUSE_EXIT as well as MOUSE_MOVED and
   * MOUSE_DRAGGED and creates synthetic MOUSE_ENTERED and MOUSE_EXITED for
   * lightweight component.s
   *
   * @param target the current mouse event target
   * @param ev the mouse event
   */
  private void trackEnterExit(final Component target, final MouseEvent ev)
  {
    int id = ev.getID();
    if (target != lastTarget)
      {
        if (lastTarget != null)
          redispatch(ev, lastTarget, MouseEvent.MOUSE_EXITED);
        if (id == MouseEvent.MOUSE_EXITED)
          ev.consume();
        if (target != null)
          redispatch(ev, target, MouseEvent.MOUSE_ENTERED);
        if (id == MouseEvent.MOUSE_ENTERED)
          ev.consume();
        lastTarget = target;
      }

  }

  /**
   * Redispatches the specified mouse event to the specified target with the
   * specified id.
   *
   * @param ev the mouse event
   * @param target the new target
   * @param id the new id
   */
  private void redispatch(MouseEvent ev, Component target, int id)
  {
    Component source = ev.getComponent();
    assert target != null;
    if (target.isShowing())
      {
        // Translate coordinates.
        int x = ev.getX();
        int y = ev.getY();
        for (Component c = target; c != null && c != source; c = c.getParent())
          {
            x -= c.x;
            y -= c.y;
          }

        // Retarget event.
        MouseEvent retargeted;
        if (id == MouseEvent.MOUSE_WHEEL)
          {
            MouseWheelEvent mwe = (MouseWheelEvent) ev;
            retargeted = new MouseWheelEvent(target, id, ev.getWhen(),
                                             ev.getModifiers()
                                             | ev.getModifiersEx(), x, y,
                                             ev.getClickCount(),
                                             ev.isPopupTrigger(),
                                             mwe.getScrollType(),
                                             mwe.getScrollAmount(),
                                             mwe.getWheelRotation());
          }
        else
          {
            retargeted = new MouseEvent(target, id, ev.getWhen(),
                                       ev.getModifiers() | ev.getModifiersEx(),
                                       x, y, ev.getClickCount(),
                                       ev.isPopupTrigger(), ev.getButton());
          }

        if (target == source)
          ((Container) target).dispatchNoLightweight(retargeted);
        else
          target.dispatchEvent(retargeted);
      }
  }

  /**
   * Determines if we are in the middle of a drag operation, that is, if
   * any of the buttons is held down.
   *
   * @param ev the mouse event to check
   *
   * @return <code>true</code> if we are in the middle of a drag operation,
   *         <code>false</code> otherwise
   */
  private boolean isDragging(MouseEvent ev)
  {
    int mods = ev.getModifiersEx();
    int id = ev.getID();
    if (id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_RELEASED)
      {
        switch (ev.getButton())
          {
            case MouseEvent.BUTTON1:
              mods ^= InputEvent.BUTTON1_DOWN_MASK;
              break;
            case MouseEvent.BUTTON2:
              mods ^= InputEvent.BUTTON2_DOWN_MASK;
              break;
            case MouseEvent.BUTTON3:
              mods ^= InputEvent.BUTTON3_DOWN_MASK;
              break;
          }
      }
    return (mods & (InputEvent.BUTTON1_DOWN_MASK
                    | InputEvent.BUTTON2_DOWN_MASK
                    | InputEvent.BUTTON3_DOWN_MASK)) != 0;
  }
}
