001: /*
002: * uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004,
003: * Refractions Research Inc. This library is free software; you can redistribute it and/or modify it
004: * under the terms of the GNU Lesser General Public License as published by the Free Software
005: * Foundation; version 2.1 of the License. This library is distributed in the hope that it will be
006: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
007: * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
008: */
009: package net.refractions.udig.project.ui.internal.render.displayAdapter.impl;
010:
011: import java.util.concurrent.CopyOnWriteArraySet;
012:
013: import net.refractions.udig.project.render.displayAdapter.IMapDisplayListener;
014: import net.refractions.udig.project.render.displayAdapter.MapDisplayEvent;
015: import net.refractions.udig.project.ui.internal.ProjectUIPlugin;
016: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseEvent;
017: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseListener;
018: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseMotionListener;
019: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseWheelEvent;
020: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseWheelListener;
021:
022: import org.eclipse.swt.widgets.Display;
023:
024: public class EventJob {
025:
026: private CopyOnWriteArraySet<IMapDisplayListener> paneListener = new CopyOnWriteArraySet<IMapDisplayListener>();
027: private CopyOnWriteArraySet<MapMouseWheelListener> wheel = new CopyOnWriteArraySet<MapMouseWheelListener>();
028: private CopyOnWriteArraySet<MapMouseMotionListener> motion = new CopyOnWriteArraySet<MapMouseMotionListener>();
029: private CopyOnWriteArraySet<MapMouseListener> mouse = new CopyOnWriteArraySet<MapMouseListener>();
030:
031: public static final int DOUBLE_CLICK = 1;
032: public static final int PRESSED = 2;
033: public static final int RELEASED = 3;
034: public static final int MOVED = 4;
035: public static final int DRAGGED = 5;
036: public static final int ENTERED = 6;
037: public static final int EXITED = 7;
038: public static final int WHEEL = 8;
039: public static final int RESIZED = 9;
040: public static final int HOVERED = 10;
041:
042: /**
043: * fires an event to all listeners. If an event is being processed then the new one is ignored
044: * because some event take a while to process.
045: *
046: * @param type the type of the event
047: * @param event the event data object
048: */
049: public void fire(int type, Object event) {
050: Event event1 = new Event(type, event);
051: if (event1.type == PRESSED || next != null) {
052: tryForDoubleClick(event1);
053: } else {
054: runEvent(event1);
055: }
056: }
057:
058: private static class Event {
059: final int type;
060: final Object data;
061:
062: Event(int type, Object event) {
063: this .type = type;
064: this .data = event;
065: }
066: }
067:
068: /**
069: * Dispatch events. Usually 1 but sometimes (in the case of an aborted double click) it can be more.
070: *
071: * @param event2 events to send
072: */
073: private void runEvent(Event... event2) {
074: for (Event event : event2) {
075: if (event == null)
076: continue;
077: try {
078: switch (event.type) {
079: case DOUBLE_CLICK: {
080: sendDoubleClickEvent(event);
081: break;
082: }
083: case PRESSED: {
084: sendMousePressedEvent(event);
085: break;
086: }
087: case RELEASED: {
088: sendMouseReleased(event);
089: break;
090: }
091: case MOVED: {
092: sendMouseMoved(event);
093: break;
094: }
095: case DRAGGED: {
096: sendMouseDragged(event);
097: break;
098: }
099: case ENTERED: {
100: sendMouseEntered(event);
101: break;
102: }
103: case EXITED: {
104: sendMouseExited(event);
105: break;
106: }
107: case WHEEL: {
108: sendMouseWheel(event);
109: break;
110: }
111: case RESIZED: {
112: sendResized(event);
113: break;
114: }
115: case HOVERED: {
116: sendHovered(event);
117: break;
118: }
119: default:
120: System.err
121: .println("Event requested that does not exist " + event.type); //$NON-NLS-1$
122: }
123: } catch (Throwable t) {
124: ProjectUIPlugin.log("", t); //$NON-NLS-1$
125: }
126: }
127: }
128:
129: private DoubleClickAttempt next = null;
130:
131: private final Runnable checkDoubleClick = new Runnable() {
132:
133: public void run() {
134: if (next == null)
135: return;
136: DoubleClickAttempt e = next;
137: next = null;
138: runEvent(e.first, e.release, e.third);
139: }
140:
141: };
142:
143: /**
144: * Waits to see if the next series of events is a double-click event.
145: *
146: * @param event
147: * @return
148: * @return
149: * @throws InterruptedException
150: */
151: private void tryForDoubleClick(Event event) {
152: if (next == null) {
153: next = new DoubleClickAttempt();
154: next.first = event;
155: Display.getCurrent().timerExec(
156: ProjectUIPlugin.getDefault().getDoubleClickSpeed(),
157: checkDoubleClick);
158: } else {
159: if (next.release == null) {
160: if (event.type == RELEASED) {
161:
162: next.release = event;
163: return;
164: } else {
165: Event first = next.first;
166: next = null;
167: runEvent(first, event);
168: }
169: } else {
170: switch (event.type) {
171: case RELEASED:
172: if (next.third != null) {
173: next = null;
174: sendDoubleClickEvent(new Event(DOUBLE_CLICK,
175: event.data));
176: return;
177: }
178: cancelDoubleClickWait(event);
179: break;
180: case PRESSED:
181: if (next.release != null && next.third == null) {
182: next.third = event;
183: } else {
184: cancelDoubleClickWait(event);
185: }
186: break;
187: default:
188: cancelDoubleClickWait(event);
189: break;
190: }
191: }
192: }
193: }
194:
195: /**
196: *
197: * @param event
198: */
199: private void cancelDoubleClickWait(Event event) {
200: Event first = next.first;
201: Event release = next.release;
202: Event third = next.third;
203: next = null;
204: runEvent(first, release, third, event);
205: }
206:
207: /**
208: * @param event
209: */
210: private void sendResized(Event event) {
211: for (IMapDisplayListener l : this .paneListener) {
212: try {
213: l.sizeChanged((MapDisplayEvent) event.data);
214: } catch (Throwable t) {
215: ProjectUIPlugin.log(
216: "Error processing a resized event", t);//$NON-NLS-1$
217: }
218: }
219: }
220:
221: /**
222: * @param event
223: */
224: private void sendMouseWheel(Event event) {
225: for (MapMouseWheelListener l : this .wheel) {
226: try {
227: l.mouseWheelMoved((MapMouseWheelEvent) event.data);
228: } catch (Throwable t) {
229: ProjectUIPlugin.log(
230: "Error processing a mouse wheel event", t);//$NON-NLS-1$
231: }
232: }
233: }
234:
235: /**
236: * @param event
237: */
238: private void sendMouseExited(Event event) {
239: for (MapMouseListener l : this .mouse) {
240: try {
241: l.mouseExited((MapMouseEvent) event.data);
242: } catch (Throwable t) {
243: ProjectUIPlugin.log(
244: "Error processing a moouse exited event", t);//$NON-NLS-1$
245: }
246: }
247: }
248:
249: /**
250: * @param event
251: */
252: private void sendHovered(Event event) {
253: for (MapMouseMotionListener l : this .motion) {
254: try {
255: l.mouseHovered((MapMouseEvent) event.data);
256: } catch (Throwable t) {
257: ProjectUIPlugin.log(
258: "Error processing a mouse dragged event", t);//$NON-NLS-1$
259: }
260: }
261: }
262:
263: /**
264: * @param event
265: */
266: private void sendMouseEntered(Event event) {
267: for (MapMouseListener l : this .mouse) {
268: try {
269: l.mouseEntered((MapMouseEvent) event.data);
270: } catch (Throwable t) {
271: ProjectUIPlugin.log(
272: "Error processing a mouse entered event", t);//$NON-NLS-1$
273: }
274: }
275: }
276:
277: /**
278: * @param event
279: */
280: private void sendMouseDragged(Event event) {
281: for (MapMouseMotionListener l : this .motion) {
282: try {
283: l.mouseDragged((MapMouseEvent) event.data);
284: } catch (Throwable t) {
285: ProjectUIPlugin.log(
286: "Error processing a mouse dragged event", t);//$NON-NLS-1$
287: }
288: }
289: }
290:
291: /**
292: * @param event
293: */
294: private void sendMouseMoved(Event event) {
295: for (MapMouseMotionListener l : this .motion) {
296: try {
297: l.mouseMoved((MapMouseEvent) event.data);
298: } catch (Throwable t) {
299: ProjectUIPlugin.log(
300: "Error processing a mouse dragged event", t);//$NON-NLS-1$
301: }
302: }
303: }
304:
305: /**
306: * @param event
307: */
308: private void sendMouseReleased(Event event) {
309: for (MapMouseListener l : this .mouse) {
310: try {
311: l.mouseReleased((MapMouseEvent) event.data);
312: } catch (Throwable t) {
313: ProjectUIPlugin.log(
314: "Error processing a mouse released event", t);//$NON-NLS-1$
315: }
316: }
317: }
318:
319: /**
320: * @param event
321: */
322: private void sendMousePressedEvent(Event event) {
323: for (MapMouseListener l : this .mouse) {
324: try {
325: l.mousePressed((MapMouseEvent) event.data);
326: } catch (Throwable t) {
327: ProjectUIPlugin.log(
328: "Error processing a mouse pressed event", t);//$NON-NLS-1$
329: }
330: }
331: }
332:
333: /**
334: * @param event
335: */
336: private void sendDoubleClickEvent(Event event) {
337: for (MapMouseListener l : this .mouse) {
338: try {
339: l.mouseDoubleClicked((MapMouseEvent) event.data);
340: } catch (Throwable t) {
341: ProjectUIPlugin.log(
342: "Error processing a double clicked event", t);//$NON-NLS-1$
343: }
344: }
345: }
346:
347: /**
348: * Adds a MapEditorListener
349: *
350: * @param l the listener
351: */
352: public void addMapEditorListener(IMapDisplayListener l) {
353: paneListener.add(l);
354: }
355:
356: /**
357: * Removes a MapEditorListener Listener
358: *
359: * @param l the listener
360: */
361: public void removeMapEditorListener(IMapDisplayListener l) {
362: paneListener.remove(l);
363: }
364:
365: /**
366: * Adds a MapMouseListener Listener
367: *
368: * @param l the listener to add.
369: */
370: public void addMouseListener(MapMouseListener l) {
371: mouse.add(l);
372: }
373:
374: /**
375: * Adds a MapMouseMotionListener Listener
376: *
377: * @param l the listener to add.
378: */
379: public void addMouseMotionListener(MapMouseMotionListener l) {
380: motion.add(l);
381:
382: }
383:
384: /**
385: * Adds a MapMouseWheelListener Listener
386: *
387: * @param l the listener to add.
388: */
389: public void addMouseWheelListener(MapMouseWheelListener l) {
390: wheel.add(l);
391: }
392:
393: /**
394: * Removes a MapMouseListener Listener
395: *
396: * @param l the listener to remove.
397: */
398: public void removeMouseListener(MapMouseListener l) {
399: mouse.remove(l);
400: }
401:
402: /**
403: * Removes a MapMouseMotionListener Listener
404: *
405: * @param l the listener to remove.
406: */
407: public void removeMouseMotionListener(MapMouseMotionListener l) {
408: motion.remove(l);
409: }
410:
411: /**
412: * Removes a MapMouseWheelListener Listener
413: *
414: * @param l the listener to remove.
415: */
416: public void removeMouseWheelListener(MapMouseWheelListener l) {
417: wheel.remove(l);
418: }
419:
420: static class DoubleClickAttempt {
421: Event first;
422: Event release;
423: Event third;
424: }
425: }
|