Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / java / awt / LightweightDispatcher.java
blob6573b128ec45254b1379f609c2efc3a7be44a27a
1 /* LightweightDispatcher.java -- Dispatches mouse events to lightweights
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package java.awt;
41 import gnu.java.awt.AWTUtilities;
43 import java.awt.event.MouseEvent;
44 import java.util.WeakHashMap;
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.
52 * @author Roman Kennke (kennke@aicas.com)
54 class LightweightDispatcher
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.
62 private static WeakHashMap instances = new WeakHashMap();
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.
69 private Component dragTarget;
71 /**
72 * The last mouse event target. If the target changes, additional
73 * MOUSE_ENTERED and MOUSE_EXITED events must be dispatched.
75 private Component lastTarget;
77 /**
78 * Returns an instance of LightweightDispatcher for the current thread's
79 * thread group.
81 * @return an instance of LightweightDispatcher for the current thread's
82 * thread group
84 static LightweightDispatcher getInstance()
86 Thread t = Thread.currentThread();
87 ThreadGroup tg = t.getThreadGroup();
88 LightweightDispatcher instance = (LightweightDispatcher) instances.get(tg);
89 if (instance == null)
91 instance = new LightweightDispatcher();
92 instances.put(tg, instance);
94 return instance;
97 /**
98 * Creates a new LightweightDispatcher. This is private to prevent access
99 * from outside. Use {@link #getInstance()} instead.
101 private LightweightDispatcher()
103 // Nothing to do here.
107 * Receives notification if a mouse event passes along the eventqueue.
109 * @param event the event
111 public boolean dispatchEvent(AWTEvent event)
113 boolean dispatched = false;
114 if (event instanceof MouseEvent && event.getSource() instanceof Window)
116 MouseEvent mouseEvent = (MouseEvent) event;
117 handleMouseEvent(mouseEvent);
118 dispatched = true;
120 return dispatched;
124 * Handles all mouse events that are targetted at toplevel containers
125 * (Window instances) and dispatches them to the correct lightweight child.
127 * @param ev the mouse event
129 private void handleMouseEvent(MouseEvent ev)
131 Window window = (Window) ev.getSource();
132 Component target = window.findComponentAt(ev.getX(), ev.getY());
133 if (target != null && target.isLightweight())
135 // Dispatch additional MOUSE_EXITED and MOUSE_ENTERED if event target
136 // is different from the last event target.
137 if (target != lastTarget)
139 if (lastTarget != null)
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);
149 Point p = AWTUtilities.convertPoint(window, ev.getX(), ev.getY(),
150 target);
151 MouseEvent mouseEntered =
152 new MouseEvent(target, MouseEvent.MOUSE_ENTERED, ev.getWhen(),
153 ev.getModifiers(), p.x, p.y, ev.getClickCount(),
154 ev.isPopupTrigger());
155 target.dispatchEvent(mouseEntered);
158 switch (ev.getID())
160 case MouseEvent.MOUSE_PRESSED:
161 dragTarget = target;
162 break;
163 case MouseEvent.MOUSE_RELEASED:
164 if (dragTarget != null)
165 target = dragTarget;
166 dragTarget = null;
167 break;
168 case MouseEvent.MOUSE_CLICKED:
169 // When we receive a MOUSE_CLICKED, we set the target to the
170 // previous target, which must have been a MOUSE_RELEASED event.
171 // This is necessary for the case when the MOUSE_RELEASED has
172 // caused the original target (like an internal component) go
173 // away.
174 target = lastTarget;
175 break;
176 case MouseEvent.MOUSE_DRAGGED:
177 target = dragTarget;
178 break;
179 default:
180 // Do nothing in other cases.
181 break;
184 lastTarget = target;
186 Point targetCoordinates =
187 AWTUtilities.convertPoint(window, ev.getX(), ev.getY(), target);
188 int dx = targetCoordinates.x - ev.getX();
189 int dy = targetCoordinates.y - ev.getY();
190 ev.translatePoint(dx, dy);
191 ev.setSource(target);
192 target.dispatchEvent(ev);
194 // We reset the event, so that the normal event dispatching is not
195 // influenced by this modified event.
196 ev.setSource(window);
197 ev.translatePoint(-dx, -dy);