KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > gvt > event > AWTEventDispatcher


1 /*
2
3    Copyright 2001-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.gvt.event;
19
20 import java.awt.Point JavaDoc;
21 import java.awt.event.InputEvent JavaDoc;
22 import java.awt.event.KeyEvent JavaDoc;
23 import java.awt.event.KeyListener JavaDoc;
24 import java.awt.event.MouseEvent JavaDoc;
25 import java.awt.event.MouseListener JavaDoc;
26 import java.awt.event.MouseMotionListener JavaDoc;
27 import java.awt.geom.AffineTransform JavaDoc;
28 import java.awt.geom.Point2D JavaDoc;
29 import java.lang.reflect.Array JavaDoc;
30 import java.util.EventListener JavaDoc;
31 import java.util.EventObject JavaDoc;
32 import java.util.LinkedList JavaDoc;
33 import java.util.List JavaDoc;
34
35 import javax.swing.event.EventListenerList JavaDoc;
36
37 import org.apache.batik.gvt.GraphicsNode;
38 import org.apache.batik.gvt.TextNode;
39
40 /**
41  * An EventDispatcher implementation based on AWT events.
42  *
43  * <p>Mouse events are dispatched to their "containing" node (the
44  * GraphicsNode corresponding to the mouse event coordinate). Searches
45  * for containment are performed from the EventDispatcher's "root"
46  * node.</p>
47  *
48  * @author <a HREF="mailto:bill.haneman@ireland.sun.com">Bill Haneman</a>
49  * @author <a HREF="mailto:cjolif@ilog.fr">Christophe Jolif</a>
50  * @author <a HREF="mailto:tkormann@ilog.fr">Thierry Kormann</a>
51  * @version $Id: AWTEventDispatcher.java,v 1.23 2005/03/27 08:58:34 cam Exp $
52  */

