Source for java.awt.AWTEventMulticaster

   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., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 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 <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