1 /*
2 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 package java.awt;
26
27 import java.awt.event;
28 import java.lang.reflect.Array;
29 import java.util.EventListener;
30 import java.io.Serializable;
31 import java.io.ObjectOutputStream;
32 import java.io.IOException;
33 import java.util.EventListener;
34
35
36 /**
37 * {@code AWTEventMulticaster} implements efficient and thread-safe multi-cast
38 * event dispatching for the AWT events defined in the {@code java.awt.event}
39 * package.
40 * <p>
41 * The following example illustrates how to use this class:
42 *
43 * <pre><code>
44 * public myComponent extends Component {
45 * ActionListener actionListener = null;
46 *
47 * public synchronized void addActionListener(ActionListener l) {
48 * actionListener = AWTEventMulticaster.add(actionListener, l);
49 * }
50 * public synchronized void removeActionListener(ActionListener l) {
51 * actionListener = AWTEventMulticaster.remove(actionListener, l);
52 * }
53 * public void processEvent(AWTEvent e) {
54 * // when event occurs which causes "action" semantic
55 * ActionListener listener = actionListener;
56 * if (listener != null) {
57 * listener.actionPerformed(new ActionEvent());
58 * }
59 * }
60 * }
61 * </code></pre>
62 * The important point to note is the first argument to the {@code
63 * add} and {@code remove} methods is the field maintaining the
64 * listeners. In addition you must assign the result of the {@code add}
65 * and {@code remove} methods to the field maintaining the listeners.
66 * <p>
67 * {@code AWTEventMulticaster} is implemented as a pair of {@code
68 * EventListeners} that are set at construction time. {@code
69 * AWTEventMulticaster} is immutable. The {@code add} and {@code
70 * remove} methods do not alter {@code AWTEventMulticaster} in
71 * anyway. If necessary, a new {@code AWTEventMulticaster} is
72 * created. In this way it is safe to add and remove listeners during
73 * the process of an event dispatching. However, event listeners
74 * added during the process of an event dispatch operation are not
75 * notified of the event currently being dispatched.
76 * <p>
77 * All of the {@code add} methods allow {@code null} arguments. If the
78 * first argument is {@code null}, the second argument is returned. If
79 * the first argument is not {@code null} and the second argument is
80 * {@code null}, the first argument is returned. If both arguments are
81 * {@code non-null}, a new {@code AWTEventMulticaster} is created using
82 * the two arguments and returned.
83 * <p>
84 * For the {@code remove} methods that take two arguments, the following is
85 * returned:
86 * <ul>
87 * <li>{@code null}, if the first argument is {@code null}, or
88 * the arguments are equal, by way of {@code ==}.
89 * <li>the first argument, if the first argument is not an instance of
90 * {@code AWTEventMulticaster}.
91 * <li>result of invoking {@code remove(EventListener)} on the
92 * first argument, supplying the second argument to the
93 * {@code remove(EventListener)} method.
94 * </ul>
95 * <p>Swing makes use of
96 * {@link javax.swing.event.EventListenerList EventListenerList} for
97 * similar logic. Refer to it for details.
98 *
99 * @see javax.swing.event.EventListenerList
100 *
101 * @author John Rose
102 * @author Amy Fowler
103 * @since 1.1
104 */
105
106 public class AWTEventMulticaster implements
107 ComponentListener, ContainerListener, FocusListener, KeyListener,
108 MouseListener, MouseMotionListener, WindowListener, WindowFocusListener,
109 WindowStateListener, ActionListener, ItemListener, AdjustmentListener,
110 TextListener, InputMethodListener, HierarchyListener,
111 HierarchyBoundsListener, MouseWheelListener {
112
113 protected final EventListener a, b;
114
115 /**
116 * Creates an event multicaster instance which chains listener-a
117 * with listener-b. Input parameters <code>a</code> and <code>b</code>
118 * should not be <code>null</code>, though implementations may vary in
119 * choosing whether or not to throw <code>NullPointerException</code>
120 * in that case.
121 * @param a listener-a
122 * @param b listener-b
123 */
124 protected AWTEventMulticaster(EventListener a, EventListener b) {
125 this.a = a; this.b = b;
126 }
127
128 /**
129 * Removes a listener from this multicaster.
130 * <p>
131 * The returned multicaster contains all the listeners in this
132 * multicaster with the exception of all occurrences of {@code oldl}.
133 * If the resulting multicaster contains only one regular listener
134 * the regular listener may be returned. If the resulting multicaster
135 * is empty, then {@code null} may be returned instead.
136 * <p>
137 * No exception is thrown if {@code oldl} is {@code null}.
138 *
139 * @param oldl the listener to be removed
140 * @return resulting listener
141 */
142 protected EventListener remove(EventListener oldl) {
143 if (oldl == a) return b;
144 if (oldl == b) return a;
145 EventListener a2 = removeInternal(a, oldl);
146 EventListener b2 = removeInternal(b, oldl);
147 if (a2 == a && b2 == b) {
148 return this; // it's not here
149 }
150 return addInternal(a2, b2);
151 }
152
153 /**
154 * Handles the componentResized event by invoking the
155 * componentResized methods on listener-a and listener-b.
156 * @param e the component event
157 */
158 public void componentResized(ComponentEvent e) {
159 ((ComponentListener)a).componentResized(e);
160 ((ComponentListener)b).componentResized(e);
161 }
162
163 /**
164 * Handles the componentMoved event by invoking the
165 * componentMoved methods on listener-a and listener-b.
166 * @param e the component event
167 */
168 public void componentMoved(ComponentEvent e) {
169 ((ComponentListener)a).componentMoved(e);
170 ((ComponentListener)b).componentMoved(e);
171 }
172
173 /**
174 * Handles the componentShown event by invoking the
175 * componentShown methods on listener-a and listener-b.
176 * @param e the component event
177 */
178 public void componentShown(ComponentEvent e) {
179 ((ComponentListener)a).componentShown(e);
180 ((ComponentListener)b).componentShown(e);
181 }
182
183 /**
184 * Handles the componentHidden event by invoking the
185 * componentHidden methods on listener-a and listener-b.
186 * @param e the component event
187 */
188 public void componentHidden(ComponentEvent e) {
189 ((ComponentListener)a).componentHidden(e);
190 ((ComponentListener)b).componentHidden(e);
191 }
192
193 /**
194 * Handles the componentAdded container event by invoking the
195 * componentAdded methods on listener-a and listener-b.
196 * @param e the component event
197 */
198 public void componentAdded(ContainerEvent e) {
199 ((ContainerListener)a).componentAdded(e);
200 ((ContainerListener)b).componentAdded(e);
201 }
202
203 /**
204 * Handles the componentRemoved container event by invoking the
205 * componentRemoved methods on listener-a and listener-b.
206 * @param e the component event
207 */
208 public void componentRemoved(ContainerEvent e) {
209 ((ContainerListener)a).componentRemoved(e);
210 ((ContainerListener)b).componentRemoved(e);
211 }
212
213 /**
214 * Handles the focusGained event by invoking the
215 * focusGained methods on listener-a and listener-b.
216 * @param e the focus event
217 */
218 public void focusGained(FocusEvent e) {
219 ((FocusListener)a).focusGained(e);
220 ((FocusListener)b).focusGained(e);
221 }
222
223 /**
224 * Handles the focusLost event by invoking the
225 * focusLost methods on listener-a and listener-b.
226 * @param e the focus event
227 */
228 public void focusLost(FocusEvent e) {
229 ((FocusListener)a).focusLost(e);
230 ((FocusListener)b).focusLost(e);
231 }
232
233 /**
234 * Handles the keyTyped event by invoking the
235 * keyTyped methods on listener-a and listener-b.
236 * @param e the key event
237 */
238 public void keyTyped(KeyEvent e) {
239 ((KeyListener)a).keyTyped(e);
240 ((KeyListener)b).keyTyped(e);
241 }
242
243 /**
244 * Handles the keyPressed event by invoking the
245 * keyPressed methods on listener-a and listener-b.
246 * @param e the key event
247 */
248 public void keyPressed(KeyEvent e) {
249 ((KeyListener)a).keyPressed(e);
250 ((KeyListener)b).keyPressed(e);
251 }
252
253 /**
254 * Handles the keyReleased event by invoking the
255 * keyReleased methods on listener-a and listener-b.
256 * @param e the key event
257 */
258 public void keyReleased(KeyEvent e) {
259 ((KeyListener)a).keyReleased(e);
260 ((KeyListener)b).keyReleased(e);
261 }
262
263 /**
264 * Handles the mouseClicked event by invoking the
265 * mouseClicked methods on listener-a and listener-b.
266 * @param e the mouse event
267 */
268 public void mouseClicked(MouseEvent e) {
269 ((MouseListener)a).mouseClicked(e);
270 ((MouseListener)b).mouseClicked(e);
271 }
272
273 /**
274 * Handles the mousePressed event by invoking the
275 * mousePressed methods on listener-a and listener-b.
276 * @param e the mouse event
277 */
278 public void mousePressed(MouseEvent e) {
279 ((MouseListener)a).mousePressed(e);
280 ((MouseListener)b).mousePressed(e);
281 }
282
283 /**
284 * Handles the mouseReleased event by invoking the
285 * mouseReleased methods on listener-a and listener-b.
286 * @param e the mouse event
287 */
288 public void mouseReleased(MouseEvent e) {
289 ((MouseListener)a).mouseReleased(e);
290 ((MouseListener)b).mouseReleased(e);
291 }
292
293 /**
294 * Handles the mouseEntered event by invoking the
295 * mouseEntered methods on listener-a and listener-b.
296 * @param e the mouse event
297 */
298 public void mouseEntered(MouseEvent e) {
299 ((MouseListener)a).mouseEntered(e);
300 ((MouseListener)b).mouseEntered(e);
301 }
302
303 /**
304 * Handles the mouseExited event by invoking the
305 * mouseExited methods on listener-a and listener-b.
306 * @param e the mouse event
307 */
308 public void mouseExited(MouseEvent e) {
309 ((MouseListener)a).mouseExited(e);
310 ((MouseListener)b).mouseExited(e);
311 }
312
313 /**
314 * Handles the mouseDragged event by invoking the
315 * mouseDragged methods on listener-a and listener-b.
316 * @param e the mouse event
317 */
318 public void mouseDragged(MouseEvent e) {
319 ((MouseMotionListener)a).mouseDragged(e);
320 ((MouseMotionListener)b).mouseDragged(e);
321 }
322
323 /**
324 * Handles the mouseMoved event by invoking the
325 * mouseMoved methods on listener-a and listener-b.
326 * @param e the mouse event
327 */
328 public void mouseMoved(MouseEvent e) {
329 ((MouseMotionListener)a).mouseMoved(e);
330 ((MouseMotionListener)b).mouseMoved(e);
331 }
332
333 /**
334 * Handles the windowOpened event by invoking the
335 * windowOpened methods on listener-a and listener-b.
336 * @param e the window event
337 */
338 public void windowOpened(WindowEvent e) {
339 ((WindowListener)a).windowOpened(e);
340 ((WindowListener)b).windowOpened(e);
341 }
342
343 /**
344 * Handles the windowClosing event by invoking the
345 * windowClosing methods on listener-a and listener-b.
346 * @param e the window event
347 */
348 public void windowClosing(WindowEvent e) {
349 ((WindowListener)a).windowClosing(e);
350 ((WindowListener)b).windowClosing(e);
351 }
352
353 /**
354 * Handles the windowClosed event by invoking the
355 * windowClosed methods on listener-a and listener-b.
356 * @param e the window event
357 */
358 public void windowClosed(WindowEvent e) {
359 ((WindowListener)a).windowClosed(e);
360 ((WindowListener)b).windowClosed(e);
361 }
362
363 /**
364 * Handles the windowIconified event by invoking the
365 * windowIconified methods on listener-a and listener-b.
366 * @param e the window event
367 */
368 public void windowIconified(WindowEvent e) {
369 ((WindowListener)a).windowIconified(e);
370 ((WindowListener)b).windowIconified(e);
371 }
372
373 /**
374 * Handles the windowDeiconfied event by invoking the
375 * windowDeiconified methods on listener-a and listener-b.
376 * @param e the window event
377 */
378 public void windowDeiconified(WindowEvent e) {
379 ((WindowListener)a).windowDeiconified(e);
380 ((WindowListener)b).windowDeiconified(e);
381 }
382
383 /**
384 * Handles the windowActivated event by invoking the
385 * windowActivated methods on listener-a and listener-b.
386 * @param e the window event
387 */
388 public void windowActivated(WindowEvent e) {
389 ((WindowListener)a).windowActivated(e);
390 ((WindowListener)b).windowActivated(e);
391 }
392
393 /**
394 * Handles the windowDeactivated event by invoking the
395 * windowDeactivated methods on listener-a and listener-b.
396 * @param e the window event
397 */
398 public void windowDeactivated(WindowEvent e) {
399 ((WindowListener)a).windowDeactivated(e);
400 ((WindowListener)b).windowDeactivated(e);
401 }
402
403 /**
404 * Handles the windowStateChanged event by invoking the
405 * windowStateChanged methods on listener-a and listener-b.
406 * @param e the window event
407 * @since 1.4
408 */
409 public void windowStateChanged(WindowEvent e) {
410 ((WindowStateListener)a).windowStateChanged(e);
411 ((WindowStateListener)b).windowStateChanged(e);
412 }
413
414
415 /**
416 * Handles the windowGainedFocus event by invoking the windowGainedFocus
417 * methods on listener-a and listener-b.
418 * @param e the window event
419 * @since 1.4
420 */
421 public void windowGainedFocus(WindowEvent e) {
422 ((WindowFocusListener)a).windowGainedFocus(e);
423 ((WindowFocusListener)b).windowGainedFocus(e);
424 }
425
426 /**
427 * Handles the windowLostFocus event by invoking the windowLostFocus
428 * methods on listener-a and listener-b.
429 * @param e the window event
430 * @since 1.4
431 */
432 public void windowLostFocus(WindowEvent e) {
433 ((WindowFocusListener)a).windowLostFocus(e);
434 ((WindowFocusListener)b).windowLostFocus(e);
435 }
436
437 /**
438 * Handles the actionPerformed event by invoking the
439 * actionPerformed methods on listener-a and listener-b.
440 * @param e the action event
441 */
442 public void actionPerformed(ActionEvent e) {
443 ((ActionListener)a).actionPerformed(e);
444 ((ActionListener)b).actionPerformed(e);
445 }
446
447 /**
448 * Handles the itemStateChanged event by invoking the
449 * itemStateChanged methods on listener-a and listener-b.
450 * @param e the item event
451 */
452 public void itemStateChanged(ItemEvent e) {
453 ((ItemListener)a).itemStateChanged(e);
454 ((ItemListener)b).itemStateChanged(e);
455 }
456
457 /**
458 * Handles the adjustmentValueChanged event by invoking the
459 * adjustmentValueChanged methods on listener-a and listener-b.
460 * @param e the adjustment event
461 */
462 public void adjustmentValueChanged(AdjustmentEvent e) {
463 ((AdjustmentListener)a).adjustmentValueChanged(e);
464 ((AdjustmentListener)b).adjustmentValueChanged(e);
465 }
466 public void textValueChanged(TextEvent e) {
467 ((TextListener)a).textValueChanged(e);
468 ((TextListener)b).textValueChanged(e);
469 }
470
471 /**
472 * Handles the inputMethodTextChanged event by invoking the
473 * inputMethodTextChanged methods on listener-a and listener-b.
474 * @param e the item event
475 */
476 public void inputMethodTextChanged(InputMethodEvent e) {
477 ((InputMethodListener)a).inputMethodTextChanged(e);
478 ((InputMethodListener)b).inputMethodTextChanged(e);
479 }
480
481 /**
482 * Handles the caretPositionChanged event by invoking the
483 * caretPositionChanged methods on listener-a and listener-b.
484 * @param e the item event
485 */
486 public void caretPositionChanged(InputMethodEvent e) {
487 ((InputMethodListener)a).caretPositionChanged(e);
488 ((InputMethodListener)b).caretPositionChanged(e);
489 }
490
491 /**
492 * Handles the hierarchyChanged event by invoking the
493 * hierarchyChanged methods on listener-a and listener-b.
494 * @param e the item event
495 * @since 1.3
496 */
497 public void hierarchyChanged(HierarchyEvent e) {
498 ((HierarchyListener)a).hierarchyChanged(e);
499 ((HierarchyListener)b).hierarchyChanged(e);
500 }
501
502 /**
503 * Handles the ancestorMoved event by invoking the
504 * ancestorMoved methods on listener-a and listener-b.
505 * @param e the item event
506 * @since 1.3
507 */
508 public void ancestorMoved(HierarchyEvent e) {
509 ((HierarchyBoundsListener)a).ancestorMoved(e);
510 ((HierarchyBoundsListener)b).ancestorMoved(e);
511 }
512
513 /**
514 * Handles the ancestorResized event by invoking the
515 * ancestorResized methods on listener-a and listener-b.
516 * @param e the item event
517 * @since 1.3
518 */
519 public void ancestorResized(HierarchyEvent e) {
520 ((HierarchyBoundsListener)a).ancestorResized(e);
521 ((HierarchyBoundsListener)b).ancestorResized(e);
522 }
523
524 /**
525 * Handles the mouseWheelMoved event by invoking the
526 * mouseWheelMoved methods on listener-a and listener-b.
527 * @param e the mouse event
528 * @since 1.4
529 */
530 public void mouseWheelMoved(MouseWheelEvent e) {
531 ((MouseWheelListener)a).mouseWheelMoved(e);
532 ((MouseWheelListener)b).mouseWheelMoved(e);
533 }
534
535 /**
536 * Adds component-listener-a with component-listener-b and
537 * returns the resulting multicast listener.
538 * @param a component-listener-a
539 * @param b component-listener-b
540 */
541 public static ComponentListener add(ComponentListener a, ComponentListener b) {
542 return (ComponentListener)addInternal(a, b);
543 }
544
545 /**
546 * Adds container-listener-a with container-listener-b and
547 * returns the resulting multicast listener.
548 * @param a container-listener-a
549 * @param b container-listener-b
550 */
551 public static ContainerListener add(ContainerListener a, ContainerListener b) {
552 return (ContainerListener)addInternal(a, b);
553 }
554
555 /**
556 * Adds focus-listener-a with focus-listener-b and
557 * returns the resulting multicast listener.
558 * @param a focus-listener-a
559 * @param b focus-listener-b
560 */
561 public static FocusListener add(FocusListener a, FocusListener b) {
562 return (FocusListener)addInternal(a, b);
563 }
564
565 /**
566 * Adds key-listener-a with key-listener-b and
567 * returns the resulting multicast listener.
568 * @param a key-listener-a
569 * @param b key-listener-b
570 */
571 public static KeyListener add(KeyListener a, KeyListener b) {
572 return (KeyListener)addInternal(a, b);
573 }
574
575 /**
576 * Adds mouse-listener-a with mouse-listener-b and
577 * returns the resulting multicast listener.
578 * @param a mouse-listener-a
579 * @param b mouse-listener-b
580 */
581 public static MouseListener add(MouseListener a, MouseListener b) {
582 return (MouseListener)addInternal(a, b);
583 }
584
585 /**
586 * Adds mouse-motion-listener-a with mouse-motion-listener-b and
587 * returns the resulting multicast listener.
588 * @param a mouse-motion-listener-a
589 * @param b mouse-motion-listener-b
590 */
591 public static MouseMotionListener add(MouseMotionListener a, MouseMotionListener b) {
592 return (MouseMotionListener)addInternal(a, b);
593 }
594
595 /**
596 * Adds window-listener-a with window-listener-b and
597 * returns the resulting multicast listener.
598 * @param a window-listener-a
599 * @param b window-listener-b
600 */
601 public static WindowListener add(WindowListener a, WindowListener b) {
602 return (WindowListener)addInternal(a, b);
603 }
604
605 /**
606 * Adds window-state-listener-a with window-state-listener-b
607 * and returns the resulting multicast listener.
608 * @param a window-state-listener-a
609 * @param b window-state-listener-b
610 * @since 1.4
611 */
612 public static WindowStateListener add(WindowStateListener a,
613 WindowStateListener b) {
614 return (WindowStateListener)addInternal(a, b);
615 }
616
617 /**
618 * Adds window-focus-listener-a with window-focus-listener-b
619 * and returns the resulting multicast listener.
620 * @param a window-focus-listener-a
621 * @param b window-focus-listener-b
622 * @since 1.4
623 */
624 public static WindowFocusListener add(WindowFocusListener a,
625 WindowFocusListener b) {
626 return (WindowFocusListener)addInternal(a, b);
627 }
628
629 /**
630 * Adds action-listener-a with action-listener-b and
631 * returns the resulting multicast listener.
632 * @param a action-listener-a
633 * @param b action-listener-b
634 */
635 public static ActionListener add(ActionListener a, ActionListener b) {
636 return (ActionListener)addInternal(a, b);
637 }
638
639 /**
640 * Adds item-listener-a with item-listener-b and
641 * returns the resulting multicast listener.
642 * @param a item-listener-a
643 * @param b item-listener-b
644 */
645 public static ItemListener add(ItemListener a, ItemListener b) {
646 return (ItemListener)addInternal(a, b);
647 }
648
649 /**
650 * Adds adjustment-listener-a with adjustment-listener-b and
651 * returns the resulting multicast listener.
652 * @param a adjustment-listener-a
653 * @param b adjustment-listener-b
654 */
655 public static AdjustmentListener add(AdjustmentListener a, AdjustmentListener b) {
656 return (AdjustmentListener)addInternal(a, b);
657 }
658 public static TextListener add(TextListener a, TextListener b) {
659 return (TextListener)addInternal(a, b);
660 }
661
662 /**
663 * Adds input-method-listener-a with input-method-listener-b and
664 * returns the resulting multicast listener.
665 * @param a input-method-listener-a
666 * @param b input-method-listener-b
667 */
668 public static InputMethodListener add(InputMethodListener a, InputMethodListener b) {
669 return (InputMethodListener)addInternal(a, b);
670 }
671
672 /**
673 * Adds hierarchy-listener-a with hierarchy-listener-b and
674 * returns the resulting multicast listener.
675 * @param a hierarchy-listener-a
676 * @param b hierarchy-listener-b
677 * @since 1.3
678 */
679 public static HierarchyListener add(HierarchyListener a, HierarchyListener b) {
680 return (HierarchyListener)addInternal(a, b);
681 }
682
683 /**
684 * Adds hierarchy-bounds-listener-a with hierarchy-bounds-listener-b and
685 * returns the resulting multicast listener.
686 * @param a hierarchy-bounds-listener-a
687 * @param b hierarchy-bounds-listener-b
688 * @since 1.3
689 */
690 public static HierarchyBoundsListener add(HierarchyBoundsListener a, HierarchyBoundsListener b) {
691 return (HierarchyBoundsListener)addInternal(a, b);
692 }
693
694 /**
695 * Adds mouse-wheel-listener-a with mouse-wheel-listener-b and
696 * returns the resulting multicast listener.
697 * @param a mouse-wheel-listener-a
698 * @param b mouse-wheel-listener-b
699 * @since 1.4
700 */
701 public static MouseWheelListener add(MouseWheelListener a,
702 MouseWheelListener b) {
703 return (MouseWheelListener)addInternal(a, b);
704 }
705
706 /**
707 * Removes the old component-listener from component-listener-l and
708 * returns the resulting multicast listener.
709 * @param l component-listener-l
710 * @param oldl the component-listener being removed
711 */
712 public static ComponentListener remove(ComponentListener l, ComponentListener oldl) {
713 return (ComponentListener) removeInternal(l, oldl);
714 }
715
716 /**
717 * Removes the old container-listener from container-listener-l and
718 * returns the resulting multicast listener.
719 * @param l container-listener-l
720 * @param oldl the container-listener being removed
721 */
722 public static ContainerListener remove(ContainerListener l, ContainerListener oldl) {
723 return (ContainerListener) removeInternal(l, oldl);
724 }
725
726 /**
727 * Removes the old focus-listener from focus-listener-l and
728 * returns the resulting multicast listener.
729 * @param l focus-listener-l
730 * @param oldl the focus-listener being removed
731 */
732 public static FocusListener remove(FocusListener l, FocusListener oldl) {
733 return (FocusListener) removeInternal(l, oldl);
734 }
735
736 /**
737 * Removes the old key-listener from key-listener-l and
738 * returns the resulting multicast listener.
739 * @param l key-listener-l
740 * @param oldl the key-listener being removed
741 */
742 public static KeyListener remove(KeyListener l, KeyListener oldl) {
743 return (KeyListener) removeInternal(l, oldl);
744 }
745
746 /**
747 * Removes the old mouse-listener from mouse-listener-l and
748 * returns the resulting multicast listener.
749 * @param l mouse-listener-l
750 * @param oldl the mouse-listener being removed
751 */
752 public static MouseListener remove(MouseListener l, MouseListener oldl) {
753 return (MouseListener) removeInternal(l, oldl);
754 }
755
756 /**
757 * Removes the old mouse-motion-listener from mouse-motion-listener-l
758 * and returns the resulting multicast listener.
759 * @param l mouse-motion-listener-l
760 * @param oldl the mouse-motion-listener being removed
761 */
762 public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) {
763 return (MouseMotionListener) removeInternal(l, oldl);
764 }
765
766 /**
767 * Removes the old window-listener from window-listener-l and
768 * returns the resulting multicast listener.
769 * @param l window-listener-l
770 * @param oldl the window-listener being removed
771 */
772 public static WindowListener remove(WindowListener l, WindowListener oldl) {
773 return (WindowListener) removeInternal(l, oldl);
774 }
775
776 /**
777 * Removes the old window-state-listener from window-state-listener-l
778 * and returns the resulting multicast listener.
779 * @param l window-state-listener-l
780 * @param oldl the window-state-listener being removed
781 * @since 1.4
782 */
783 public static WindowStateListener remove(WindowStateListener l,
784 WindowStateListener oldl) {
785 return (WindowStateListener) removeInternal(l, oldl);
786 }
787
788 /**
789 * Removes the old window-focus-listener from window-focus-listener-l
790 * and returns the resulting multicast listener.
791 * @param l window-focus-listener-l
792 * @param oldl the window-focus-listener being removed
793 * @since 1.4
794 */
795 public static WindowFocusListener remove(WindowFocusListener l,
796 WindowFocusListener oldl) {
797 return (WindowFocusListener) removeInternal(l, oldl);
798 }
799
800 /**
801 * Removes the old action-listener from action-listener-l and
802 * returns the resulting multicast listener.
803 * @param l action-listener-l
804 * @param oldl the action-listener being removed
805 */
806 public static ActionListener remove(ActionListener l, ActionListener oldl) {
807 return (ActionListener) removeInternal(l, oldl);
808 }
809
810 /**
811 * Removes the old item-listener from item-listener-l and
812 * returns the resulting multicast listener.
813 * @param l item-listener-l
814 * @param oldl the item-listener being removed
815 */
816 public static ItemListener remove(ItemListener l, ItemListener oldl) {
817 return (ItemListener) removeInternal(l, oldl);
818 }
819
820 /**
821 * Removes the old adjustment-listener from adjustment-listener-l and
822 * returns the resulting multicast listener.
823 * @param l adjustment-listener-l
824 * @param oldl the adjustment-listener being removed
825 */
826 public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) {
827 return (AdjustmentListener) removeInternal(l, oldl);
828 }
829 public static TextListener remove(TextListener l, TextListener oldl) {
830 return (TextListener) removeInternal(l, oldl);
831 }
832
833 /**
834 * Removes the old input-method-listener from input-method-listener-l and
835 * returns the resulting multicast listener.
836 * @param l input-method-listener-l
837 * @param oldl the input-method-listener being removed
838 */
839 public static InputMethodListener remove(InputMethodListener l, InputMethodListener oldl) {
840 return (InputMethodListener) removeInternal(l, oldl);
841 }
842
843 /**
844 * Removes the old hierarchy-listener from hierarchy-listener-l and
845 * returns the resulting multicast listener.
846 * @param l hierarchy-listener-l
847 * @param oldl the hierarchy-listener being removed
848 * @since 1.3
849 */
850 public static HierarchyListener remove(HierarchyListener l, HierarchyListener oldl) {
851 return (HierarchyListener) removeInternal(l, oldl);
852 }
853
854 /**
855 * Removes the old hierarchy-bounds-listener from
856 * hierarchy-bounds-listener-l and returns the resulting multicast
857 * listener.
858 * @param l hierarchy-bounds-listener-l
859 * @param oldl the hierarchy-bounds-listener being removed
860 * @since 1.3
861 */
862 public static HierarchyBoundsListener remove(HierarchyBoundsListener l, HierarchyBoundsListener oldl) {
863 return (HierarchyBoundsListener) removeInternal(l, oldl);
864 }
865
866 /**
867 * Removes the old mouse-wheel-listener from mouse-wheel-listener-l
868 * and returns the resulting multicast listener.
869 * @param l mouse-wheel-listener-l
870 * @param oldl the mouse-wheel-listener being removed
871 * @since 1.4
872 */
873 public static MouseWheelListener remove(MouseWheelListener l,
874 MouseWheelListener oldl) {
875 return (MouseWheelListener) removeInternal(l, oldl);
876 }
877
878 /**
879 * Returns the resulting multicast listener from adding listener-a
880 * and listener-b together.
881 * If listener-a is null, it returns listener-b;
882 * If listener-b is null, it returns listener-a
883 * If neither are null, then it creates and returns
884 * a new AWTEventMulticaster instance which chains a with b.
885 * @param a event listener-a
886 * @param b event listener-b
887 */
888 protected static EventListener addInternal(EventListener a, EventListener b) {
889 if (a == null) return b;
890 if (b == null) return a;
891 return new AWTEventMulticaster(a, b);
892 }
893
894 /**
895 * Returns the resulting multicast listener after removing the
896 * old listener from listener-l.
897 * If listener-l equals the old listener OR listener-l is null,
898 * returns null.
899 * Else if listener-l is an instance of AWTEventMulticaster,
900 * then it removes the old listener from it.
901 * Else, returns listener l.
902 * @param l the listener being removed from
903 * @param oldl the listener being removed
904 */
905 protected static EventListener removeInternal(EventListener l, EventListener oldl) {
906 if (l == oldl || l == null) {
907 return null;
908 } else if (l instanceof AWTEventMulticaster) {
909 return ((AWTEventMulticaster)l).remove(oldl);
910 } else {
911 return l; // it's not here
912 }
913 }
914
915
916 /* Serialization support.
917 */
918
919 protected void saveInternal(ObjectOutputStream s, String k) throws IOException {
920 if (a instanceof AWTEventMulticaster) {
921 ((AWTEventMulticaster)a).saveInternal(s, k);
922 }
923 else if (a instanceof Serializable) {
924 s.writeObject(k);
925 s.writeObject(a);
926 }
927
928 if (b instanceof AWTEventMulticaster) {
929 ((AWTEventMulticaster)b).saveInternal(s, k);
930 }
931 else if (b instanceof Serializable) {
932 s.writeObject(k);
933 s.writeObject(b);
934 }
935 }
936
937 protected static void save(ObjectOutputStream s, String k, EventListener l) throws IOException {
938 if (l == null) {
939 return;
940 }
941 else if (l instanceof AWTEventMulticaster) {
942 ((AWTEventMulticaster)l).saveInternal(s, k);
943 }
944 else if (l instanceof Serializable) {
945 s.writeObject(k);
946 s.writeObject(l);
947 }
948 }
949
950 /*
951 * Recursive method which returns a count of the number of listeners in
952 * EventListener, handling the (common) case of l actually being an
953 * AWTEventMulticaster. Additionally, only listeners of type listenerType
954 * are counted. Method modified to fix bug 4513402. -bchristi
955 */
956 private static int getListenerCount(EventListener l, Class listenerType) {
957 if (l instanceof AWTEventMulticaster) {
958 AWTEventMulticaster mc = (AWTEventMulticaster)l;
959 return getListenerCount(mc.a, listenerType) +
960 getListenerCount(mc.b, listenerType);
961 }
962 else {
963 // Only count listeners of correct type
964 return listenerType.isInstance(l) ? 1 : 0;
965 }
966 }
967
968 /*
969 * Recusive method which populates EventListener array a with EventListeners
970 * from l. l is usually an AWTEventMulticaster. Bug 4513402 revealed that
971 * if l differed in type from the element type of a, an ArrayStoreException
972 * would occur. Now l is only inserted into a if it's of the appropriate
973 * type. -bchristi
974 */
975 private static int populateListenerArray(EventListener[] a, EventListener l, int index) {
976 if (l instanceof AWTEventMulticaster) {
977 AWTEventMulticaster mc = (AWTEventMulticaster)l;
978 int lhs = populateListenerArray(a, mc.a, index);
979 return populateListenerArray(a, mc.b, lhs);
980 }
981 else if (a.getClass().getComponentType().isInstance(l)) {
982 a[index] = l;
983 return index + 1;
984 }
985 // Skip nulls, instances of wrong class
986 else {
987 return index;
988 }
989 }
990
991 /**
992 * Returns an array of all the objects chained as
993 * <code><em>Foo</em>Listener</code>s by the specified
994 * <code>java.util.EventListener</code>.
995 * <code><em>Foo</em>Listener</code>s are chained by the
996 * <code>AWTEventMulticaster</code> using the
997 * <code>add<em>Foo</em>Listener</code> method.
998 * If a <code>null</code> listener is specified, this method returns an
999 * empty array. If the specified listener is not an instance of
1000 * <code>AWTEventMulticaster</code>, this method returns an array which
1001 * contains only the specified listener. If no such listeners are chanined,
1002 * this method returns an empty array.
1003 *
1004 * @param l the specified <code>java.util.EventListener</code>
1005 * @param listenerType the type of listeners requested; this parameter
1006 * should specify an interface that descends from
1007 * <code>java.util.EventListener</code>
1008 * @return an array of all objects chained as
1009 * <code><em>Foo</em>Listener</code>s by the specified multicast
1010 * listener, or an empty array if no such listeners have been
1011 * chained by the specified multicast listener
1012 * @exception NullPointerException if the specified
1013 * {@code listenertype} parameter is {@code null}
1014 * @exception ClassCastException if <code>listenerType</code>
1015 * doesn't specify a class or interface that implements
1016 * <code>java.util.EventListener</code>
1017 *
1018 * @since 1.4
1019 */
1020 public static <T extends EventListener> T[]
1021 getListeners(EventListener l, Class<T> listenerType)
1022 {
1023 if (listenerType == null) {
1024 throw new NullPointerException ("Listener type should not be null");
1025 }
1026
1027 int n = getListenerCount(l, listenerType);
1028 T[] result = (T[])Array.newInstance(listenerType, n);
1029 populateListenerArray(result, l, 0);
1030 return result;
1031 }
1032 }