1 /* AWTEventMulticaster.java -- allows multicast chaining of listeners
2    Copyright (C) 1999, 2000, 2002 Free Software Foundation
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package java.awt;
40 
41 import java.awt.event.ActionEvent;
42 import java.awt.event.ActionListener;
43 import java.awt.event.AdjustmentEvent;
44 import java.awt.event.AdjustmentListener;
45 import java.awt.event.ComponentEvent;
46 import java.awt.event.ComponentListener;
47 import java.awt.event.ContainerEvent;
48 import java.awt.event.ContainerListener;
49 import java.awt.event.FocusEvent;
50 import java.awt.event.FocusListener;
51 import java.awt.event.HierarchyBoundsListener;
52 import java.awt.event.HierarchyEvent;
53 import java.awt.event.HierarchyListener;
54 import java.awt.event.InputMethodEvent;
55 import java.awt.event.InputMethodListener;
56 import java.awt.event.ItemEvent;
57 import java.awt.event.ItemListener;
58 import java.awt.event.KeyEvent;
59 import java.awt.event.KeyListener;
60 import java.awt.event.MouseEvent;
61 import java.awt.event.MouseListener;
62 import java.awt.event.MouseMotionListener;
63 import java.awt.event.MouseWheelEvent;
64 import java.awt.event.MouseWheelListener;
65 import java.awt.event.TextEvent;
66 import java.awt.event.TextListener;
67 import java.awt.event.WindowEvent;
68 import java.awt.event.WindowFocusListener;
69 import java.awt.event.WindowListener;
70 import java.awt.event.WindowStateListener;
71 import java.io.IOException;
72 import java.io.ObjectOutputStream;
73 import java.io.Serializable;
74 import java.lang.reflect.Array;
75 import java.util.ArrayList;
76 import java.util.EventListener;
77 
78 /**
79  * This class is used to implement a chain of event handlers.  Dispatching
80  * using this class is thread safe.  Here is a quick example of how to
81  * add and delete listeners using this class.  For this example, we will
82  * assume are firing <code>AdjustmentEvent</code>'s.  However, this
83  * same approach is useful for all events in the <code>java.awt.event</code>
84  * package, and more if this class is subclassed.
85  *
86  * <p><code>
87  * AdjustmentListener al;
88  * public void addAdjustmentListener(AdjustmentListener listener)
89  * {
90  *   al = AWTEventMulticaster.add(al, listener);
91  * }
92  * public void removeAdjustmentListener(AdjustmentListener listener)
93  * {
94  *   al = AWTEventMulticaster.remove(al, listener);
95  * }
96  * </code>
97  *
98  * <p>When it come time to process an event, simply call <code>al</code>,
99  * assuming it is not <code>null</code>, and all listeners in the chain will
100  * be fired.
101  *
102  * <p>The first time <code>add</code> is called it is passed
103  * <code>null</code> and <code>listener</code> as its arguments.  This
104  * starts building the chain.  This class returns <code>listener</code>
105  * which becomes the new <code>al</code>.  The next time, <code>add</code>
106  * is called with <code>al</code> and <code>listener</code> and the
107  * new listener is then chained to the old.
108  *
109  * @author Bryce McKinlay
110  * @author Aaron M. Renn <arenn@urbanophile.com>
111  * @author Eric Blake <ebb9@email.byu.edu>
112  * @since 1.1
113  * @status updated to 1.4
114  */
115 public class AWTEventMulticaster
116   implements ComponentListener, ContainerListener, FocusListener, KeyListener,
117              MouseListener, MouseMotionListener, WindowListener,
118              WindowFocusListener, WindowStateListener, ActionListener,
119              ItemListener, AdjustmentListener, TextListener,
120              InputMethodListener, HierarchyListener, HierarchyBoundsListener,
121              MouseWheelListener
122 {
123   /**
124    * A variable in the event chain.
125    */
126   protected final EventListener a;
127 
128   /**
129    * A variable in the event chain.
130    */
131   protected final EventListener b;
132 
133   /**
134    * Initializes a new instance of <code>AWTEventMulticaster</code> with
135    * the specified event listener parameters. The parameters should not be
136    * null, although it is not required to enforce this with a
137    * NullPointerException.
138    *
139    * @param a the "a" listener object
140    * @param b the "b" listener object
141    */
AWTEventMulticaster(EventListener a, EventListener b)142   protected AWTEventMulticaster(EventListener a, EventListener b)
143   {
144     this.a = a;
145     this.b = b;
146   }
147 
148   /**
149    * Removes one instance of the specified listener from this multicaster
150    * chain. This descends recursively if either child is a multicaster, and
151    * returns a multicaster chain with the old listener removed.
152    *
153    * @param oldl the object to remove from this multicaster
154    * @return the resulting multicaster with the specified listener removed
155    */
remove(EventListener oldl)156   protected EventListener remove(EventListener oldl)
157   {
158     // If oldl is an immediate child, return the other child.
159     if (a == oldl)
160       return b;
161     if (b == oldl)
162       return a;
163     // If a and/or b are Multicaster's, search them recursively.
164     if (a instanceof AWTEventMulticaster)
165       {
166         EventListener newa = ((AWTEventMulticaster) a).remove(oldl);
167         if (newa != a)
168           return new AWTEventMulticaster(newa, b);
169       }
170     if (b instanceof AWTEventMulticaster)
171       {
172         EventListener newb = ((AWTEventMulticaster) b).remove(oldl);
173         if (newb != b)
174           return new AWTEventMulticaster(a, newb);
175       }
176     // oldl was not found.
177     return this;
178   }
179 
180   /**
181    * Handles this event by dispatching it to the "a" and "b" listener
182    * instances.
183    *
184    * @param event the event to handle
185    */
componentResized(ComponentEvent e)186   public void componentResized(ComponentEvent e)
187   {
188     ((ComponentListener) a).componentResized(e);
189     ((ComponentListener) b).componentResized(e);
190   }
191 
192   /**
193    * Handles this event by dispatching it to the "a" and "b" listener
194    * instances.
195    *
196    * @param event the event to handle
197    */
componentMoved(ComponentEvent e)198   public void componentMoved(ComponentEvent e)
199   {
200     ((ComponentListener) a).componentMoved(e);
201     ((ComponentListener) b).componentMoved(e);
202   }
203 
204   /**
205    * Handles this event by dispatching it to the "a" and "b" listener
206    * instances.
207    *
208    * @param event the event to handle
209    */
componentShown(ComponentEvent e)210   public void componentShown(ComponentEvent e)
211   {
212     ((ComponentListener) a).componentShown(e);
213     ((ComponentListener) b).componentShown(e);
214   }
215 
216   /**
217    * Handles this event by dispatching it to the "a" and "b" listener
218    * instances.
219    *
220    * @param event the event to handle
221    */
componentHidden(ComponentEvent e)222   public void componentHidden(ComponentEvent e)
223   {
224     ((ComponentListener) a).componentHidden(e);
225     ((ComponentListener) b).componentHidden(e);
226   }
227 
228   /**
229    * Handles this event by dispatching it to the "a" and "b" listener
230    * instances.
231    *
232    * @param event the event to handle
233    */
componentAdded(ContainerEvent e)234   public void componentAdded(ContainerEvent e)
235   {
236     ((ContainerListener) a).componentAdded(e);
237     ((ContainerListener) b).componentAdded(e);
238   }
239 
240   /**
241    * Handles this event by dispatching it to the "a" and "b" listener
242    * instances.
243    *
244    * @param event the event to handle
245    */
componentRemoved(ContainerEvent e)246   public void componentRemoved(ContainerEvent e)
247   {
248     ((ContainerListener) a).componentRemoved(e);
249     ((ContainerListener) b).componentRemoved(e);
250   }
251 
252   /**
253    * Handles this event by dispatching it to the "a" and "b" listener
254    * instances.
255    *
256    * @param event the event to handle
257    */
focusGained(FocusEvent e)258   public void focusGained(FocusEvent e)
259   {
260     ((FocusListener) a).focusGained(e);
261     ((FocusListener) b).focusGained(e);
262   }
263 
264   /**
265    * Handles this event by dispatching it to the "a" and "b" listener
266    * instances.
267    *
268    * @param event the event to handle
269    */
focusLost(FocusEvent e)270   public void focusLost(FocusEvent e)
271   {
272     ((FocusListener) a).focusLost(e);
273     ((FocusListener) b).focusLost(e);
274   }
275 
276   /**
277    * Handles this event by dispatching it to the "a" and "b" listener
278    * instances.
279    *
280    * @param event the event to handle
281    */
keyTyped(KeyEvent e)282   public void keyTyped(KeyEvent e)
283   {
284     ((KeyListener) a).keyTyped(e);
285     ((KeyListener) b).keyTyped(e);
286   }
287 
288   /**
289    * Handles this event by dispatching it to the "a" and "b" listener
290    * instances.
291    *
292    * @param event the event to handle
293    */
keyPressed(KeyEvent e)294   public void keyPressed(KeyEvent e)
295   {
296     ((KeyListener) a).keyPressed(e);
297     ((KeyListener) b).keyPressed(e);
298   }
299 
300   /**
301    * Handles this event by dispatching it to the "a" and "b" listener
302    * instances.
303    *
304    * @param event the event to handle
305    */
keyReleased(KeyEvent e)306   public void keyReleased(KeyEvent e)
307   {
308     ((KeyListener) a).keyReleased(e);
309     ((KeyListener) b).keyReleased(e);
310   }
311 
312   /**
313    * Handles this event by dispatching it to the "a" and "b" listener
314    * instances.
315    *
316    * @param event the event to handle
317    */
mouseClicked(MouseEvent e)318   public void mouseClicked(MouseEvent e)
319   {
320     ((MouseListener) a).mouseClicked(e);
321     ((MouseListener) b).mouseClicked(e);
322   }
323 
324   /**
325    * Handles this event by dispatching it to the "a" and "b" listener
326    * instances.
327    *
328    * @param event the event to handle
329    */
mousePressed(MouseEvent e)330   public void mousePressed(MouseEvent e)
331   {
332     ((MouseListener) a).mousePressed(e);
333     ((MouseListener) b).mousePressed(e);
334   }
335 
336   /**
337    * Handles this event by dispatching it to the "a" and "b" listener
338    * instances.
339    *
340    * @param event the event to handle
341    */
mouseReleased(MouseEvent e)342   public void mouseReleased(MouseEvent e)
343   {
344     ((MouseListener) a).mouseReleased(e);
345     ((MouseListener) b).mouseReleased(e);
346   }
347 
348   /**
349    * Handles this event by dispatching it to the "a" and "b" listener
350    * instances.
351    *
352    * @param event the event to handle
353    */
mouseEntered(MouseEvent e)354   public void mouseEntered(MouseEvent e)
355   {
356     ((MouseListener) a).mouseEntered(e);
357     ((MouseListener) b).mouseEntered(e);
358   }
359 
360   /**
361    * Handles this event by dispatching it to the "a" and "b" listener
362    * instances.
363    *
364    * @param event the event to handle
365    */
mouseExited(MouseEvent e)366   public void mouseExited(MouseEvent e)
367   {
368     ((MouseListener) a).mouseExited(e);
369     ((MouseListener) b).mouseExited(e);
370   }
371 
372   /**
373    * Handles this event by dispatching it to the "a" and "b" listener
374    * instances.
375    *
376    * @param event the event to handle
377    */
mouseDragged(MouseEvent e)378   public void mouseDragged(MouseEvent e)
379   {
380     ((MouseMotionListener) a).mouseDragged(e);
381     ((MouseMotionListener) b).mouseDragged(e);
382   }
383 
384   /**
385    * Handles this event by dispatching it to the "a" and "b" listener
386    * instances.
387    *
388    * @param event the event to handle
389    */
mouseMoved(MouseEvent e)390   public void mouseMoved(MouseEvent e)
391   {
392     ((MouseMotionListener) a).mouseMoved(e);
393     ((MouseMotionListener) b).mouseMoved(e);
394   }
395 
396   /**
397    * Handles this event by dispatching it to the "a" and "b" listener
398    * instances.
399    *
400    * @param event the event to handle
401    */
windowOpened(WindowEvent e)402   public void windowOpened(WindowEvent e)
403   {
404     ((WindowListener) a).windowOpened(e);
405     ((WindowListener) b).windowOpened(e);
406   }
407 
408   /**
409    * Handles this event by dispatching it to the "a" and "b" listener
410    * instances.
411    *
412    * @param event the event to handle
413    */
windowClosing(WindowEvent e)414   public void windowClosing(WindowEvent e)
415   {
416     ((WindowListener) a).windowClosing(e);
417     ((WindowListener) b).windowClosing(e);
418   }
419 
420   /**
421    * Handles this event by dispatching it to the "a" and "b" listener
422    * instances.
423    *
424    * @param event the event to handle
425    */
windowClosed(WindowEvent e)426   public void windowClosed(WindowEvent e)
427   {
428     ((WindowListener) a).windowClosed(e);
429     ((WindowListener) b).windowClosed(e);
430   }
431 
432   /**
433    * Handles this event by dispatching it to the "a" and "b" listener
434    * instances.
435    *
436    * @param event the event to handle
437    */
windowIconified(WindowEvent e)438   public void windowIconified(WindowEvent e)
439   {
440     ((WindowListener) a).windowIconified(e);
441     ((WindowListener) b).windowIconified(e);
442   }
443 
444   /**
445    * Handles this event by dispatching it to the "a" and "b" listener
446    * instances.
447    *
448    * @param event the event to handle
449    */
windowDeiconified(WindowEvent e)450   public void windowDeiconified(WindowEvent e)
451   {
452     ((WindowListener) a).windowDeiconified(e);
453     ((WindowListener) b).windowDeiconified(e);
454   }
455 
456   /**
457    * Handles this event by dispatching it to the "a" and "b" listener
458    * instances.
459    *
460    * @param event the event to handle
461    */
windowActivated(WindowEvent e)462   public void windowActivated(WindowEvent e)
463   {
464     ((WindowListener) a).windowActivated(e);
465     ((WindowListener) b).windowActivated(e);
466   }
467 
468   /**
469    * Handles this event by dispatching it to the "a" and "b" listener
470    * instances.
471    *
472    * @param event the event to handle
473    */
windowDeactivated(WindowEvent e)474   public void windowDeactivated(WindowEvent e)
475   {
476     ((WindowListener) a).windowDeactivated(e);
477     ((WindowListener) b).windowDeactivated(e);
478   }
479 
480   /**
481    * Handles this event by dispatching it to the "a" and "b" listener
482    * instances.
483    *
484    * @param event the event to handle
485    * @since 1.4
486    */
windowStateChanged(WindowEvent e)487   public void windowStateChanged(WindowEvent e)
488   {
489     ((WindowStateListener) a).windowStateChanged(e);
490     ((WindowStateListener) b).windowStateChanged(e);
491   }
492 
493   /**
494    * Handles this event by dispatching it to the "a" and "b" listener
495    * instances.
496    *
497    * @param event the event to handle
498    * @since 1.4
499    */
windowGainedFocus(WindowEvent e)500   public void windowGainedFocus(WindowEvent e)
501   {
502     ((WindowFocusListener) a).windowGainedFocus(e);
503     ((WindowFocusListener) b).windowGainedFocus(e);
504   }
505 
506   /**
507    * Handles this event by dispatching it to the "a" and "b" listener
508    * instances.
509    *
510    * @param event the event to handle
511    * @since 1.4
512    */
windowLostFocus(WindowEvent e)513   public void windowLostFocus(WindowEvent e)
514   {
515     ((WindowFocusListener) a).windowLostFocus(e);
516     ((WindowFocusListener) b).windowLostFocus(e);
517   }
518 
519   /**
520    * Handles this event by dispatching it to the "a" and "b" listener
521    * instances.
522    *
523    * @param event the event to handle
524    */
actionPerformed(ActionEvent e)525   public void actionPerformed(ActionEvent e)
526   {
527     ((ActionListener) a).actionPerformed(e);
528     ((ActionListener) b).actionPerformed(e);
529   }
530 
531   /**
532    * Handles this event by dispatching it to the "a" and "b" listener
533    * instances.
534    *
535    * @param event the event to handle
536    */
itemStateChanged(ItemEvent e)537   public void itemStateChanged(ItemEvent e)
538   {
539     ((ItemListener) a).itemStateChanged(e);
540     ((ItemListener) b).itemStateChanged(e);
541   }
542 
543   /**
544    * Handles this event by dispatching it to the "a" and "b" listener
545    * instances.
546    *
547    * @param event the event to handle
548    */
adjustmentValueChanged(AdjustmentEvent e)549   public void adjustmentValueChanged(AdjustmentEvent e)
550   {
551     ((AdjustmentListener) a).adjustmentValueChanged(e);
552     ((AdjustmentListener) b).adjustmentValueChanged(e);
553   }
554 
555   /**
556    * Handles this event by dispatching it to the "a" and "b" listener
557    * instances.
558    *
559    * @param event the event to handle
560    */
textValueChanged(TextEvent e)561   public void textValueChanged(TextEvent e)
562   {
563     ((TextListener) a).textValueChanged(e);
564     ((TextListener) b).textValueChanged(e);
565   }
566 
567   /**
568    * Handles this event by dispatching it to the "a" and "b" listener
569    * instances.
570    *
571    * @param event the event to handle
572    * @since 1.2
573    */
inputMethodTextChanged(InputMethodEvent e)574   public void inputMethodTextChanged(InputMethodEvent e)
575   {
576     ((InputMethodListener) a).inputMethodTextChanged(e);
577     ((InputMethodListener) b).inputMethodTextChanged(e);
578   }
579 
580   /**
581    * Handles this event by dispatching it to the "a" and "b" listener
582    * instances.
583    *
584    * @param event the event to handle
585    * @since 1.2
586    */
caretPositionChanged(InputMethodEvent e)587   public void caretPositionChanged(InputMethodEvent e)
588   {
589     ((InputMethodListener) a).caretPositionChanged(e);
590     ((InputMethodListener) b).caretPositionChanged(e);
591   }
592 
593   /**
594    * Handles this event by dispatching it to the "a" and "b" listener
595    * instances.
596    *
597    * @param event the event to handle
598    * @since 1.3
599    */
hierarchyChanged(HierarchyEvent e)600   public void hierarchyChanged(HierarchyEvent e)
601   {
602     ((HierarchyListener) a).hierarchyChanged(e);
603     ((HierarchyListener) b).hierarchyChanged(e);
604   }
605 
606   /**
607    * Handles this event by dispatching it to the "a" and "b" listener
608    * instances.
609    *
610    * @param event the event to handle
611    * @since 1.3
612    */
ancestorMoved(HierarchyEvent e)613   public void ancestorMoved(HierarchyEvent e)
614   {
615     ((HierarchyBoundsListener) a).ancestorMoved(e);
616     ((HierarchyBoundsListener) b).ancestorMoved(e);
617   }
618 
619   /**
620    * Handles this event by dispatching it to the "a" and "b" listener
621    * instances.
622    *
623    * @param event the event to handle
624    * @since 1.3
625    */
ancestorResized(HierarchyEvent e)626   public void ancestorResized(HierarchyEvent e)
627   {
628     ((HierarchyBoundsListener) a).ancestorResized(e);
629     ((HierarchyBoundsListener) b).ancestorResized(e);
630   }
631 
632   /**
633    * Handles this event by dispatching it to the "a" and "b" listener
634    * instances.
635    *
636    * @param event the event to handle
637    * @since 1.4
638    */
mouseWheelMoved(MouseWheelEvent e)639   public void mouseWheelMoved(MouseWheelEvent e)
640   {
641     ((MouseWheelListener) a).mouseWheelMoved(e);
642     ((MouseWheelListener) b).mouseWheelMoved(e);
643   }
644 
645   /**
646    * Chain <code>ComponentListener</code> a and b.
647    *
648    * @param a the "a" listener, may be null
649    * @param b the "b" listener, may be null
650    * @return latest entry in the chain
651    */
add(ComponentListener a, ComponentListener b)652   public static ComponentListener add(ComponentListener a, ComponentListener b)
653   {
654     return (ComponentListener) addInternal(a, b);
655   }
656 
657   /**
658    * Chain <code>ContainerListener</code> a and b.
659    *
660    * @param a the "a" listener, may be null
661    * @param b the "b" listener, may be null
662    * @return latest entry in the chain
663    */
add(ContainerListener a, ContainerListener b)664   public static ContainerListener add(ContainerListener a, ContainerListener b)
665   {
666     return (ContainerListener) addInternal(a, b);
667   }
668 
669   /**
670    * Chain <code>FocusListener</code> a and b.
671    *
672    * @param a the "a" listener, may be null
673    * @param b the "b" listener, may be null
674    * @return latest entry in the chain
675    */
add(FocusListener a, FocusListener b)676   public static FocusListener add(FocusListener a, FocusListener b)
677   {
678     return (FocusListener) addInternal(a, b);
679   }
680 
681   /**
682    * Chain <code>KeyListener</code> a and b.
683    *
684    * @param a the "a" listener, may be null
685    * @param b the "b" listener, may be null
686    * @return latest entry in the chain
687    */
add(KeyListener a, KeyListener b)688   public static KeyListener add(KeyListener a, KeyListener b)
689   {
690     return (KeyListener) addInternal(a, b);
691   }
692 
693   /**
694    * Chain <code>MouseListener</code> a and b.
695    *
696    * @param a the "a" listener, may be null
697    * @param b the "b" listener, may be null
698    * @return latest entry in the chain
699    */
add(MouseListener a, MouseListener b)700   public static MouseListener add(MouseListener a, MouseListener b)
701   {
702     return (MouseListener) addInternal(a, b);
703   }
704 
705   /**
706    * Chain <code>MouseMotionListener</code> a and b.
707    *
708    * @param a the "a" listener, may be null
709    * @param b the "b" listener, may be null
710    * @return latest entry in the chain
711    */
add(MouseMotionListener a, MouseMotionListener b)712   public static MouseMotionListener add(MouseMotionListener a,
713                                         MouseMotionListener b)
714   {
715     return (MouseMotionListener) addInternal(a, b);
716   }
717 
718   /**
719    * Chain <code>WindowListener</code> a and b.
720    *
721    * @param a the "a" listener, may be null
722    * @param b the "b" listener, may be null
723    * @return latest entry in the chain
724    */
add(WindowListener a, WindowListener b)725   public static WindowListener add(WindowListener a, WindowListener b)
726   {
727     return (WindowListener) addInternal(a, b);
728   }
729 
730   /**
731    * Chain <code>WindowStateListener</code> a and b.
732    *
733    * @param a the "a" listener, may be null
734    * @param b the "b" listener, may be null
735    * @return latest entry in the chain
736    * @since 1.4
737    */
add(WindowStateListener a, WindowStateListener b)738   public static WindowStateListener add(WindowStateListener a,
739                                         WindowStateListener b)
740   {
741     return (WindowStateListener) addInternal(a, b);
742   }
743 
744   /**
745    * Chain <code>WindowFocusListener</code> a and b.
746    *
747    * @param a the "a" listener, may be null
748    * @param b the "b" listener, may be null
749    * @return latest entry in the chain
750    * @since 1.4
751    */
add(WindowFocusListener a, WindowFocusListener b)752   public static WindowFocusListener add(WindowFocusListener a,
753                                         WindowFocusListener b)
754   {
755     return (WindowFocusListener) addInternal(a, b);
756   }
757 
758   /**
759    * Chain <code>ActionListener</code> a and b.
760    *
761    * @param a the "a" listener, may be null
762    * @param b the "b" listener, may be null
763    * @return latest entry in the chain
764    */
add(ActionListener a, ActionListener b)765   public static ActionListener add(ActionListener a, ActionListener b)
766   {
767     return (ActionListener) addInternal(a, b);
768   }
769 
770   /**
771    * Chain <code>ItemListener</code> a and b.
772    *
773    * @param a the "a" listener, may be null
774    * @param b the "b" listener, may be null
775    * @return latest entry in the chain
776    */
add(ItemListener a, ItemListener b)777   public static ItemListener add(ItemListener a, ItemListener b)
778   {
779     return (ItemListener) addInternal(a, b);
780   }
781 
782   /**
783    * Chain <code>AdjustmentListener</code> a and b.
784    *
785    * @param a the "a" listener, may be null
786    * @param b the "b" listener, may be null
787    * @return latest entry in the chain
788    */
add(AdjustmentListener a, AdjustmentListener b)789   public static AdjustmentListener add(AdjustmentListener a,
790                                        AdjustmentListener b)
791   {
792     return (AdjustmentListener) addInternal(a, b);
793   }
794 
795   /**
796    * Chain <code>AdjustmentListener</code> a and b.
797    *
798    * @param a the "a" listener, may be null
799    * @param b the "b" listener, may be null
800    * @return latest entry in the chain
801    */
add(TextListener a, TextListener b)802   public static TextListener add(TextListener a, TextListener b)
803   {
804     return (TextListener) addInternal(a, b);
805   }
806 
807   /**
808    * Chain <code>InputMethodListener</code> a and b.
809    *
810    * @param a the "a" listener, may be null
811    * @param b the "b" listener, may be null
812    * @return latest entry in the chain
813    * @since 1.2
814    */
add(InputMethodListener a, InputMethodListener b)815   public static InputMethodListener add(InputMethodListener a,
816                                         InputMethodListener b)
817   {
818     return (InputMethodListener) addInternal(a, b);
819   }
820 
821   /**
822    * Chain <code>HierarchyListener</code> a and b.
823    *
824    * @param a the "a" listener, may be null
825    * @param b the "b" listener, may be null
826    * @return latest entry in the chain
827    * @since 1.3
828    */
add(HierarchyListener a, HierarchyListener b)829   public static HierarchyListener add(HierarchyListener a, HierarchyListener b)
830   {
831     return (HierarchyListener) addInternal(a, b);
832   }
833 
834   /**
835    * Chain <code>HierarchyBoundsListener</code> a and b.
836    *
837    * @param a the "a" listener, may be null
838    * @param b the "b" listener, may be null
839    * @return latest entry in the chain
840    * @since 1.3
841    */
add(HierarchyBoundsListener a, HierarchyBoundsListener b)842   public static HierarchyBoundsListener add(HierarchyBoundsListener a,
843                                             HierarchyBoundsListener b)
844   {
845     return (HierarchyBoundsListener) addInternal(a, b);
846   }
847 
848   /**
849    * Chain <code>MouseWheelListener</code> a and b.
850    *
851    * @param a the "a" listener, may be null
852    * @param b the "b" listener, may be null
853    * @return latest entry in the chain
854    * @since 1.4
855    */
add(MouseWheelListener a, MouseWheelListener b)856   public static MouseWheelListener add(MouseWheelListener a,
857                                        MouseWheelListener b)
858   {
859     return (MouseWheelListener) addInternal(a, b);
860   }
861 
862   /**
863    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
864    *
865    * @param l the listener chain to reduce
866    * @param oldl the listener to remove
867    * @return the resulting listener chain
868    */
remove(ComponentListener l, ComponentListener oldl)869   public static ComponentListener remove(ComponentListener l,
870                                          ComponentListener oldl)
871   {
872     return (ComponentListener) removeInternal(l, oldl);
873   }
874 
875   /**
876    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
877    *
878    * @param l the listener chain to reduce
879    * @param oldl the listener to remove
880    * @return the resulting listener chain
881    */
remove(ContainerListener l, ContainerListener oldl)882   public static ContainerListener remove(ContainerListener l,
883                                          ContainerListener oldl)
884   {
885     return (ContainerListener) removeInternal(l, oldl);
886   }
887 
888   /**
889    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
890    *
891    * @param l the listener chain to reduce
892    * @param oldl the listener to remove
893    * @return the resulting listener chain
894    */
remove(FocusListener l, FocusListener oldl)895   public static FocusListener remove(FocusListener l, FocusListener oldl)
896   {
897     return (FocusListener) removeInternal(l, oldl);
898   }
899 
900   /**
901    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
902    *
903    * @param l the listener chain to reduce
904    * @param oldl the listener to remove
905    * @return the resulting listener chain
906    */
remove(KeyListener l, KeyListener oldl)907   public static KeyListener remove(KeyListener l, KeyListener oldl)
908   {
909     return (KeyListener) removeInternal(l, oldl);
910   }
911 
912   /**
913    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
914    *
915    * @param l the listener chain to reduce
916    * @param oldl the listener to remove
917    * @return the resulting listener chain
918    */
remove(MouseListener l, MouseListener oldl)919   public static MouseListener remove(MouseListener l, MouseListener oldl)
920   {
921     return (MouseListener) removeInternal(l, oldl);
922   }
923 
924   /**
925    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
926    *
927    * @param l the listener chain to reduce
928    * @param oldl the listener to remove
929    * @return the resulting listener chain
930    */
remove(MouseMotionListener l, MouseMotionListener oldl)931   public static MouseMotionListener remove(MouseMotionListener l,
932                                            MouseMotionListener oldl)
933   {
934     return (MouseMotionListener) removeInternal(l, oldl);
935   }
936 
937   /**
938    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
939    *
940    * @param l the listener chain to reduce
941    * @param oldl the listener to remove
942    * @return the resulting listener chain
943    */
remove(WindowListener l, WindowListener oldl)944   public static WindowListener remove(WindowListener l, WindowListener oldl)
945   {
946     return (WindowListener) removeInternal(l, oldl);
947   }
948 
949   /**
950    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
951    *
952    * @param l the listener chain to reduce
953    * @param oldl the listener to remove
954    * @return the resulting listener chain
955    * @since 1.4
956    */
remove(WindowStateListener l, WindowStateListener oldl)957   public static WindowStateListener remove(WindowStateListener l,
958                                            WindowStateListener oldl)
959   {
960     return (WindowStateListener) removeInternal(l, oldl);
961   }
962 
963   /**
964    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
965    *
966    * @param l the listener chain to reduce
967    * @param oldl the listener to remove
968    * @return the resulting listener chain
969    * @since 1.4
970    */
remove(WindowFocusListener l, WindowFocusListener oldl)971   public static WindowFocusListener remove(WindowFocusListener l,
972                                            WindowFocusListener oldl)
973   {
974     return (WindowFocusListener) removeInternal(l, oldl);
975   }
976 
977   /**
978    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
979    *
980    * @param l the listener chain to reduce
981    * @param oldl the listener to remove
982    * @return the resulting listener chain
983    */
remove(ActionListener l, ActionListener oldl)984   public static ActionListener remove(ActionListener l, ActionListener oldl)
985   {
986     return (ActionListener) removeInternal(l, oldl);
987   }
988 
989   /**
990    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
991    *
992    * @param l the listener chain to reduce
993    * @param oldl the listener to remove
994    * @return the resulting listener chain
995    */
remove(ItemListener l, ItemListener oldl)996   public static ItemListener remove(ItemListener l, ItemListener oldl)
997   {
998     return (ItemListener) removeInternal(l, oldl);
999   }
1000 
1001   /**
1002    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
1003    *
1004    * @param l the listener chain to reduce
1005    * @param oldl the listener to remove
1006    * @return the resulting listener chain
1007    */
remove(AdjustmentListener l, AdjustmentListener oldl)1008   public static AdjustmentListener remove(AdjustmentListener l,
1009                                           AdjustmentListener oldl)
1010   {
1011     return (AdjustmentListener) removeInternal(l, oldl);
1012   }
1013 
1014   /**
1015    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
1016    *
1017    * @param l the listener chain to reduce
1018    * @param oldl the listener to remove
1019    * @return the resulting listener chain
1020    */
remove(TextListener l, TextListener oldl)1021   public static TextListener remove(TextListener l, TextListener oldl)
1022   {
1023     return (TextListener) removeInternal(l, oldl);
1024   }
1025 
1026   /**
1027    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
1028    *
1029    * @param l the listener chain to reduce
1030    * @param oldl the listener to remove
1031    * @return the resulting listener chain
1032    * @since 1.2
1033    */
remove(InputMethodListener l, InputMethodListener oldl)1034   public static InputMethodListener remove(InputMethodListener l,
1035                                            InputMethodListener oldl)
1036   {
1037     return (InputMethodListener) removeInternal(l, oldl);
1038   }
1039 
1040   /**
1041    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
1042    *
1043    * @param l the listener chain to reduce
1044    * @param oldl the listener to remove
1045    * @return the resulting listener chain
1046    * @since 1.3
1047    */
remove(HierarchyListener l, HierarchyListener oldl)1048   public static HierarchyListener remove(HierarchyListener l,
1049                                          HierarchyListener oldl)
1050   {
1051     return (HierarchyListener) removeInternal(l, oldl);
1052   }
1053 
1054   /**
1055    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
1056    *
1057    * @param l the listener chain to reduce
1058    * @param oldl the listener to remove
1059    * @return the resulting listener chain
1060    * @since 1.3
1061    */
remove(HierarchyBoundsListener l, HierarchyBoundsListener oldl)1062   public static HierarchyBoundsListener remove(HierarchyBoundsListener l,
1063                                                HierarchyBoundsListener oldl)
1064   {
1065     return (HierarchyBoundsListener) removeInternal(l, oldl);
1066   }
1067 
1068   /**
1069    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
1070    *
1071    * @param l the listener chain to reduce
1072    * @param oldl the listener to remove
1073    * @return the resulting listener chain
1074    * @since 1.4
1075    */
remove(MouseWheelListener l, MouseWheelListener oldl)1076   public static MouseWheelListener remove(MouseWheelListener l,
1077                                           MouseWheelListener oldl)
1078   {
1079     return (MouseWheelListener) removeInternal(l, oldl);
1080   }
1081 
1082   /**
1083    * Chain <code>EventListener</code> a and b.
1084    *
1085    * @param a the "a" listener, may be null
1086    * @param b the "b" listener, may be null
1087    * @return latest entry in the chain
1088    */
addInternal(EventListener a, EventListener b)1089   protected static EventListener addInternal(EventListener a, EventListener b)
1090   {
1091     if (a == null)
1092       return b;
1093     if (b == null)
1094       return a;
1095     return new AWTEventMulticaster(a, b);
1096   }
1097 
1098   /**
1099    * Removes the listener <code>oldl</code> from the listener <code>l</code>.
1100    *
1101    * @param l the listener chain to reduce
1102    * @param oldl the listener to remove
1103    * @return the resulting listener chain
1104    */
removeInternal(EventListener l, EventListener oldl)1105   protected static EventListener removeInternal(EventListener l,
1106                                                 EventListener oldl)
1107   {
1108     if (l == oldl)
1109       return null;
1110     if (l instanceof AWTEventMulticaster)
1111       return ((AWTEventMulticaster) l).remove(oldl);
1112     return l;
1113   }
1114 
1115   /**
1116    * Saves all Serializable listeners to a serialization stream.
1117    *
1118    * @param s the stream to save to
1119    * @param k a prefix stream put before each serializable listener
1120    * @throws IOException if serialization fails
1121    */
saveInternal(ObjectOutputStream s, String k)1122   protected void saveInternal(ObjectOutputStream s, String k)
1123     throws IOException
1124   {
1125     // This is not documented by Sun, but I think it is correct.
1126     if (a instanceof AWTEventMulticaster)
1127       ((AWTEventMulticaster) a).saveInternal(s, k);
1128     else if (a instanceof Serializable)
1129       {
1130         s.writeObject(k);
1131         s.writeObject(a);
1132       }
1133     if (b instanceof AWTEventMulticaster)
1134       ((AWTEventMulticaster) b).saveInternal(s, k);
1135     else if (b instanceof Serializable)
1136       {
1137         s.writeObject(k);
1138         s.writeObject(b);
1139       }
1140   }
1141 
1142   /**
1143    * Saves a Serializable listener chain to a serialization stream.
1144    *
1145    * @param s the stream to save to
1146    * @param k a prefix stream put before each serializable listener
1147    * @param l the listener chain to save
1148    * @throws IOException if serialization fails
1149    */
save(ObjectOutputStream s, String k, EventListener l)1150   protected static void save(ObjectOutputStream s, String k, EventListener l)
1151     throws IOException
1152   {
1153     // This is not documented by Sun, but I think it is correct.
1154     if (l instanceof AWTEventMulticaster)
1155       ((AWTEventMulticaster) l).saveInternal(s, k);
1156     else if (l instanceof Serializable)
1157       {
1158         s.writeObject(k);
1159         s.writeObject(l);
1160       }
1161   }
1162 
1163   /**
1164    * Returns an array of all chained listeners of the specified type in the
1165    * given chain. A null listener returns an empty array, and a listener
1166    * which is not an AWTEventMulticaster returns an array of one element. If
1167    * no listeners in the chain are of the specified type, an empty array is
1168    * returned.
1169    *
1170    * @param l the listener chain to convert to an array
1171    * @param type the type of listeners to collect
1172    * @return an array of the listeners of that type in the chain
1173    * @throws ClassCastException if type is not assignable from EventListener
1174    * @throws NullPointerException if type is null
1175    * @throws IllegalArgumentException if type is Void.TYPE
1176    * @since 1.4
1177    */
getListeners(EventListener l, Class type)1178   public static EventListener[] getListeners(EventListener l, Class type)
1179   {
1180     ArrayList list = new ArrayList();
1181     if (l instanceof AWTEventMulticaster)
1182       ((AWTEventMulticaster) l).getListeners(list, type);
1183     else if (type.isInstance(l))
1184       list.add(l);
1185     EventListener[] r = (EventListener[]) Array.newInstance(type, list.size());
1186     list.toArray(r);
1187     return r;
1188   }
1189 
1190   /**
1191    * Collects all instances of the given type in the chain into the list.
1192    *
1193    * @param l the list to collect into
1194    * @param type the type of listeners to collect
1195    * @throws NullPointerException if type is null
1196    * @see #getListeners(EventListener, Class)
1197    */
getListeners(ArrayList l, Class type)1198   private void getListeners(ArrayList l, Class type)
1199   {
1200     if (a instanceof AWTEventMulticaster)
1201       ((AWTEventMulticaster) a).getListeners(l, type);
1202     else if (type.isInstance(a))
1203       l.add(a);
1204     if (b instanceof AWTEventMulticaster)
1205       ((AWTEventMulticaster) b).getListeners(l, type);
1206     else if (type.isInstance(b))
1207       l.add(b);
1208   }
1209 } // class AWTEventMulticaster
1210