001    /* AWTEventMulticaster.java -- allows multicast chaining of listeners
002       Copyright (C) 1999, 2000, 2002 Free Software Foundation
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.awt;
040    
041    import java.awt.event.ActionEvent;
042    import java.awt.event.ActionListener;
043    import java.awt.event.AdjustmentEvent;
044    import java.awt.event.AdjustmentListener;
045    import java.awt.event.ComponentEvent;
046    import java.awt.event.ComponentListener;
047    import java.awt.event.ContainerEvent;
048    import java.awt.event.ContainerListener;
049    import java.awt.event.FocusEvent;
050    import java.awt.event.FocusListener;
051    import java.awt.event.HierarchyBoundsListener;
052    import java.awt.event.HierarchyEvent;
053    import java.awt.event.HierarchyListener;
054    import java.awt.event.InputMethodEvent;
055    import java.awt.event.InputMethodListener;
056    import java.awt.event.ItemEvent;
057    import java.awt.event.ItemListener;
058    import java.awt.event.KeyEvent;
059    import java.awt.event.KeyListener;
060    import java.awt.event.MouseEvent;
061    import java.awt.event.MouseListener;
062    import java.awt.event.MouseMotionListener;
063    import java.awt.event.MouseWheelEvent;
064    import java.awt.event.MouseWheelListener;
065    import java.awt.event.TextEvent;
066    import java.awt.event.TextListener;
067    import java.awt.event.WindowEvent;
068    import java.awt.event.WindowFocusListener;
069    import java.awt.event.WindowListener;
070    import java.awt.event.WindowStateListener;
071    import java.io.IOException;
072    import java.io.ObjectOutputStream;
073    import java.io.Serializable;
074    import java.lang.reflect.Array;
075    import java.util.ArrayList;
076    import java.util.EventListener;
077    
078    /**
079     * This class is used to implement a chain of event handlers.  Dispatching
080     * using this class is thread safe.  Here is a quick example of how to
081     * add and delete listeners using this class.  For this example, we will
082     * assume are firing <code>AdjustmentEvent</code>'s.  However, this
083     * same approach is useful for all events in the <code>java.awt.event</code>
084     * package, and more if this class is subclassed.
085     *
086     * <p><code>
087     * AdjustmentListener al;
088     * public void addAdjustmentListener(AdjustmentListener listener)
089     * {
090     *   al = AWTEventMulticaster.add(al, listener);
091     * }
092     * public void removeAdjustmentListener(AdjustmentListener listener)
093     * {
094     *   al = AWTEventMulticaster.remove(al, listener);
095     * }
096     * </code>
097     *
098     * <p>When it come time to process an event, simply call <code>al</code>,
099     * 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       */
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       */
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 e the event to handle
185       */
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 e the event to handle
197       */
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 e the event to handle
209       */
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 e the event to handle
221       */
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 e the event to handle
233       */
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 e the event to handle
245       */
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 e the event to handle
257       */
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 e the event to handle
269       */
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 e the event to handle
281       */
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 e the event to handle
293       */
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 e the event to handle
305       */
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 e the event to handle
317       */
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 e the event to handle
329       */
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 e the event to handle
341       */
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 e the event to handle
353       */
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 e the event to handle
365       */
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 e the event to handle
377       */
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 e the event to handle
389       */
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 e the event to handle
401       */
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 e the event to handle
413       */
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 e the event to handle
425       */
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 e the event to handle
437       */
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 e the event to handle
449       */
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 e the event to handle
461       */
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 e the event to handle
473       */
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 e the event to handle
485       * @since 1.4
486       */
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 e the event to handle
498       * @since 1.4
499       */
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 e the event to handle
511       * @since 1.4
512       */
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 e the event to handle
524       */
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 e the event to handle
536       */
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 e the event to handle
548       */
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 e the event to handle
560       */
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 e the event to handle
572       * @since 1.2
573       */
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 e the event to handle
585       * @since 1.2
586       */
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 e the event to handle
598       * @since 1.3
599       */
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 e the event to handle
611       * @since 1.3
612       */
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 e the event to handle
624       * @since 1.3
625       */
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 e the event to handle
637       * @since 1.4
638       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
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       */
1178      public static <T extends EventListener> T[] getListeners(EventListener l,
1179                                                               Class<T> type)
1180      {
1181        ArrayList<EventListener> list = new ArrayList<EventListener>();
1182        if (l instanceof AWTEventMulticaster)
1183          ((AWTEventMulticaster) l).getListeners(list, type);
1184        else if (type.isInstance(l))
1185          list.add(l);
1186        EventListener[] r = (EventListener[]) Array.newInstance(type, list.size());
1187        list.toArray(r);
1188        return (T[]) r;
1189      }
1190    
1191      /**
1192       * Collects all instances of the given type in the chain into the list.
1193       *
1194       * @param l the list to collect into
1195       * @param type the type of listeners to collect
1196       * @throws NullPointerException if type is null
1197       * @see #getListeners(EventListener, Class)
1198       */
1199      private void getListeners(ArrayList l, Class type)
1200      {
1201        if (a instanceof AWTEventMulticaster)
1202          ((AWTEventMulticaster) a).getListeners(l, type);
1203        else if (type.isInstance(a))
1204          l.add(a);
1205        if (b instanceof AWTEventMulticaster)
1206          ((AWTEventMulticaster) b).getListeners(l, type);
1207        else if (type.isInstance(b))
1208          l.add(b);
1209      }
1210    } // class AWTEventMulticaster