1 /* 2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.event.*; 28 import java.lang.reflect.Array; 29 import java.util.EventListener; 30 import java.io.Serializable; 31 import java.io.ObjectOutputStream; 32 import java.io.IOException; 33 import java.util.EventListener; 34 35 36 /** 37 * {@code AWTEventMulticaster} implements efficient and thread-safe multi-cast 38 * event dispatching for the AWT events defined in the {@code java.awt.event} 39 * package. 40 * <p> 41 * The following example illustrates how to use this class: 42 * 43 * <pre><code> 44 * public myComponent extends Component { 45 * ActionListener actionListener = null; 46 * 47 * public synchronized void addActionListener(ActionListener l) { 48 * actionListener = AWTEventMulticaster.add(actionListener, l); 49 * } 50 * public synchronized void removeActionListener(ActionListener l) { 51 * actionListener = AWTEventMulticaster.remove(actionListener, l); 52 * } 53 * public void processEvent(AWTEvent e) { 54 * // when event occurs which causes "action" semantic 55 * ActionListener listener = actionListener; 56 * if (listener != null) { 57 * listener.actionPerformed(new ActionEvent()); 58 * } 59 * } 60 * } 61 * </code></pre> 62 * The important point to note is the first argument to the {@code 63 * add} and {@code remove} methods is the field maintaining the 64 * listeners. In addition you must assign the result of the {@code add} 65 * and {@code remove} methods to the field maintaining the listeners. 66 * <p> 67 * {@code AWTEventMulticaster} is implemented as a pair of {@code 68 * EventListeners} that are set at construction time. {@code 69 * AWTEventMulticaster} is immutable. The {@code add} and {@code 70 * remove} methods do not alter {@code AWTEventMulticaster} in 71 * anyway. If necessary, a new {@code AWTEventMulticaster} is 72 * created. In this way it is safe to add and remove listeners during 73 * the process of an event dispatching. However, event listeners 74 * added during the process of an event dispatch operation are not 75 * notified of the event currently being dispatched. 76 * <p> 77 * All of the {@code add} methods allow {@code null} arguments. If the 78 * first argument is {@code null}, the second argument is returned. If 79 * the first argument is not {@code null} and the second argument is 80 * {@code null}, the first argument is returned. If both arguments are 81 * {@code non-null}, a new {@code AWTEventMulticaster} is created using 82 * the two arguments and returned. 83 * <p> 84 * For the {@code remove} methods that take two arguments, the following is 85 * returned: 86 * <ul> 87 * <li>{@code null}, if the first argument is {@code null}, or 88 * the arguments are equal, by way of {@code ==}. 89 * <li>the first argument, if the first argument is not an instance of 90 * {@code AWTEventMulticaster}. 91 * <li>result of invoking {@code remove(EventListener)} on the 92 * first argument, supplying the second argument to the 93 * {@code remove(EventListener)} method. 94 * </ul> 95 * <p>Swing makes use of 96 * {@link javax.swing.event.EventListenerList EventListenerList} for 97 * similar logic. Refer to it for details. 98 * 99 * @see javax.swing.event.EventListenerList 100 * 101 * @author John Rose 102 * @author Amy Fowler 103 * @since 1.1 104 */ 105 106 public class AWTEventMulticaster implements 107 ComponentListener, ContainerListener, FocusListener, KeyListener, 108 MouseListener, MouseMotionListener, WindowListener, WindowFocusListener, 109 WindowStateListener, ActionListener, ItemListener, AdjustmentListener, 110 TextListener, InputMethodListener, HierarchyListener, 111 HierarchyBoundsListener, MouseWheelListener { 112 113 /** 114 * A variable in the event chain (listener-a) 115 */ 116 protected final EventListener a; 117 118 /** 119 * A variable in the event chain (listener-b) 120 */ 121 protected final EventListener b; 122 123 /** 124 * Creates an event multicaster instance which chains listener-a 125 * with listener-b. Input parameters <code>a</code> and <code>b</code> 126 * should not be <code>null</code>, though implementations may vary in 127 * choosing whether or not to throw <code>NullPointerException</code> 128 * in that case. 129 * @param a listener-a 130 * @param b listener-b 131 */ 132 protected AWTEventMulticaster(EventListener a, EventListener b) { 133 this.a = a; this.b = b; 134 } 135 136 /** 137 * Removes a listener from this multicaster. 138 * <p> 139 * The returned multicaster contains all the listeners in this 140 * multicaster with the exception of all occurrences of {@code oldl}. 141 * If the resulting multicaster contains only one regular listener 142 * the regular listener may be returned. If the resulting multicaster 143 * is empty, then {@code null} may be returned instead. 144 * <p> 145 * No exception is thrown if {@code oldl} is {@code null}. 146 * 147 * @param oldl the listener to be removed 148 * @return resulting listener 149 */ 150 protected EventListener remove(EventListener oldl) { 151 if (oldl == a) return b; 152 if (oldl == b) return a; 153 EventListener a2 = removeInternal(a, oldl); 154 EventListener b2 = removeInternal(b, oldl); 155 if (a2 == a && b2 == b) { 156 return this; // it's not here 157 } 158 return addInternal(a2, b2); 159 } 160 161 /** 162 * Handles the componentResized event by invoking the 163 * componentResized methods on listener-a and listener-b. 164 * @param e the component event 165 */ 166 public void componentResized(ComponentEvent e) { 167 ((ComponentListener)a).componentResized(e); 168 ((ComponentListener)b).componentResized(e); 169 } 170 171 /** 172 * Handles the componentMoved event by invoking the 173 * componentMoved methods on listener-a and listener-b. 174 * @param e the component event 175 */ 176 public void componentMoved(ComponentEvent e) { 177 ((ComponentListener)a).componentMoved(e); 178 ((ComponentListener)b).componentMoved(e); 179 } 180 181 /** 182 * Handles the componentShown event by invoking the 183 * componentShown methods on listener-a and listener-b. 184 * @param e the component event 185 */ 186 public void componentShown(ComponentEvent e) { 187 ((ComponentListener)a).componentShown(e); 188 ((ComponentListener)b).componentShown(e); 189 } 190 191 /** 192 * Handles the componentHidden event by invoking the 193 * componentHidden methods on listener-a and listener-b. 194 * @param e the component event 195 */ 196 public void componentHidden(ComponentEvent e) { 197 ((ComponentListener)a).componentHidden(e); 198 ((ComponentListener)b).componentHidden(e); 199 } 200 201 /** 202 * Handles the componentAdded container event by invoking the 203 * componentAdded methods on listener-a and listener-b. 204 * @param e the component event 205 */ 206 public void componentAdded(ContainerEvent e) { 207 ((ContainerListener)a).componentAdded(e); 208 ((ContainerListener)b).componentAdded(e); 209 } 210 211 /** 212 * Handles the componentRemoved container event by invoking the 213 * componentRemoved methods on listener-a and listener-b. 214 * @param e the component event 215 */ 216 public void componentRemoved(ContainerEvent e) { 217 ((ContainerListener)a).componentRemoved(e); 218 ((ContainerListener)b).componentRemoved(e); 219 } 220 221 /** 222 * Handles the focusGained event by invoking the 223 * focusGained methods on listener-a and listener-b. 224 * @param e the focus event 225 */ 226 public void focusGained(FocusEvent e) { 227 ((FocusListener)a).focusGained(e); 228 ((FocusListener)b).focusGained(e); 229 } 230 231 /** 232 * Handles the focusLost event by invoking the 233 * focusLost methods on listener-a and listener-b. 234 * @param e the focus event 235 */ 236 public void focusLost(FocusEvent e) { 237 ((FocusListener)a).focusLost(e); 238 ((FocusListener)b).focusLost(e); 239 } 240 241 /** 242 * Handles the keyTyped event by invoking the 243 * keyTyped methods on listener-a and listener-b. 244 * @param e the key event 245 */ 246 public void keyTyped(KeyEvent e) { 247 ((KeyListener)a).keyTyped(e); 248 ((KeyListener)b).keyTyped(e); 249 } 250 251 /** 252 * Handles the keyPressed event by invoking the 253 * keyPressed methods on listener-a and listener-b. 254 * @param e the key event 255 */ 256 public void keyPressed(KeyEvent e) { 257 ((KeyListener)a).keyPressed(e); 258 ((KeyListener)b).keyPressed(e); 259 } 260 261 /** 262 * Handles the keyReleased event by invoking the 263 * keyReleased methods on listener-a and listener-b. 264 * @param e the key event 265 */ 266 public void keyReleased(KeyEvent e) { 267 ((KeyListener)a).keyReleased(e); 268 ((KeyListener)b).keyReleased(e); 269 } 270 271 /** 272 * Handles the mouseClicked event by invoking the 273 * mouseClicked methods on listener-a and listener-b. 274 * @param e the mouse event 275 */ 276 public void mouseClicked(MouseEvent e) { 277 ((MouseListener)a).mouseClicked(e); 278 ((MouseListener)b).mouseClicked(e); 279 } 280 281 /** 282 * Handles the mousePressed event by invoking the 283 * mousePressed methods on listener-a and listener-b. 284 * @param e the mouse event 285 */ 286 public void mousePressed(MouseEvent e) { 287 ((MouseListener)a).mousePressed(e); 288 ((MouseListener)b).mousePressed(e); 289 } 290 291 /** 292 * Handles the mouseReleased event by invoking the 293 * mouseReleased methods on listener-a and listener-b. 294 * @param e the mouse event 295 */ 296 public void mouseReleased(MouseEvent e) { 297 ((MouseListener)a).mouseReleased(e); 298 ((MouseListener)b).mouseReleased(e); 299 } 300 301 /** 302 * Handles the mouseEntered event by invoking the 303 * mouseEntered methods on listener-a and listener-b. 304 * @param e the mouse event 305 */ 306 public void mouseEntered(MouseEvent e) { 307 ((MouseListener)a).mouseEntered(e); 308 ((MouseListener)b).mouseEntered(e); 309 } 310 311 /** 312 * Handles the mouseExited event by invoking the 313 * mouseExited methods on listener-a and listener-b. 314 * @param e the mouse event 315 */ 316 public void mouseExited(MouseEvent e) { 317 ((MouseListener)a).mouseExited(e); 318 ((MouseListener)b).mouseExited(e); 319 } 320 321 /** 322 * Handles the mouseDragged event by invoking the 323 * mouseDragged methods on listener-a and listener-b. 324 * @param e the mouse event 325 */ 326 public void mouseDragged(MouseEvent e) { 327 ((MouseMotionListener)a).mouseDragged(e); 328 ((MouseMotionListener)b).mouseDragged(e); 329 } 330 331 /** 332 * Handles the mouseMoved event by invoking the 333 * mouseMoved methods on listener-a and listener-b. 334 * @param e the mouse event 335 */ 336 public void mouseMoved(MouseEvent e) { 337 ((MouseMotionListener)a).mouseMoved(e); 338 ((MouseMotionListener)b).mouseMoved(e); 339 } 340 341 /** 342 * Handles the windowOpened event by invoking the 343 * windowOpened methods on listener-a and listener-b. 344 * @param e the window event 345 */ 346 public void windowOpened(WindowEvent e) { 347 ((WindowListener)a).windowOpened(e); 348 ((WindowListener)b).windowOpened(e); 349 } 350 351 /** 352 * Handles the windowClosing event by invoking the 353 * windowClosing methods on listener-a and listener-b. 354 * @param e the window event 355 */ 356 public void windowClosing(WindowEvent e) { 357 ((WindowListener)a).windowClosing(e); 358 ((WindowListener)b).windowClosing(e); 359 } 360 361 /** 362 * Handles the windowClosed event by invoking the 363 * windowClosed methods on listener-a and listener-b. 364 * @param e the window event 365 */ 366 public void windowClosed(WindowEvent e) { 367 ((WindowListener)a).windowClosed(e); 368 ((WindowListener)b).windowClosed(e); 369 } 370 371 /** 372 * Handles the windowIconified event by invoking the 373 * windowIconified methods on listener-a and listener-b. 374 * @param e the window event 375 */ 376 public void windowIconified(WindowEvent e) { 377 ((WindowListener)a).windowIconified(e); 378 ((WindowListener)b).windowIconified(e); 379 } 380 381 /** 382 * Handles the windowDeiconified event by invoking the 383 * windowDeiconified methods on listener-a and listener-b. 384 * @param e the window event 385 */ 386 public void windowDeiconified(WindowEvent e) { 387 ((WindowListener)a).windowDeiconified(e); 388 ((WindowListener)b).windowDeiconified(e); 389 } 390 391 /** 392 * Handles the windowActivated event by invoking the 393 * windowActivated methods on listener-a and listener-b. 394 * @param e the window event 395 */ 396 public void windowActivated(WindowEvent e) { 397 ((WindowListener)a).windowActivated(e); 398 ((WindowListener)b).windowActivated(e); 399 } 400 401 /** 402 * Handles the windowDeactivated event by invoking the 403 * windowDeactivated methods on listener-a and listener-b. 404 * @param e the window event 405 */ 406 public void windowDeactivated(WindowEvent e) { 407 ((WindowListener)a).windowDeactivated(e); 408 ((WindowListener)b).windowDeactivated(e); 409 } 410 411 /** 412 * Handles the windowStateChanged event by invoking the 413 * windowStateChanged methods on listener-a and listener-b. 414 * @param e the window event 415 * @since 1.4 416 */ 417 public void windowStateChanged(WindowEvent e) { 418 ((WindowStateListener)a).windowStateChanged(e); 419 ((WindowStateListener)b).windowStateChanged(e); 420 } 421 422 423 /** 424 * Handles the windowGainedFocus event by invoking the windowGainedFocus 425 * methods on listener-a and listener-b. 426 * @param e the window event 427 * @since 1.4 428 */ 429 public void windowGainedFocus(WindowEvent e) { 430 ((WindowFocusListener)a).windowGainedFocus(e); 431 ((WindowFocusListener)b).windowGainedFocus(e); 432 } 433 434 /** 435 * Handles the windowLostFocus event by invoking the windowLostFocus 436 * methods on listener-a and listener-b. 437 * @param e the window event 438 * @since 1.4 439 */ 440 public void windowLostFocus(WindowEvent e) { 441 ((WindowFocusListener)a).windowLostFocus(e); 442 ((WindowFocusListener)b).windowLostFocus(e); 443 } 444 445 /** 446 * Handles the actionPerformed event by invoking the 447 * actionPerformed methods on listener-a and listener-b. 448 * @param e the action event 449 */ 450 public void actionPerformed(ActionEvent e) { 451 ((ActionListener)a).actionPerformed(e); 452 ((ActionListener)b).actionPerformed(e); 453 } 454 455 /** 456 * Handles the itemStateChanged event by invoking the 457 * itemStateChanged methods on listener-a and listener-b. 458 * @param e the item event 459 */ 460 public void itemStateChanged(ItemEvent e) { 461 ((ItemListener)a).itemStateChanged(e); 462 ((ItemListener)b).itemStateChanged(e); 463 } 464 465 /** 466 * Handles the adjustmentValueChanged event by invoking the 467 * adjustmentValueChanged methods on listener-a and listener-b. 468 * @param e the adjustment event 469 */ 470 public void adjustmentValueChanged(AdjustmentEvent e) { 471 ((AdjustmentListener)a).adjustmentValueChanged(e); 472 ((AdjustmentListener)b).adjustmentValueChanged(e); 473 } 474 public void textValueChanged(TextEvent e) { 475 ((TextListener)a).textValueChanged(e); 476 ((TextListener)b).textValueChanged(e); 477 } 478 479 /** 480 * Handles the inputMethodTextChanged event by invoking the 481 * inputMethodTextChanged methods on listener-a and listener-b. 482 * @param e the item event 483 */ 484 public void inputMethodTextChanged(InputMethodEvent e) { 485 ((InputMethodListener)a).inputMethodTextChanged(e); 486 ((InputMethodListener)b).inputMethodTextChanged(e); 487 } 488 489 /** 490 * Handles the caretPositionChanged event by invoking the 491 * caretPositionChanged methods on listener-a and listener-b. 492 * @param e the item event 493 */ 494 public void caretPositionChanged(InputMethodEvent e) { 495 ((InputMethodListener)a).caretPositionChanged(e); 496 ((InputMethodListener)b).caretPositionChanged(e); 497 } 498 499 /** 500 * Handles the hierarchyChanged event by invoking the 501 * hierarchyChanged methods on listener-a and listener-b. 502 * @param e the item event 503 * @since 1.3 504 */ 505 public void hierarchyChanged(HierarchyEvent e) { 506 ((HierarchyListener)a).hierarchyChanged(e); 507 ((HierarchyListener)b).hierarchyChanged(e); 508 } 509 510 /** 511 * Handles the ancestorMoved event by invoking the 512 * ancestorMoved methods on listener-a and listener-b. 513 * @param e the item event 514 * @since 1.3 515 */ 516 public void ancestorMoved(HierarchyEvent e) { 517 ((HierarchyBoundsListener)a).ancestorMoved(e); 518 ((HierarchyBoundsListener)b).ancestorMoved(e); 519 } 520 521 /** 522 * Handles the ancestorResized event by invoking the 523 * ancestorResized methods on listener-a and listener-b. 524 * @param e the item event 525 * @since 1.3 526 */ 527 public void ancestorResized(HierarchyEvent e) { 528 ((HierarchyBoundsListener)a).ancestorResized(e); 529 ((HierarchyBoundsListener)b).ancestorResized(e); 530 } 531 532 /** 533 * Handles the mouseWheelMoved event by invoking the 534 * mouseWheelMoved methods on listener-a and listener-b. 535 * @param e the mouse event 536 * @since 1.4 537 */ 538 public void mouseWheelMoved(MouseWheelEvent e) { 539 ((MouseWheelListener)a).mouseWheelMoved(e); 540 ((MouseWheelListener)b).mouseWheelMoved(e); 541 } 542 543 /** 544 * Adds component-listener-a with component-listener-b and 545 * returns the resulting multicast listener. 546 * @param a component-listener-a 547 * @param b component-listener-b 548 * @return the resulting listener 549 */ 550 public static ComponentListener add(ComponentListener a, ComponentListener b) { 551 return (ComponentListener)addInternal(a, b); 552 } 553 554 /** 555 * Adds container-listener-a with container-listener-b and 556 * returns the resulting multicast listener. 557 * @param a container-listener-a 558 * @param b container-listener-b 559 * @return the resulting listener 560 */ 561 public static ContainerListener add(ContainerListener a, ContainerListener b) { 562 return (ContainerListener)addInternal(a, b); 563 } 564 565 /** 566 * Adds focus-listener-a with focus-listener-b and 567 * returns the resulting multicast listener. 568 * @param a focus-listener-a 569 * @param b focus-listener-b 570 * @return the resulting listener 571 */ 572 public static FocusListener add(FocusListener a, FocusListener b) { 573 return (FocusListener)addInternal(a, b); 574 } 575 576 /** 577 * Adds key-listener-a with key-listener-b and 578 * returns the resulting multicast listener. 579 * @param a key-listener-a 580 * @param b key-listener-b 581 * @return the resulting listener 582 */ 583 public static KeyListener add(KeyListener a, KeyListener b) { 584 return (KeyListener)addInternal(a, b); 585 } 586 587 /** 588 * Adds mouse-listener-a with mouse-listener-b and 589 * returns the resulting multicast listener. 590 * @param a mouse-listener-a 591 * @param b mouse-listener-b 592 * @return the resulting listener 593 */ 594 public static MouseListener add(MouseListener a, MouseListener b) { 595 return (MouseListener)addInternal(a, b); 596 } 597 598 /** 599 * Adds mouse-motion-listener-a with mouse-motion-listener-b and 600 * returns the resulting multicast listener. 601 * @param a mouse-motion-listener-a 602 * @param b mouse-motion-listener-b 603 * @return the resulting listener 604 */ 605 public static MouseMotionListener add(MouseMotionListener a, MouseMotionListener b) { 606 return (MouseMotionListener)addInternal(a, b); 607 } 608 609 /** 610 * Adds window-listener-a with window-listener-b and 611 * returns the resulting multicast listener. 612 * @param a window-listener-a 613 * @param b window-listener-b 614 * @return the resulting listener 615 */ 616 public static WindowListener add(WindowListener a, WindowListener b) { 617 return (WindowListener)addInternal(a, b); 618 } 619 620 /** 621 * Adds window-state-listener-a with window-state-listener-b 622 * and returns the resulting multicast listener. 623 * @param a window-state-listener-a 624 * @param b window-state-listener-b 625 * @return the resulting listener 626 * @since 1.4 627 */ 628 @SuppressWarnings("overloads") 629 public static WindowStateListener add(WindowStateListener a, 630 WindowStateListener b) { 631 return (WindowStateListener)addInternal(a, b); 632 } 633 634 /** 635 * Adds window-focus-listener-a with window-focus-listener-b 636 * and returns the resulting multicast listener. 637 * @param a window-focus-listener-a 638 * @param b window-focus-listener-b 639 * @return the resulting listener 640 * @since 1.4 641 */ 642 public static WindowFocusListener add(WindowFocusListener a, 643 WindowFocusListener b) { 644 return (WindowFocusListener)addInternal(a, b); 645 } 646 647 /** 648 * Adds action-listener-a with action-listener-b and 649 * returns the resulting multicast listener. 650 * @param a action-listener-a 651 * @param b action-listener-b 652 * @return the resulting listener 653 */ 654 @SuppressWarnings("overloads") 655 public static ActionListener add(ActionListener a, ActionListener b) { 656 return (ActionListener)addInternal(a, b); 657 } 658 659 /** 660 * Adds item-listener-a with item-listener-b and 661 * returns the resulting multicast listener. 662 * @param a item-listener-a 663 * @param b item-listener-b 664 * @return the resulting listener 665 */ 666 @SuppressWarnings("overloads") 667 public static ItemListener add(ItemListener a, ItemListener b) { 668 return (ItemListener)addInternal(a, b); 669 } 670 671 /** 672 * Adds adjustment-listener-a with adjustment-listener-b and 673 * returns the resulting multicast listener. 674 * @param a adjustment-listener-a 675 * @param b adjustment-listener-b 676 * @return the resulting listener 677 */ 678 @SuppressWarnings("overloads") 679 public static AdjustmentListener add(AdjustmentListener a, AdjustmentListener b) { 680 return (AdjustmentListener)addInternal(a, b); 681 } 682 683 /** 684 * Adds text-listener-a with text-listener-b and 685 * returns the resulting multicast listener. 686 * 687 * @param a text-listener-a 688 * @param b text-listener-b 689 * @return the resulting listener 690 */ 691 @SuppressWarnings("overloads") 692 public static TextListener add(TextListener a, TextListener b) { 693 return (TextListener)addInternal(a, b); 694 } 695 696 /** 697 * Adds input-method-listener-a with input-method-listener-b and 698 * returns the resulting multicast listener. 699 * @param a input-method-listener-a 700 * @param b input-method-listener-b 701 * @return the resulting listener 702 */ 703 public static InputMethodListener add(InputMethodListener a, InputMethodListener b) { 704 return (InputMethodListener)addInternal(a, b); 705 } 706 707 /** 708 * Adds hierarchy-listener-a with hierarchy-listener-b and 709 * returns the resulting multicast listener. 710 * @param a hierarchy-listener-a 711 * @param b hierarchy-listener-b 712 * @return the resulting listener 713 * @since 1.3 714 */ 715 @SuppressWarnings("overloads") 716 public static HierarchyListener add(HierarchyListener a, HierarchyListener b) { 717 return (HierarchyListener)addInternal(a, b); 718 } 719 720 /** 721 * Adds hierarchy-bounds-listener-a with hierarchy-bounds-listener-b and 722 * returns the resulting multicast listener. 723 * @param a hierarchy-bounds-listener-a 724 * @param b hierarchy-bounds-listener-b 725 * @return the resulting listener 726 * @since 1.3 727 */ 728 public static HierarchyBoundsListener add(HierarchyBoundsListener a, HierarchyBoundsListener b) { 729 return (HierarchyBoundsListener)addInternal(a, b); 730 } 731 732 /** 733 * Adds mouse-wheel-listener-a with mouse-wheel-listener-b and 734 * returns the resulting multicast listener. 735 * @param a mouse-wheel-listener-a 736 * @param b mouse-wheel-listener-b 737 * @return the resulting listener 738 * @since 1.4 739 */ 740 @SuppressWarnings("overloads") 741 public static MouseWheelListener add(MouseWheelListener a, 742 MouseWheelListener b) { 743 return (MouseWheelListener)addInternal(a, b); 744 } 745 746 /** 747 * Removes the old component-listener from component-listener-l and 748 * returns the resulting multicast listener. 749 * @param l component-listener-l 750 * @param oldl the component-listener being removed 751 * @return the resulting listener 752 */ 753 public static ComponentListener remove(ComponentListener l, ComponentListener oldl) { 754 return (ComponentListener) removeInternal(l, oldl); 755 } 756 757 /** 758 * Removes the old container-listener from container-listener-l and 759 * returns the resulting multicast listener. 760 * @param l container-listener-l 761 * @param oldl the container-listener being removed 762 * @return the resulting listener 763 */ 764 public static ContainerListener remove(ContainerListener l, ContainerListener oldl) { 765 return (ContainerListener) removeInternal(l, oldl); 766 } 767 768 /** 769 * Removes the old focus-listener from focus-listener-l and 770 * returns the resulting multicast listener. 771 * @param l focus-listener-l 772 * @param oldl the focus-listener being removed 773 * @return the resulting listener 774 */ 775 public static FocusListener remove(FocusListener l, FocusListener oldl) { 776 return (FocusListener) removeInternal(l, oldl); 777 } 778 779 /** 780 * Removes the old key-listener from key-listener-l and 781 * returns the resulting multicast listener. 782 * @param l key-listener-l 783 * @param oldl the key-listener being removed 784 * @return the resulting listener 785 */ 786 public static KeyListener remove(KeyListener l, KeyListener oldl) { 787 return (KeyListener) removeInternal(l, oldl); 788 } 789 790 /** 791 * Removes the old mouse-listener from mouse-listener-l and 792 * returns the resulting multicast listener. 793 * @param l mouse-listener-l 794 * @param oldl the mouse-listener being removed 795 * @return the resulting listener 796 */ 797 public static MouseListener remove(MouseListener l, MouseListener oldl) { 798 return (MouseListener) removeInternal(l, oldl); 799 } 800 801 /** 802 * Removes the old mouse-motion-listener from mouse-motion-listener-l 803 * and returns the resulting multicast listener. 804 * @param l mouse-motion-listener-l 805 * @param oldl the mouse-motion-listener being removed 806 * @return the resulting listener 807 */ 808 public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) { 809 return (MouseMotionListener) removeInternal(l, oldl); 810 } 811 812 /** 813 * Removes the old window-listener from window-listener-l and 814 * returns the resulting multicast listener. 815 * @param l window-listener-l 816 * @param oldl the window-listener being removed 817 * @return the resulting listener 818 */ 819 public static WindowListener remove(WindowListener l, WindowListener oldl) { 820 return (WindowListener) removeInternal(l, oldl); 821 } 822 823 /** 824 * Removes the old window-state-listener from window-state-listener-l 825 * and returns the resulting multicast listener. 826 * @param l window-state-listener-l 827 * @param oldl the window-state-listener being removed 828 * @return the resulting listener 829 * @since 1.4 830 */ 831 @SuppressWarnings("overloads") 832 public static WindowStateListener remove(WindowStateListener l, 833 WindowStateListener oldl) { 834 return (WindowStateListener) removeInternal(l, oldl); 835 } 836 837 /** 838 * Removes the old window-focus-listener from window-focus-listener-l 839 * and returns the resulting multicast listener. 840 * @param l window-focus-listener-l 841 * @param oldl the window-focus-listener being removed 842 * @return the resulting listener 843 * @since 1.4 844 */ 845 public static WindowFocusListener remove(WindowFocusListener l, 846 WindowFocusListener oldl) { 847 return (WindowFocusListener) removeInternal(l, oldl); 848 } 849 850 /** 851 * Removes the old action-listener from action-listener-l and 852 * returns the resulting multicast listener. 853 * @param l action-listener-l 854 * @param oldl the action-listener being removed 855 * @return the resulting listener 856 */ 857 @SuppressWarnings("overloads") 858 public static ActionListener remove(ActionListener l, ActionListener oldl) { 859 return (ActionListener) removeInternal(l, oldl); 860 } 861 862 /** 863 * Removes the old item-listener from item-listener-l and 864 * returns the resulting multicast listener. 865 * @param l item-listener-l 866 * @param oldl the item-listener being removed 867 * @return the resulting listener 868 */ 869 @SuppressWarnings("overloads") 870 public static ItemListener remove(ItemListener l, ItemListener oldl) { 871 return (ItemListener) removeInternal(l, oldl); 872 } 873 874 /** 875 * Removes the old adjustment-listener from adjustment-listener-l and 876 * returns the resulting multicast listener. 877 * @param l adjustment-listener-l 878 * @param oldl the adjustment-listener being removed 879 * @return the resulting listener 880 */ 881 @SuppressWarnings("overloads") 882 public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) { 883 return (AdjustmentListener) removeInternal(l, oldl); 884 } 885 886 /** 887 * Removes the old text-listener from text-listener-l and 888 * returns the resulting multicast listener. 889 * 890 * @param l text-listener-l 891 * @param oldl the text-listener being removed 892 * @return the resulting listener 893 */ 894 @SuppressWarnings("overloads") 895 public static TextListener remove(TextListener l, TextListener oldl) { 896 return (TextListener) removeInternal(l, oldl); 897 } 898 899 /** 900 * Removes the old input-method-listener from input-method-listener-l and 901 * returns the resulting multicast listener. 902 * @param l input-method-listener-l 903 * @param oldl the input-method-listener being removed 904 * @return the resulting listener 905 */ 906 public static InputMethodListener remove(InputMethodListener l, InputMethodListener oldl) { 907 return (InputMethodListener) removeInternal(l, oldl); 908 } 909 910 /** 911 * Removes the old hierarchy-listener from hierarchy-listener-l and 912 * returns the resulting multicast listener. 913 * @param l hierarchy-listener-l 914 * @param oldl the hierarchy-listener being removed 915 * @return the resulting listener 916 * @since 1.3 917 */ 918 @SuppressWarnings("overloads") 919 public static HierarchyListener remove(HierarchyListener l, HierarchyListener oldl) { 920 return (HierarchyListener) removeInternal(l, oldl); 921 } 922 923 /** 924 * Removes the old hierarchy-bounds-listener from 925 * hierarchy-bounds-listener-l and returns the resulting multicast 926 * listener. 927 * @param l hierarchy-bounds-listener-l 928 * @param oldl the hierarchy-bounds-listener being removed 929 * @return the resulting listener 930 * @since 1.3 931 */ 932 public static HierarchyBoundsListener remove(HierarchyBoundsListener l, HierarchyBoundsListener oldl) { 933 return (HierarchyBoundsListener) removeInternal(l, oldl); 934 } 935 936 /** 937 * Removes the old mouse-wheel-listener from mouse-wheel-listener-l 938 * and returns the resulting multicast listener. 939 * @param l mouse-wheel-listener-l 940 * @param oldl the mouse-wheel-listener being removed 941 * @return the resulting listener 942 * @since 1.4 943 */ 944 @SuppressWarnings("overloads") 945 public static MouseWheelListener remove(MouseWheelListener l, 946 MouseWheelListener oldl) { 947 return (MouseWheelListener) removeInternal(l, oldl); 948 } 949 950 /** 951 * Returns the resulting multicast listener from adding listener-a 952 * and listener-b together. 953 * If listener-a is null, it returns listener-b; 954 * If listener-b is null, it returns listener-a 955 * If neither are null, then it creates and returns 956 * a new AWTEventMulticaster instance which chains a with b. 957 * @param a event listener-a 958 * @param b event listener-b 959 * @return the resulting listener 960 */ 961 protected static EventListener addInternal(EventListener a, EventListener b) { 962 if (a == null) return b; 963 if (b == null) return a; 964 return new AWTEventMulticaster(a, b); 965 } 966 967 /** 968 * Returns the resulting multicast listener after removing the 969 * old listener from listener-l. 970 * If listener-l equals the old listener OR listener-l is null, 971 * returns null. 972 * Else if listener-l is an instance of AWTEventMulticaster, 973 * then it removes the old listener from it. 974 * Else, returns listener l. 975 * @param l the listener being removed from 976 * @param oldl the listener being removed 977 * @return the resulting listener 978 */ 979 protected static EventListener removeInternal(EventListener l, EventListener oldl) { 980 if (l == oldl || l == null) { 981 return null; 982 } else if (l instanceof AWTEventMulticaster) { 983 return ((AWTEventMulticaster)l).remove(oldl); 984 } else { 985 return l; // it's not here 986 } 987 } 988 989 990 /** 991 * Serialization support. Saves all Serializable listeners 992 * to a serialization stream. 993 * 994 * @param s the stream to save to 995 * @param k a prefix stream to put before each serializable listener 996 * @throws IOException if serialization fails 997 */ 998 protected void saveInternal(ObjectOutputStream s, String k) throws IOException { 999 if (a instanceof AWTEventMulticaster) { 1000 ((AWTEventMulticaster)a).saveInternal(s, k); 1001 } 1002 else if (a instanceof Serializable) { 1003 s.writeObject(k); 1004 s.writeObject(a); 1005 } 1006 1007 if (b instanceof AWTEventMulticaster) { 1008 ((AWTEventMulticaster)b).saveInternal(s, k); 1009 } 1010 else if (b instanceof Serializable) { 1011 s.writeObject(k); 1012 s.writeObject(b); 1013 } 1014 } 1015 1016 /** 1017 * Saves a Serializable listener chain to a serialization stream. 1018 * 1019 * @param s the stream to save to 1020 * @param k a prefix stream to put before each serializable listener 1021 * @param l the listener chain to save 1022 * @throws IOException if serialization fails 1023 */ 1024 protected static void save(ObjectOutputStream s, String k, EventListener l) throws IOException { 1025 if (l == null) { 1026 return; 1027 } 1028 else if (l instanceof AWTEventMulticaster) { 1029 ((AWTEventMulticaster)l).saveInternal(s, k); 1030 } 1031 else if (l instanceof Serializable) { 1032 s.writeObject(k); 1033 s.writeObject(l); 1034 } 1035 } 1036 1037 /* 1038 * Recursive method which returns a count of the number of listeners in 1039 * EventListener, handling the (common) case of l actually being an 1040 * AWTEventMulticaster. Additionally, only listeners of type listenerType 1041 * are counted. Method modified to fix bug 4513402. -bchristi 1042 */ 1043 private static int getListenerCount(EventListener l, Class<?> listenerType) { 1044 if (l instanceof AWTEventMulticaster) { 1045 AWTEventMulticaster mc = (AWTEventMulticaster)l; 1046 return getListenerCount(mc.a, listenerType) + 1047 getListenerCount(mc.b, listenerType); 1048 } 1049 else { 1050 // Only count listeners of correct type 1051 return listenerType.isInstance(l) ? 1 : 0; 1052 } 1053 } 1054 1055 /* 1056 * Recursive method which populates EventListener array a with EventListeners 1057 * from l. l is usually an AWTEventMulticaster. Bug 4513402 revealed that 1058 * if l differed in type from the element type of a, an ArrayStoreException 1059 * would occur. Now l is only inserted into a if it's of the appropriate 1060 * type. -bchristi 1061 */ 1062 private static int populateListenerArray(EventListener[] a, EventListener l, int index) { 1063 if (l instanceof AWTEventMulticaster) { 1064 AWTEventMulticaster mc = (AWTEventMulticaster)l; 1065 int lhs = populateListenerArray(a, mc.a, index); 1066 return populateListenerArray(a, mc.b, lhs); 1067 } 1068 else if (a.getClass().getComponentType().isInstance(l)) { 1069 a[index] = l; 1070 return index + 1; 1071 } 1072 // Skip nulls, instances of wrong class 1073 else { 1074 return index; 1075 } 1076 } 1077 1078 /** 1079 * Returns an array of all the objects chained as 1080 * <code><em>Foo</em>Listener</code>s by the specified 1081 * <code>java.util.EventListener</code>. 1082 * <code><em>Foo</em>Listener</code>s are chained by the 1083 * <code>AWTEventMulticaster</code> using the 1084 * <code>add<em>Foo</em>Listener</code> method. 1085 * If a <code>null</code> listener is specified, this method returns an 1086 * empty array. If the specified listener is not an instance of 1087 * <code>AWTEventMulticaster</code>, this method returns an array which 1088 * contains only the specified listener. If no such listeners are chained, 1089 * this method returns an empty array. 1090 * 1091 * @param l the specified <code>java.util.EventListener</code> 1092 * @param listenerType the type of listeners requested; this parameter 1093 * should specify an interface that descends from 1094 * <code>java.util.EventListener</code> 1095 * @return an array of all objects chained as 1096 * <code><em>Foo</em>Listener</code>s by the specified multicast 1097 * listener, or an empty array if no such listeners have been 1098 * chained by the specified multicast listener 1099 * @exception NullPointerException if the specified 1100 * {@code listenertype} parameter is {@code null} 1101 * @exception ClassCastException if <code>listenerType</code> 1102 * doesn't specify a class or interface that implements 1103 * <code>java.util.EventListener</code> 1104 * 1105 * @since 1.4 1106 */ 1107 @SuppressWarnings("unchecked") 1108 public static <T extends EventListener> T[] 1109 getListeners(EventListener l, Class<T> listenerType) 1110 { 1111 if (listenerType == null) { 1112 throw new NullPointerException ("Listener type should not be null"); 1113 } 1114 1115 int n = getListenerCount(l, listenerType); 1116 T[] result = (T[])Array.newInstance(listenerType, n); 1117 populateListenerArray(result, l, 0); 1118 return result; 1119 } 1120 }