001: /*
002: * MouseTracker.java
003: *
004: * Created on November 28, 2006, 7:49 AM
005: *
006: * Copyright 2006-2007 Nigel Hughes
007: *
008: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
009: * in compliance with the License. You may obtain a copy of the License at http://www.apache.org/
010: * licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
012: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
013: * governing permissions and limitations under the License.
014: */
015:
016: package com.blogofbug.swing.delegates;
017:
018: import java.awt.Component;
019: import java.awt.Container;
020: import java.awt.Point;
021: import java.awt.event.ContainerEvent;
022: import java.awt.event.ContainerListener;
023: import java.awt.event.MouseEvent;
024: import java.awt.event.MouseListener;
025: import java.awt.event.MouseMotionListener;
026: import java.util.LinkedList;
027:
028: /**
029: * A class which abstracts away some of the complexity of a mouse listener meaning that listeners (See MouseTrackerListener) need to implement fewer methods.
030: * Furthermore, unlike a normal mouse listener it still considers the mouse to be inside
031: * even if it is over a component inside a container, and will translate the co-ordintates to be
032: * relative to the "listened to" component
033: * @author nigel
034: */
035: public class MouseTracker implements ContainerListener, MouseListener,
036: MouseMotionListener {
037: /**
038: * The lisetners
039: */
040: protected LinkedList<MouseTrackerListener> clients = new LinkedList<MouseTrackerListener>();
041: /**
042: * The component being tracked
043: */
044: protected Component component;
045: /**
046: * True if the mouse is inside
047: */
048: protected boolean mouseInside = false;
049: /**
050: * The last known position
051: */
052: protected Point position = new Point(0, 0);
053:
054: /**
055: * Adds a mouse tracker to the specified component
056: *
057: * @param component the component to track
058: */
059: public MouseTracker(Component component) {
060: this .component = component;
061: initialize();
062: }
063:
064: /**
065: * Retreives the point position, returns null if the pointer is outside the
066: * component
067: *
068: * @return The pointer position or null if the pointer is not inside the tracked object
069: */
070: public Point getPosition() {
071: if (!mouseInside) {
072: return null;
073: }
074: return position;
075: }
076:
077: /**
078: * Determines if the mouse is inside the tracked component
079: *
080: * @return true if it is, false if it isn't
081: */
082: public boolean isMouseInside() {
083: return mouseInside;
084: }
085:
086: /**
087: * Adds a mouse tracker to the specified component, and adds the specified
088: * listener
089: *
090: * @param component The component to track
091: * @param client A listener
092: */
093: public MouseTracker(Component component, MouseTrackerListener client) {
094: this (component);
095: addListener(client);
096: }
097:
098: /**
099: * Adds a listener to the MouseTracker. The listener will get all of the mouse
100: * tracker events
101: *
102: * @param client The listener
103: */
104: public void addListener(MouseTrackerListener client) {
105: if (clients.contains(client)) {
106: return;
107: }
108: clients.addLast(client);
109: }
110:
111: /**
112: * Removes a listener from the listener list
113: *
114: * @param client the listener to remove from the list
115: */
116: public void removeListener(MouseTrackerListener client) {
117: clients.remove(client);
118: }
119:
120: /**
121: * Adds mouse listeners to the component. If the component is also a container
122: * adds itself as a container listener so it can track added components also
123: */
124: private void initialize() {
125: component.addMouseListener(this );
126: component.addMouseMotionListener(this );
127: if (component instanceof Container) {
128: ((Container) component).addContainerListener(this );
129: }
130: }
131:
132: /**
133: * NOT USED
134: * @param e Mouse Event
135: */
136: public void mouseClicked(MouseEvent e) {
137: }
138:
139: /**
140: * NOT USED
141: * @param e Mouse Event
142: */
143: public void mousePressed(MouseEvent e) {
144: }
145:
146: /**
147: * NOT USED
148: * @param e Mouse Event
149: */
150: public void mouseReleased(MouseEvent e) {
151: }
152:
153: /**
154: * Tracks when the mouse moves into the component
155: * @param e Mouse Event
156: */
157: public void mouseEntered(MouseEvent e) {
158: if (!mouseInside) {
159: mouseInside = true;
160: for (MouseTrackerListener listener : clients) {
161: listener.mouseCrossThreshold(true);
162: }
163: }
164: }
165:
166: /**
167: * Called when the mouse has been determined to have REALLY exited the component
168: */
169: protected void mouseExited() {
170: mouseInside = false;
171: for (MouseTrackerListener listener : clients) {
172: listener.mouseCrossThreshold(false);
173: }
174: }
175:
176: /**
177: * Captures the exit event and checks to see if the compnent is a container. If it's
178: * not it just passes on the event, otherwise the event is only passed on if the
179: * component the mouse is now over is not contained in the container.
180: * @param e Mouse Event
181: */
182: public void mouseExited(MouseEvent e) {
183: if (mouseInside) {
184: if (component instanceof Container) {
185: if (((Container) component)
186: .getComponentAt(e.getPoint()) == null) {
187: mouseExited();
188: }
189: } else {
190: if (e.getSource() == component) {
191: mouseExited();
192: }
193: }
194: }
195: }
196:
197: /**
198: * NOT USED
199: * @param e Mouse Event
200: */
201: public void mouseDragged(MouseEvent e) {
202: }
203:
204: /**
205: * When the mouse moves within the component, or one of the contained componets
206: * determines the point within the tracked component and passes that on to the
207: * listeners.
208: * @param e Mouse Event
209: */
210: public void mouseMoved(MouseEvent e) {
211: Point p = e.getPoint();
212: //If it's not in the container, but one of the contained objects then
213: //tranlate the point to container relative co-ordinates
214:
215: if (e.getSource() != component) {
216: Component comp = (Component) e.getSource();
217: int dx = p.x;
218: int dy = p.y;
219: //Should be modified by where it is inside the component
220: comp.getLocation(p);
221: p.x += dx;
222: p.y += dy;
223: }
224:
225: //Notify all of the listeners
226: for (MouseTrackerListener listener : clients) {
227: listener.mouseMoved(p);
228: }
229: }
230:
231: /**
232: * Adds a mouseMotion listener to the added component
233: * @param e The event when something is added
234: */
235: public void componentAdded(ContainerEvent e) {
236: e.getChild().addMouseMotionListener(this );
237: e.getChild().addMouseListener(this );
238: }
239:
240: /**
241: * Removes the mouseMotion listener from the removed component
242: * @param e
243: */
244: public void componentRemoved(ContainerEvent e) {
245: e.getChild().removeMouseMotionListener(this);
246: e.getChild().addMouseListener(this);
247: }
248:
249: }
|