OSDN Git Service

2005-02-17 Michael Koch <konqueror@gmx.de>
[pf3gnuchains/gcc-fork.git] / libjava / java / awt / AWTEventMulticaster.java
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    */
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 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    */
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