Home » openjdk-7 » java » awt » [javadoc | source]

    1   /* LightweightDispatcher.java -- Dispatches mouse events to lightweights
    2      Copyright (C) 2006 Free Software Foundation, Inc.
    3   
    4   This file is part of GNU Classpath.
    5   
    6   GNU Classpath is free software; you can redistribute it and/or modify
    7   it under the terms of the GNU General Public License as published by
    8   the Free Software Foundation; either version 2, or (at your option)
    9   any later version.
   10   
   11   GNU Classpath is distributed in the hope that it will be useful, but
   12   WITHOUT ANY WARRANTY; without even the implied warranty of
   13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14   General Public License for more details.
   15   
   16   You should have received a copy of the GNU General Public License
   17   along with GNU Classpath; see the file COPYING.  If not, write to the
   18   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   19   02110-1301 USA.
   20   
   21   Linking this library statically or dynamically with other modules is
   22   making a combined work based on this library.  Thus, the terms and
   23   conditions of the GNU General Public License cover the whole
   24   combination.
   25   
   26   As a special exception, the copyright holders of this library give you
   27   permission to link this library with independent modules to produce an
   28   executable, regardless of the license terms of these independent
   29   modules, and to copy and distribute the resulting executable under
   30   terms of your choice, provided that you also meet, for each linked
   31   independent module, the terms and conditions of the license of that
   32   module.  An independent module is a module which is not derived from
   33   or based on this library.  If you modify this library, you may extend
   34   this exception to your version of the library, but you are not
   35   obligated to do so.  If you do not wish to do so, delete this
   36   exception statement from your version. */
   37   
   38   
   39   package java.awt;
   40   
   41   import gnu.java.awt.AWTUtilities;
   42   
   43   import java.awt.event.MouseEvent;
   44   import java.util.WeakHashMap;
   45   
   46   /**
   47    * Redispatches mouse events to lightweight components. The native peers know
   48    * nothing about the lightweight components and thus mouse events are always
   49    * targetted at Windows or heavyweight components. This class listenes directly
   50    * on the eventqueue and dispatches mouse events to lightweight components.
   51    *
   52    * @author Roman Kennke (kennke@aicas.com)
   53    */
   54   class LightweightDispatcher
   55   {
   56   
   57     /**
   58      * Maps thread groups to lightweight dispatcher instances. We need to
   59      * have one instance per thread group so that 2 or more applets or otherwise
   60      * separated applications (like in OSGI) do not interfer with each other.
   61      */
   62     private static WeakHashMap instances = new WeakHashMap();
   63   
   64     /**
   65      * The component that is the start of a mouse dragging. All MOUSE_DRAGGED
   66      * events that follow the initial press must have the source set to this,
   67      * as well as the MOUSE_RELEASED event following the dragging.
   68      */
   69     private Component dragTarget;
   70   
   71     /**
   72      * The last mouse event target. If the target changes, additional
   73      * MOUSE_ENTERED and MOUSE_EXITED events must be dispatched.
   74      */
   75     private Component lastTarget;
   76   
   77     /**
   78      * Returns an instance of LightweightDispatcher for the current thread's
   79      * thread group.
   80      *
   81      * @return an instance of LightweightDispatcher for the current thread's
   82      *         thread group
   83      */
   84     static LightweightDispatcher getInstance()
   85     {
   86       Thread t = Thread.currentThread();
   87       ThreadGroup tg = t.getThreadGroup();
   88       LightweightDispatcher instance = (LightweightDispatcher) instances.get(tg);
   89       if (instance == null)
   90         {
   91           instance = new LightweightDispatcher();
   92           instances.put(tg, instance);
   93         }
   94       return instance;
   95     }
   96   
   97     /**
   98      * Creates a new LightweightDispatcher. This is private to prevent access
   99      * from outside. Use {@link #getInstance()} instead.
  100      */
  101     private LightweightDispatcher()
  102     {
  103       // Nothing to do here.
  104     }
  105     
  106     /**
  107      * Receives notification if a mouse event passes along the eventqueue.
  108      *
  109      * @param event the event
  110      */
  111     public boolean dispatchEvent(AWTEvent event)
  112     {
  113       if (event instanceof MouseEvent && event.getSource() instanceof Window)
  114         {
  115           MouseEvent mouseEvent = (MouseEvent) event;
  116           return handleMouseEvent(mouseEvent);
  117         }
  118       return false;
  119     }
  120   
  121     /**
  122      * Handles all mouse events that are targetted at toplevel containers
  123      * (Window instances) and dispatches them to the correct lightweight child.
  124      *
  125      * @param ev the mouse event
  126      * @return whether or not we found a lightweight that handled the event.
  127      */
  128     private boolean handleMouseEvent(MouseEvent ev)
  129     {
  130       Window window = (Window) ev.getSource();
  131       Component target = window.findComponentAt(ev.getX(), ev.getY());
  132       target = findTarget(target);
  133       if (target == null || target.isLightweight())
  134         {
  135           // Dispatch additional MOUSE_EXITED and MOUSE_ENTERED if event target
  136           // is different from the last event target.
  137           if (target != lastTarget)
  138             {
  139               if (lastTarget != null)
  140                 {
  141                   Point p1 = AWTUtilities.convertPoint(window, ev.getX(),
  142                                                        ev.getY(), lastTarget);
  143                   MouseEvent mouseExited =
  144                     new MouseEvent(lastTarget, MouseEvent.MOUSE_EXITED,
  145                                    ev.getWhen(), ev.getModifiers(), p1.x, p1.y,
  146                                    ev.getClickCount(), ev.isPopupTrigger());
  147                   lastTarget.dispatchEvent(mouseExited);
  148                 }
  149               if (target != null)
  150                 {
  151                   Point p = AWTUtilities.convertPoint(window, ev.getX(), ev.getY(),
  152                                                       target);
  153                   MouseEvent mouseEntered =
  154                     new MouseEvent(target, MouseEvent.MOUSE_ENTERED, ev.getWhen(),
  155                                    ev.getModifiers(), p.x, p.y, ev.getClickCount(),
  156                                    ev.isPopupTrigger());
  157                   target.dispatchEvent(mouseEntered);
  158                 }
  159             }
  160           
  161           switch (ev.getID())
  162           {
  163             case MouseEvent.MOUSE_PRESSED:
  164               dragTarget = target;
  165               break;
  166             case MouseEvent.MOUSE_RELEASED:
  167               if (dragTarget != null)
  168                 target = dragTarget;
  169               dragTarget = null;
  170               break;
  171             case MouseEvent.MOUSE_CLICKED:
  172               // When we receive a MOUSE_CLICKED, we set the target to the
  173               // previous target, which must have been a MOUSE_RELEASED event.
  174               // This is necessary for the case when the MOUSE_RELEASED has
  175               // caused the original target (like an internal component) go
  176               // away.
  177               target = lastTarget;
  178               break;
  179             case MouseEvent.MOUSE_DRAGGED:
  180               target = dragTarget;
  181               break;
  182             default:
  183               // Do nothing in other cases.
  184               break;
  185           }
  186   
  187           lastTarget = target;
  188   
  189           if (target != null)
  190             {
  191               Point targetCoordinates =
  192                 AWTUtilities.convertPoint(window, ev.getX(), ev.getY(), target);
  193               int dx = targetCoordinates.x - ev.getX();
  194               int dy = targetCoordinates.y - ev.getY();
  195               ev.translatePoint(dx, dy);
  196               ev.setSource(target);
  197               target.dispatchEvent(ev);
  198               // We reset the event, so that the normal event dispatching is not
  199               // influenced by this modified event.
  200               ev.setSource(window);
  201               ev.translatePoint(-dx, -dy);
  202             }
  203   
  204   	return true;
  205         }
  206       else
  207         return false;
  208     }
  209   
  210     /**
  211      * Finds the actual target for a mouseevent, starting at <code>c</code>.
  212      * This searches upwards the component hierarchy until it finds a component
  213      * that has a mouselistener attached.
  214      *
  215      * @param c the component to start searching from
  216      *
  217      * @return the actual receiver of the mouse event
  218      */
  219     private Component findTarget(Component c)
  220     {
  221       Component target = c;
  222       while (target != null && target.getMouseListeners().length == 0)
  223         {
  224           target = target.getParent();
  225         }
  226       return target;
  227     }
  228   }

Home » openjdk-7 » java » awt » [javadoc | source]