001/* AWTEventMulticaster.java -- allows multicast chaining of listeners
002   Copyright (C) 1999, 2000, 2002 Free Software Foundation
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.awt;
040
041import java.awt.event.ActionEvent;
042import java.awt.event.ActionListener;
043import java.awt.event.AdjustmentEvent;
044import java.awt.event.AdjustmentListener;
045import java.awt.event.ComponentEvent;
046import java.awt.event.ComponentListener;
047import java.awt.event.ContainerEvent;
048import java.awt.event.ContainerListener;
049import java.awt.event.FocusEvent;
050import java.awt.event.FocusListener;
051import java.awt.event.HierarchyBoundsListener;
052import java.awt.event.HierarchyEvent;
053import java.awt.event.HierarchyListener;
054import java.awt.event.InputMethodEvent;
055import java.awt.event.InputMethodListener;
056import java.awt.event.ItemEvent;
057import java.awt.event.ItemListener;
058import java.awt.event.KeyEvent;
059import java.awt.event.KeyListener;
060import java.awt.event.MouseEvent;
061import java.awt.event.MouseListener;
062import java.awt.event.MouseMotionListener;
063import java.awt.event.MouseWheelEvent;
064import java.awt.event.MouseWheelListener;
065import java.awt.event.TextEvent;
066import java.awt.event.TextListener;
067import java.awt.event.WindowEvent;
068import java.awt.event.WindowFocusListener;
069import java.awt.event.WindowListener;
070import java.awt.event.WindowStateListener;
071import java.io.IOException;
072import java.io.ObjectOutputStream;
073import java.io.Serializable;
074import java.lang.reflect.Array;
075import java.util.ArrayList;
076import 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 */
115public 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