53 public class AWTEventDispatcher implements EventDispatcher,
54                                            MouseListener JavaDoc,
55                                            MouseMotionListener JavaDoc,
56                                            KeyListener JavaDoc {
57
58     /**
59      * The root GraphicsNode as determined by setRootNode().
60      */

61     protected GraphicsNode root;
62
63     /**
64      * The base AffineTransform for InputEvent-to-GraphicsNodeEvent
65      * coordinates as determined by setBaseTransform().
66      */

67     protected AffineTransform JavaDoc baseTransform;
68
69     /**
70      * The global listener list.
71      */

72     protected EventListenerList JavaDoc glisteners;
73
74     /**
75      * The lastest node which has been targeted by an event.
76      */

77     protected GraphicsNode lastHit;
78
79     /**
80      * A dummy graphics node to dispatch "deselect" mouse events to. That is,
81      * when the mouse is clicked outside any nodes.
82      */

83     protected GraphicsNode dummyNode = new TextNode();
84
85     /**
86      * The current GraphicsNode targeted by an key events.
87      */

88     protected GraphicsNode currentKeyEventTarget;
89
90     /**
91      * These are used to queue events while a rendering event
92      * is in progress.
93      */

94     protected List JavaDoc eventQueue = new LinkedList JavaDoc();
95     protected boolean eventDispatchEnabled = true;
96     protected int eventQueueMaxSize = MAX_QUEUE_SIZE;
97     /**
98      * default max size of the event queue.
99      */

100     final static int MAX_QUEUE_SIZE = 10;
101
102     private int nodeIncrementEventID = KeyEvent.KEY_PRESSED;
103     private int nodeIncrementEventCode = KeyEvent.VK_TAB;
104     private int nodeIncrementEventModifiers = 0;
105     private int nodeDecrementEventID = KeyEvent.KEY_PRESSED;
106     private int nodeDecrementEventCode = KeyEvent.VK_TAB;
107     private int nodeDecrementEventModifiers = InputEvent.SHIFT_MASK;
108
109     /**
110      * Constructs a new event dispatcher.
111      */

112     public AWTEventDispatcher() {
113     }
114
115     /**
116      * Sets the root node for MouseEvent dispatch containment searches
117      * and field selections.
118      * @param root the root node
119      */

120     public void setRootNode(GraphicsNode root) {
121         if (this.root != root)
122             eventQueue.clear(); // new root so clear 'old' events.
123
this.root = root;
124     }
125
126     /**
127      * Returns the root node for MouseEvent dispatch containment
128      * searches and field selections.
129      */

130     public GraphicsNode getRootNode() {
131         return root;
132     }
133
134     /**
135      * Sets the base transform applied to MouseEvent coordinates prior
136      * to dispatch.
137      * @param t the affine transform
138      */

139     public void setBaseTransform(AffineTransform JavaDoc t) {
140         if ((baseTransform != t) &&
141             ((baseTransform == null) || (!baseTransform.equals(t))))
142             // new Display transform so events are not where user
143
// thinks they were.
144
eventQueue.clear();
145         baseTransform = t;
146     }
147
148     /**
149      * Returns the base transform applied to MouseEvent coordinates prior
150      * to dispatch.
151      */

152     public AffineTransform JavaDoc getBaseTransform() {
153         return new AffineTransform JavaDoc(baseTransform);
154     }
155
156     //
157
// AWT listeners wrapper
158
//
159

160     /**
161      * Dispatches the specified AWT mouse event down to the GVT tree.
162      * The mouse event is mutated to a GraphicsNodeMouseEvent.
163      * @param evt the mouse event to propagate
164      */

165     public void mousePressed(MouseEvent JavaDoc evt) {
166         dispatchEvent(evt);
167     }
168
169     /**
170      * Dispatches the specified AWT mouse event down to the GVT tree.
171      * The mouse event is mutated to a GraphicsNodeMouseEvent.
172      * @param evt the mouse event to propagate
173      */

174     public void mouseReleased(MouseEvent JavaDoc evt) {
175         dispatchEvent(evt);
176     }
177
178     /**
179      * Dispatches the specified AWT mouse event down to the GVT tree.
180      * The mouse event is mutated to a GraphicsNodeMouseEvent.
181      * @param evt the mouse event to propagate
182      */

183     public void mouseEntered(MouseEvent JavaDoc evt) {
184         dispatchEvent(evt);
185     }
186
187     /**
188      * Dispatches the specified AWT mouse event down to the GVT tree.
189      * The mouse event is mutated to a GraphicsNodeMouseEvent.
190      * @param evt the mouse event to propagate
191      */

192     public void mouseExited(MouseEvent JavaDoc evt) {
193         dispatchEvent(evt);
194     }
195
196     /**
197      * Dispatches the specified AWT mouse event down to the GVT tree.
198      * The mouse event is mutated to a GraphicsNodeMouseEvent.
199      * @param evt the mouse event to propagate
200      */

201     public void mouseClicked(MouseEvent JavaDoc evt) {
202         dispatchEvent(evt);
203     }
204
205     /**
206      * Dispatches the specified AWT mouse event down to the GVT tree.
207      * The mouse event is mutated to a GraphicsNodeMouseEvent.
208      * @param evt the mouse event to propagate
209      */

210     public void mouseMoved(MouseEvent JavaDoc evt) {
211         dispatchEvent(evt);
212     }
213
214     /**
215      * Dispatches the specified AWT mouse event down to the GVT tree.
216      * The mouse event is mutated to a GraphicsNodeMouseEvent.
217      * @param evt the mouse event to propagate
218      */

219     public void mouseDragged(MouseEvent JavaDoc evt) {
220         dispatchEvent(evt);
221     }
222
223     /**
224      * Dispatches the specified AWT key event down to the GVT tree.
225      * The mouse event is mutated to a GraphicsNodeKeyEvent.
226      * @param evt the key event to propagate
227      */

228     public void keyPressed(KeyEvent JavaDoc evt) {
229         dispatchEvent(evt);
230     }
231
232     /**
233      * Dispatches the specified AWT key event down to the GVT tree.
234      * The mouse event is mutated to a GraphicsNodeKeyEvent.
235      * @param evt the key event to propagate
236      */

237     public void keyReleased(KeyEvent JavaDoc evt) {
238         dispatchEvent(evt);
239     }
240
241     /**
242      * Dispatches the specified AWT key event down to the GVT tree.
243      * The mouse event is mutated to a GraphicsNodeKeyEvent.
244      * @param evt the key event to propagate
245      */

246     public void keyTyped(KeyEvent JavaDoc evt) {
247         dispatchEvent(evt);
248     }
249
250     //
251
// Global GVT listeners support
252
//
253

254     /**
255      * Adds the specified 'global' GraphicsNodeMouseListener which is
256      * notified of all MouseEvents dispatched.
257      * @param l the listener to add
258      */

259     public void addGraphicsNodeMouseListener(GraphicsNodeMouseListener l) {
260         if (glisteners == null) {
261             glisteners = new EventListenerList JavaDoc();
262         }
263         glisteners.add(GraphicsNodeMouseListener.class, l);
264     }
265
266     /**
267      * Removes the specified 'global' GraphicsNodeMouseListener which is
268      * notified of all MouseEvents dispatched.
269      * @param l the listener to remove
270      */

271     public void removeGraphicsNodeMouseListener(GraphicsNodeMouseListener l) {
272         if (glisteners != null) {
273             glisteners.remove(GraphicsNodeMouseListener.class, l);
274         }
275     }
276
277     /**
278      * Adds the specified 'global' GraphicsNodeKeyListener which is
279      * notified of all KeyEvents dispatched.
280      * @param l the listener to add
281      */

282     public void addGraphicsNodeKeyListener(GraphicsNodeKeyListener l) {
283         if (glisteners == null) {
284             glisteners = new EventListenerList JavaDoc();
285         }
286         glisteners.add(GraphicsNodeKeyListener.class, l);
287     }
288
289     /**
290      * Removes the specified 'global' GraphicsNodeKeyListener which is
291      * notified of all KeyEvents dispatched.
292      * @param l the listener to remove
293      */

294     public void removeGraphicsNodeKeyListener(GraphicsNodeKeyListener l) {
295         if (glisteners != null) {
296             glisteners.remove(GraphicsNodeKeyListener.class, l);
297         }
298     }
299
300     /**
301      * Returns an array of listeners that were added to this event
302      * dispatcher and of the specified type.
303      * @param listenerType the type of the listeners to return
304      */

305     public EventListener JavaDoc [] getListeners(Class JavaDoc listenerType) {
306         Object JavaDoc array =
307             Array.newInstance(listenerType,
308                               glisteners.getListenerCount(listenerType));
309         Object JavaDoc[] pairElements = glisteners.getListenerList();
310         for (int i = 0, j = 0;i < pairElements.length-1; i+=2) {
311             if (pairElements[i].equals(listenerType)) {
312                 Array.set(array, j, pairElements[i+1]);
313                 ++j;
314             }
315         }
316         return (EventListener JavaDoc[]) array;
317     }
318
319     //
320
// Event dispatch implementation
321
//
322

323     public void setEventDispatchEnabled(boolean b) {
324         eventDispatchEnabled = b;
325         if (eventDispatchEnabled) {
326             // Dispatch any queued events.
327
while (eventQueue.size() > 0) {
328                 EventObject JavaDoc evt = (EventObject JavaDoc)eventQueue.remove(0);
329                 dispatchEvent(evt);
330             }
331         }
332     }
333     public void setEventQueueMaxSize(int n) {
334         eventQueueMaxSize = n;
335         if (n == 0) eventQueue.clear();
336         while(eventQueue.size() > eventQueueMaxSize)
337             eventQueue.remove(0);
338     }
339
340     /**
341      * Dispatches the specified AWT event.
342      * @param evt the event to dispatch
343      */

344     public void dispatchEvent(EventObject JavaDoc evt) {
345         if (root == null) // No root do not store anything.
346
return;
347         if (!eventDispatchEnabled) {
348             if (eventQueueMaxSize > 0) {
349                 eventQueue.add(evt);
350                 while (eventQueue.size() > eventQueueMaxSize)
351                     // Limit how many events we queue - don't want
352
// user waiting forever for them to clear.
353
eventQueue.remove(0);
354             }
355             return;
356         }
357         if (evt instanceof MouseEvent JavaDoc) {
358             dispatchMouseEvent((MouseEvent JavaDoc) evt);
359         } else if (evt instanceof KeyEvent JavaDoc) {
360             InputEvent JavaDoc e = (InputEvent JavaDoc)evt;
361             if (isNodeIncrementEvent(e)) {
362                 incrementKeyTarget();
363             } else if (isNodeDecrementEvent(e)) {
364                 decrementKeyTarget();
365             } else {
366                 dispatchKeyEvent((KeyEvent JavaDoc) evt);
367             }
368         }
369     }
370
371     /**
372      * Dispatches the specified AWT key event.
373      * @param evt the key event to dispatch
374      */

375     protected void dispatchKeyEvent(KeyEvent JavaDoc evt) {
376         currentKeyEventTarget = lastHit;
377         if (currentKeyEventTarget != null) {
378             processKeyEvent
379                 (new GraphicsNodeKeyEvent(currentKeyEventTarget,
380                                           evt.getID(),
381                                           evt.getWhen(),
382                                           evt.getModifiers(),
383                                           evt.getKeyCode(),
384                                           evt.getKeyChar()));
385         }
386     }
387     
388     /**
389      * Dispatches the specified AWT mouse event.
390      * @param evt the mouse event to dispatch
391      */

392     protected void dispatchMouseEvent(MouseEvent JavaDoc evt) {
393         GraphicsNodeMouseEvent gvtevt;
394         Point2D JavaDoc p = new Point2D.Float JavaDoc(evt.getX(), evt.getY());
395         Point2D JavaDoc gnp = p;
396         if (baseTransform != null) {
397             gnp = baseTransform.transform(p, null);
398         }
399
400         GraphicsNode node = root.nodeHitAt(gnp);
401         
402         // If the receiving node has changed, send a notification
403
// check if we enter a new node
404
Point JavaDoc screenPos;
405         if (!evt.getComponent().isShowing()) {
406             screenPos = new Point JavaDoc(0,0);
407         } else {
408             screenPos = evt.getComponent().getLocationOnScreen();
409             screenPos.x += evt.getX();
410             screenPos.y += evt.getY();
411         }
412
413         if (lastHit != node) {
414             // post an MOUSE_EXITED
415
if (lastHit != null) {
416                 gvtevt = new GraphicsNodeMouseEvent(lastHit,
417                                                     MouseEvent.
418                                                     MOUSE_EXITED,
419                                                     evt.getWhen(),
420                                                     evt.getModifiers(),
421                                                     (float)gnp.getX(),
422                                                     (float)gnp.getY(),
423                                                     (int)Math.floor(p.getX()),
424                                                     (int)Math.floor(p.getY()),
425                                                     screenPos.x,
426                                                     screenPos.y,
427                                                     evt.getClickCount(),
428                                                     node);
429                 processMouseEvent(gvtevt);
430                 // lastHit.processMouseEvent(gvtevt);
431
}
432             // post an MOUSE_ENTERED
433
if (node != null) {
434                 gvtevt = new GraphicsNodeMouseEvent(node,
435                                                     MouseEvent.
436                                                     MOUSE_ENTERED,
437                                                     evt.getWhen(),
438                                                     evt.
439                                                     getModifiers(),
440                                                     (float)gnp.getX(),
441                                                     (float)gnp.getY(),
442                                                     (int)Math.floor(p.getX()),
443                                                     (int)Math.floor(p.getY()),
444                                                     screenPos.x,
445                                                     screenPos.y,
446                                                     evt.getClickCount(),
447                                                     lastHit);
448                 processMouseEvent(gvtevt);
449                 // node.processMouseEvent(gvtevt);
450
}
451         }
452         // In all cases, dispatch the original event
453
if (node != null) {
454             gvtevt = new GraphicsNodeMouseEvent(node,
455                                                 evt.getID(),
456                                                 evt.getWhen(),
457                                                 evt.getModifiers(),
458                                                 (float)gnp.getX(),
459                                                 (float)gnp.getY(),
460                                                 (int)Math.floor(p.getX()),
461                                                 (int)Math.floor(p.getY()),
462                                                 screenPos.x,
463                                                 screenPos.y,
464                                                 evt.getClickCount(),
465                                                 null);
466
467             // node.processMouseEvent(gvtevt);
468
processMouseEvent(gvtevt);
469
470         } else {
471             // this is a deselect event, dispatch it to dummy node
472
gvtevt = new GraphicsNodeMouseEvent(root,
473                                                 evt.getID(),
474                                                 evt.getWhen(),
475                                                 evt.getModifiers(),
476                                                 (float)gnp.getX(),
477                                                 (float)gnp.getY(),
478                                                 (int)Math.floor(p.getX()),
479                                                 (int)Math.floor(p.getY()),
480                                                 screenPos.x,
481                                                 screenPos.y,
482                                                 evt.getClickCount(),
483                                                 null);
484
485             processMouseEvent(gvtevt);
486         }
487         lastHit = node;
488     }
489
490     /**
491      * Processes the specified event by firing the 'global' listeners
492      * attached to this event dispatcher.
493      * @param evt the event to process
494      */

495     protected void processMouseEvent(GraphicsNodeMouseEvent evt) {
496         if (glisteners != null) {
497             GraphicsNodeMouseListener[] listeners =
498                 (GraphicsNodeMouseListener[])
499                 getListeners(GraphicsNodeMouseListener.class);
500             switch (evt.getID()) {
501             case GraphicsNodeMouseEvent.MOUSE_MOVED:
502                 for (int i = 0; i < listeners.length; i++) {
503                     listeners[i].mouseMoved(evt);
504                 }
505                 break;
506             case GraphicsNodeMouseEvent.MOUSE_DRAGGED:
507                 for (int i = 0; i < listeners.length; i++) {
508                     listeners[i].mouseDragged(evt);
509                 }
510                 break;
511             case GraphicsNodeMouseEvent.MOUSE_ENTERED:
512                 for (int i = 0; i < listeners.length; i++) {
513                     listeners[i].mouseEntered(evt);
514                 }
515                 break;
516             case GraphicsNodeMouseEvent.MOUSE_EXITED:
517                 for (int i = 0; i < listeners.length; i++) {
518                     listeners[i].mouseExited(evt);
519                 }
520                 break;
521             case GraphicsNodeMouseEvent.MOUSE_CLICKED:
522                 for (int i = 0; i < listeners.length; i++) {
523                     listeners[i].mouseClicked(evt);
524                 }
525                 break;
526             case GraphicsNodeMouseEvent.MOUSE_PRESSED:
527                 for (int i = 0; i < listeners.length; i++) {
528                     listeners[i].mousePressed(evt);
529                 }
530                 break;
531             case GraphicsNodeMouseEvent.MOUSE_RELEASED:
532                 for (int i = 0; i < listeners.length; i++) {
533                     listeners[i].mouseReleased(evt);
534                 }
535                 break;
536             default:
537                 throw new Error JavaDoc("Unknown Mouse Event type: "+evt.getID());
538             }
539         }
540     }
541
542     /**
543      * Dispatches a graphics node key event to by firing the 'global'
544      * listeners attached to this event dispatcher.
545      *
546      * @param evt the evt to dispatch
547      */

548     public void processKeyEvent(GraphicsNodeKeyEvent evt) {
549         if ((glisteners != null)) {
550             GraphicsNodeKeyListener[] listeners =
551                 (GraphicsNodeKeyListener[])
552                 getListeners(GraphicsNodeKeyListener.class);
553
554             switch (evt.getID()) {
555             case GraphicsNodeKeyEvent.KEY_PRESSED:
556                 for (int i=0; i<listeners.length; ++i) {
557                     listeners[i].keyPressed(evt);
558                 }
559                 break;
560             case GraphicsNodeKeyEvent.KEY_RELEASED:
561                 for (int i=0; i<listeners.length; ++i) {
562                     listeners[i].keyReleased(evt);
563                 }
564                 break;
565             case GraphicsNodeKeyEvent.KEY_TYPED:
566                 for (int i=0; i<listeners.length; ++i) {
567                     listeners[i].keyTyped(evt);
568                 }
569                 break;
570             default:
571                 throw new Error JavaDoc("Unknown Key Event type: "+evt.getID());
572             }
573         }
574         evt.consume();
575     }
576
577
578     private void incrementKeyTarget() {
579         // <!> FIXME TODO: Not implemented.
580
throw new Error JavaDoc("Increment not implemented.");
581     }
582
583     private void decrementKeyTarget() {
584         // <!> FIXME TODO: Not implemented.
585
throw new Error JavaDoc("Decrement not implemented.");
586     }
587
588     /**
589      * Associates all InputEvents of type <tt>e.getID()</tt>
590      * with "incrementing" of the currently selected GraphicsNode.
591      */

592     public void setNodeIncrementEvent(InputEvent JavaDoc e) {
593         nodeIncrementEventID = e.getID();
594         if (e instanceof KeyEvent JavaDoc) {
595             nodeIncrementEventCode = ((KeyEvent JavaDoc) e).getKeyCode();
596         }
597         nodeIncrementEventModifiers = e.getModifiers();
598     }
599
600     /**
601      * Associates all InputEvents of type <tt>e.getID()</tt>
602      * with "decrementing" of the currently selected GraphicsNode.
603      * The notion of "currently selected" GraphicsNode is used
604      * for dispatching KeyEvents.
605      */

606     public void setNodeDecrementEvent(InputEvent JavaDoc e) {
607         nodeDecrementEventID = e.getID();
608         if (e instanceof KeyEvent JavaDoc) {
609             nodeDecrementEventCode = ((KeyEvent JavaDoc) e).getKeyCode();
610         }
611         nodeDecrementEventModifiers = e.getModifiers();
612     }
613
614     /**
615      * Returns true if the input event e is a node increment event,
616      * false otherwise.
617      * @param e the input event
618      */

619     protected boolean isNodeIncrementEvent(InputEvent JavaDoc e) {
620         // TODO: Improve code readability!
621
return ((e.getID() == nodeIncrementEventID) &&
622                 ((e instanceof KeyEvent JavaDoc) ?
623                      (((KeyEvent JavaDoc) e).getKeyCode() == nodeIncrementEventCode) : true) &&
624                 ((e.getModifiers() & nodeIncrementEventModifiers) != 0));
625     }
626
627     /**
628      * Returns true if the input event e is a node decrement event,
629      * false otherwise.
630      */

631     protected boolean isNodeDecrementEvent(InputEvent JavaDoc e) {
632         // TODO: Improve code readability!
633
return ((e.getID() == nodeDecrementEventID) &&
634                 ((e instanceof KeyEvent JavaDoc) ?
635                      ( ((KeyEvent JavaDoc) e).getKeyCode() == nodeDecrementEventCode) : true) &&
636                 ((e.getModifiers() & nodeDecrementEventModifiers) != 0 ));
637
638     }
639 }
640
Popular Tags