001: /*
002: * GlassCapturePanel.java
003: *
004: * Created on 15 June 2006, 01:49
005: *
006: * To change this template, choose Tools | Template Manager
007: * and open the template in the editor.
008: */
009:
010: package org.underworldlabs.swing;
011:
012: import java.awt.Component;
013: import java.awt.Container;
014: import java.awt.Point;
015: import java.awt.event.MouseEvent;
016: import java.awt.event.MouseWheelEvent;
017: import java.awt.event.MouseWheelListener;
018: import java.util.ArrayList;
019: import java.util.List;
020: import javax.swing.JPanel;
021: import javax.swing.SwingUtilities;
022: import javax.swing.event.MouseInputListener;
023:
024: /**
025: *
026: * @author Takis Diakoumis
027: * @version $Revision: 1.2 $
028: * @date $Date: 2006/06/14 16:49:33 $
029: */
030: public class GlassCapturePanel extends JPanel implements
031: MouseInputListener, MouseWheelListener {
032:
033: /** The primary component */
034: protected Container mainComponent;
035:
036: private List<GlassPaneSelectionListener> listeners;
037:
038: /** Creates a new instance of GlassCapturePanel */
039: public GlassCapturePanel(Container mainComponent) {
040: this .mainComponent = mainComponent;
041: addMouseMotionListener(this );
042: addMouseListener(this );
043: addMouseWheelListener(this );
044: setOpaque(false);
045: }
046:
047: public void removeGlassPaneSelectionListener(
048: GlassPaneSelectionListener listener) {
049: if (listeners == null) {
050: return;
051: }
052: listeners.remove(listener);
053: }
054:
055: public void addGlassPaneSelectionListener(
056: GlassPaneSelectionListener listener) {
057: if (listeners == null) {
058: listeners = new ArrayList<GlassPaneSelectionListener>();
059: }
060: listeners.add(listener);
061: }
062:
063: private Component mouseEventTarget = null;
064: private Component dragSource = null;
065:
066: public void mouseWheelMoved(MouseWheelEvent e) {
067: forwardMouseEvent(e);
068: }
069:
070: /**
071: * When inactive, mouse events are forwarded as appropriate either to
072: * the UI to activate the frame or to the underlying child component.
073: */
074: public void mousePressed(MouseEvent e) {
075: forwardMouseEvent(e);
076: }
077:
078: /**
079: * Forward the mouseEntered event to the underlying child container.
080: * @see #mousePressed
081: */
082: public void mouseEntered(MouseEvent e) {
083: forwardMouseEvent(e);
084: }
085:
086: /**
087: * Forward the mouseMoved event to the underlying child container.
088: * @see #mousePressed
089: */
090: public void mouseMoved(MouseEvent e) {
091: forwardMouseEvent(e);
092: }
093:
094: /**
095: * Forward the mouseExited event to the underlying child container.
096: * @see #mousePressed
097: */
098: public void mouseExited(MouseEvent e) {
099: forwardMouseEvent(e);
100: }
101:
102: /**
103: * Ignore mouseClicked events.
104: * @see #mousePressed
105: */
106: public void mouseClicked(MouseEvent e) {
107: forwardMouseEvent(e);
108: }
109:
110: /**
111: * Forward the mouseReleased event to the underlying child container.
112: * @see #mousePressed
113: */
114: public void mouseReleased(MouseEvent e) {
115: forwardMouseEvent(e);
116: }
117:
118: /**
119: * Forward the mouseDragged event to the underlying child container.
120: * @see #mousePressed
121: */
122: public void mouseDragged(MouseEvent e) {
123: forwardMouseEvent(e);
124: }
125:
126: /**
127: * Forward a mouse event to the current mouse target, setting it
128: * if necessary.
129: */
130: private void forwardMouseEvent(MouseEvent e) {
131: Component target = findComponentAt(mainComponent, e.getX(), e
132: .getY());
133:
134: int id = e.getID();
135:
136: if (e instanceof MouseWheelEvent) {
137: if (target == null) {
138: return;
139: }
140:
141: MouseWheelEvent wheelEvent = (MouseWheelEvent) e;
142:
143: // do the retarget here - not a focus event
144: if (target != mouseEventTarget) {
145: mouseEventTarget = target;
146: }
147:
148: Point p = SwingUtilities.convertPoint(mainComponent, e
149: .getX(), e.getY(), target);
150:
151: MouseWheelEvent retargeted = new MouseWheelEvent(target,
152: id, e.getWhen(), wheelEvent.getModifiers()
153: | wheelEvent.getModifiersEx(), p.x, p.y,
154: wheelEvent.getClickCount(), wheelEvent
155: .isPopupTrigger(), wheelEvent
156: .getScrollType(), wheelEvent
157: .getScrollAmount(), wheelEvent
158: .getWheelRotation());
159:
160: target.dispatchEvent(retargeted);
161:
162: }
163:
164: switch (id) {
165: case MouseEvent.MOUSE_ENTERED:
166:
167: if (target != mouseEventTarget) {
168: mouseEventTarget = target;
169: }
170:
171: retargetMouseEvent(id, e, mouseEventTarget);
172: break;
173:
174: case MouseEvent.MOUSE_PRESSED:
175:
176: if (target != mouseEventTarget) {
177: mouseEventTarget = target;
178: }
179:
180: retargetMouseEvent(id, e, mouseEventTarget);
181: // Set the drag source in case we start dragging.
182: dragSource = target;
183: break;
184:
185: case MouseEvent.MOUSE_EXITED:
186: retargetMouseEvent(id, e, mouseEventTarget);
187: break;
188:
189: case MouseEvent.MOUSE_CLICKED:
190: retargetMouseEvent(id, e, mouseEventTarget);
191: break;
192:
193: case MouseEvent.MOUSE_MOVED:
194:
195: if (target != mouseEventTarget) {
196: retargetMouseEvent(MouseEvent.MOUSE_EXITED, e,
197: mouseEventTarget);
198: mouseEventTarget = target;
199: retargetMouseEvent(MouseEvent.MOUSE_ENTERED, e,
200: mouseEventTarget);
201: }
202:
203: retargetMouseEvent(id, e, mouseEventTarget);
204: break;
205:
206: case MouseEvent.MOUSE_DRAGGED:
207: retargetMouseEvent(id, e, dragSource);
208: break;
209:
210: case MouseEvent.MOUSE_RELEASED:
211: retargetMouseEvent(id, e, mouseEventTarget);
212: break;
213:
214: }
215:
216: // notify listeners of the selection
217: if (listeners != null) {
218:
219: for (int i = 0, n = listeners.size(); i < n; i++) {
220: listeners.get(i).glassPaneSelected(e);
221: }
222:
223: }
224:
225: }
226:
227: /*
228: * Find the lightweight child component which corresponds to the
229: * specified location. This is similar to the new 1.2 API in
230: * Container, but we need to run on 1.1. The other changes are
231: * due to Container.findComponentAt's use of package-private data.
232: */
233: private Component findComponentAt(Container c, int x, int y) {
234:
235: if (!c.contains(x, y)) {
236: return c;
237: }
238:
239: int ncomponents = c.getComponentCount();
240: Component component[] = c.getComponents();
241:
242: for (int i = 0; i < ncomponents; i++) {
243: Component comp = component[i];
244: Point loc = comp.getLocation();
245:
246: if ((comp != null) && (comp.contains(x - loc.x, y - loc.y))
247: &&
248: //(comp.getPeer() instanceof java.awt.peer.LightweightPeer) &&
249: comp.isDisplayable() && comp.isVisible()) {
250:
251: // found a component that intersects the point, see if there
252: // is a deeper possibility.
253: if (comp instanceof Container) {
254:
255: Container child = (Container) comp;
256: Point childLoc = child.getLocation();
257: Component deeper = findComponentAt(child, x
258: - childLoc.x, y - childLoc.y);
259:
260: if (deeper != null) {
261: return deeper;
262: }
263:
264: } else {
265: return comp;
266: }
267:
268: }
269:
270: }
271:
272: return c;
273: }
274:
275: /*
276: * Dispatch an event clone, retargeted for the specified target.
277: */
278: protected void retargetMouseEvent(int id, MouseEvent e,
279: Component target) {
280:
281: if (target == null) {
282: return;
283: }
284:
285: Point p = SwingUtilities.convertPoint(mainComponent, e.getX(),
286: e.getY(), target);
287:
288: MouseEvent retargeted = new MouseEvent(target, id, e.getWhen(),
289: e.getModifiers() | e.getModifiersEx(), p.x, p.y, e
290: .getClickCount(), e.isPopupTrigger());
291:
292: target.dispatchEvent(retargeted);
293: }
294:
295: /**
296: * Returns the components below this glass pane.
297: */
298: public Container getComponentBelow() {
299: return mainComponent;
300: }
301:
302: }
|