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 windowDeiconfied 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 * @param a text-listener-a 687 * @param b text-listener-b 688 * @return the resulting listener 689 */ 690 @SuppressWarnings("overloads") 691 public static TextListener add(TextListener a, TextListener b) { 692 return (TextListener)addInternal(a, b); 693 } 694 695 /** 696 * Adds input-method-listener-a with input-method-listener-b and 697 * returns the resulting multicast listener. 698 * @param a input-method-listener-a 699 * @param b input-method-listener-b 700 * @return the resulting listener 701 */ 702 public static InputMethodListener add(InputMethodListener a, InputMethodListener b) { 703 return (InputMethodListener)addInternal(a, b); 704 } 705 706 /** 707 * Adds hierarchy-listener-a with hierarchy-listener-b and 708 * returns the resulting multicast listener. 709 * @param a hierarchy-listener-a 710 * @param b hierarchy-listener-b 711 * @return the resulting listener 712 * @since 1.3 713 */ 714 @SuppressWarnings("overloads") 715 public static HierarchyListener add(HierarchyListener a, HierarchyListener b) { 716 return (HierarchyListener)addInternal(a, b); 717 } 718 719 /** 720 * Adds hierarchy-bounds-listener-a with hierarchy-bounds-listener-b and 721 * returns the resulting multicast listener. 722 * @param a hierarchy-bounds-listener-a 723 * @param b hierarchy-bounds-listener-b 724 * @return the resulting listener 725 * @since 1.3 726 */ 727 public static HierarchyBoundsListener add(HierarchyBoundsListener a, HierarchyBoundsListener b) { 728 return (HierarchyBoundsListener)addInternal(a, b); 729 } 730 731 /** 732 * Adds mouse-wheel-listener-a with mouse-wheel-listener-b and 733 * returns the resulting multicast listener. 734 * @param a mouse-wheel-listener-a 735 * @param b mouse-wheel-listener-b 736 * @return the resulting listener 737 * @since 1.4 738 */ 739 @SuppressWarnings("overloads") 740 public static MouseWheelListener add(MouseWheelListener a, 741 MouseWheelListener b) { 742 return (MouseWheelListener)addInternal(a, b); 743 } 744 745 /** 746 * Removes the old component-listener from component-listener-l and 747 * returns the resulting multicast listener. 748 * @param l component-listener-l 749 * @param oldl the component-listener being removed 750 * @return the resulting listener 751 */ 752 public static ComponentListener remove(ComponentListener l, ComponentListener oldl) { 753 return (ComponentListener) removeInternal(l, oldl); 754 } 755 756 /** 757 * Removes the old container-listener from container-listener-l and 758 * returns the resulting multicast listener. 759 * @param l container-listener-l 760 * @param oldl the container-listener being removed 761 * @return the resulting listener 762 */ 763 public static ContainerListener remove(ContainerListener l, ContainerListener oldl) { 764 return (ContainerListener) removeInternal(l, oldl); 765 } 766 767 /** 768 * Removes the old focus-listener from focus-listener-l and 769 * returns the resulting multicast listener. 770 * @param l focus-listener-l 771 * @param oldl the focus-listener being removed 772 * @return the resulting listener 773 */ 774 public static FocusListener remove(FocusListener l, FocusListener oldl) { 775 return (FocusListener) removeInternal(l, oldl); 776 } 777 778 /** 779 * Removes the old key-listener from key-listener-l and 780 * returns the resulting multicast listener. 781 * @param l key-listener-l 782 * @param oldl the key-listener being removed 783 * @return the resulting listener 784 */ 785 public static KeyListener remove(KeyListener l, KeyListener oldl) { 786 return (KeyListener) removeInternal(l, oldl); 787 } 788 789 /** 790 * Removes the old mouse-listener from mouse-listener-l and 791 * returns the resulting multicast listener. 792 * @param l mouse-listener-l 793 * @param oldl the mouse-listener being removed 794 * @return the resulting listener 795 */ 796 public static MouseListener remove(MouseListener l, MouseListener oldl) { 797 return (MouseListener) removeInternal(l, oldl); 798 } 799 800 /** 801 * Removes the old mouse-motion-listener from mouse-motion-listener-l 802 * and returns the resulting multicast listener. 803 * @param l mouse-motion-listener-l 804 * @param oldl the mouse-motion-listener being removed 805 * @return the resulting listener 806 */ 807 public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) { 808 return (MouseMotionListener) removeInternal(l, oldl); 809 } 810 811 /** 812 * Removes the old window-listener from window-listener-l and 813 * returns the resulting multicast listener. 814 * @param l window-listener-l 815 * @param oldl the window-listener being removed 816 * @return the resulting listener 817 */ 818 public static WindowListener remove(WindowListener l, WindowListener oldl) { 819 return (WindowListener) removeInternal(l, oldl); 820 } 821 822 /** 823 * Removes the old window-state-listener from window-state-listener-l 824 * and returns the resulting multicast listener. 825 * @param l window-state-listener-l 826 * @param oldl the window-state-listener being removed 827 * @return the resulting listener 828 * @since 1.4 829 */ 830 @SuppressWarnings("overloads") 831 public static WindowStateListener remove(WindowStateListener l, 832 WindowStateListener oldl) { 833 return (WindowStateListener) removeInternal(l, oldl); 834 } 835 836 /** 837 * Removes the old window-focus-listener from window-focus-listener-l 838 * and returns the resulting multicast listener. 839 * @param l window-focus-listener-l 840 * @param oldl the window-focus-listener being removed 841 * @return the resulting listener 842 * @since 1.4 843 */ 844 public static WindowFocusListener remove(WindowFocusListener l, 845 WindowFocusListener oldl) { 846 return (WindowFocusListener) removeInternal(l, oldl); 847 } 848 849 /** 850 * Removes the old action-listener from action-listener-l and 851 * returns the resulting multicast listener. 852 * @param l action-listener-l 853 * @param oldl the action-listener being removed 854 * @return the resulting listener 855 */ 856 @SuppressWarnings("overloads") 857 public static ActionListener remove(ActionListener l, ActionListener oldl) { 858 return (ActionListener) removeInternal(l, oldl); 859 } 860 861 /** 862 * Removes the old item-listener from item-listener-l and 863 * returns the resulting multicast listener. 864 * @param l item-listener-l 865 * @param oldl the item-listener being removed 866 * @return the resulting listener 867 */ 868 @SuppressWarnings("overloads") 869 public static ItemListener remove(ItemListener l, ItemListener oldl) { 870 return (ItemListener) removeInternal(l, oldl); 871 } 872 873 /** 874 * Removes the old adjustment-listener from adjustment-listener-l and 875 * returns the resulting multicast listener. 876 * @param l adjustment-listener-l 877 * @param oldl the adjustment-listener being removed 878 * @return the resulting listener 879 */ 880 @SuppressWarnings("overloads") 881 public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) { 882 return (AdjustmentListener) removeInternal(l, oldl); 883 } 884 885 /** 886 * Removes the old text-listener from text-listener-l and 887 * returns the resulting multicast listener. 888 * @param l text-listener-l 889 * @param oldl the text-listener being removed 890 * @return the resulting listener 891 */ 892 @SuppressWarnings("overloads") 893 public static TextListener remove(TextListener l, TextListener oldl) { 894 return (TextListener) removeInternal(l, oldl); 895 } 896 897 /** 898 * Removes the old input-method-listener from input-method-listener-l and 899 * returns the resulting multicast listener. 900 * @param l input-method-listener-l 901 * @param oldl the input-method-listener being removed 902 * @return the resulting listener 903 */ 904 public static InputMethodListener remove(InputMethodListener l, InputMethodListener oldl) { 905 return (InputMethodListener) removeInternal(l, oldl); 906 } 907 908 /** 909 * Removes the old hierarchy-listener from hierarchy-listener-l and 910 * returns the resulting multicast listener. 911 * @param l hierarchy-listener-l 912 * @param oldl the hierarchy-listener being removed 913 * @return the resulting listener 914 * @since 1.3 915 */ 916 @SuppressWarnings("overloads") 917 public static HierarchyListener remove(HierarchyListener l, HierarchyListener oldl) { 918 return (HierarchyListener) removeInternal(l, oldl); 919 } 920 921 /** 922 * Removes the old hierarchy-bounds-listener from 923 * hierarchy-bounds-listener-l and returns the resulting multicast 924 * listener. 925 * @param l hierarchy-bounds-listener-l 926 * @param oldl the hierarchy-bounds-listener being removed 927 * @return the resulting listener 928 * @since 1.3 929 */ 930 public static HierarchyBoundsListener remove(HierarchyBoundsListener l, HierarchyBoundsListener oldl) { 931 return (HierarchyBoundsListener) removeInternal(l, oldl); 932 } 933 934 /** 935 * Removes the old mouse-wheel-listener from mouse-wheel-listener-l 936 * and returns the resulting multicast listener. 937 * @param l mouse-wheel-listener-l 938 * @param oldl the mouse-wheel-listener being removed 939 * @return the resulting listener 940 * @since 1.4 941 */ 942 @SuppressWarnings("overloads") 943 public static MouseWheelListener remove(MouseWheelListener l, 944 MouseWheelListener oldl) { 945 return (MouseWheelListener) removeInternal(l, oldl); 946 } 947 948 /** 949 * Returns the resulting multicast listener from adding listener-a 950 * and listener-b together. 951 * If listener-a is null, it returns listener-b; 952 * If listener-b is null, it returns listener-a 953 * If neither are null, then it creates and returns 954 * a new AWTEventMulticaster instance which chains a with b. 955 * @param a event listener-a 956 * @param b event listener-b 957 * @return the resulting listener 958 */ 959 protected static EventListener addInternal(EventListener a, EventListener b) { 960 if (a == null) return b; 961 if (b == null) return a; 962 return new AWTEventMulticaster(a, b); 963 } 964 965 /** 966 * Returns the resulting multicast listener after removing the 967 * old listener from listener-l. 968 * If listener-l equals the old listener OR listener-l is null, 969 * returns null. 970 * Else if listener-l is an instance of AWTEventMulticaster, 971 * then it removes the old listener from it. 972 * Else, returns listener l. 973 * @param l the listener being removed from 974 * @param oldl the listener being removed 975 * @return the resulting listener 976 */ 977 protected static EventListener removeInternal(EventListener l, EventListener oldl) { 978 if (l == oldl || l == null) { 979 return null; 980 } else if (l instanceof AWTEventMulticaster) { 981 return ((AWTEventMulticaster)l).remove(oldl); 982 } else { 983 return l; // it's not here 984 } 985 } 986 987 988 /** 989 * Serialization support. Saves all Serializable listeners to a serialization stream. 990 * 991 * @param s the stream to save to 992 * @param k a prefix stream to put before each serializable listener 993 * @throws IOException if serialization fails 994 */ 995 protected void saveInternal(ObjectOutputStream s, String k) throws IOException { 996 if (a instanceof AWTEventMulticaster) { 997 ((AWTEventMulticaster)a).saveInternal(s, k); 998 } 999 else if (a instanceof Serializable) { 1000 s.writeObject(k); 1001 s.writeObject(a); 1002 } 1003 1004 if (b instanceof AWTEventMulticaster) { 1005 ((AWTEventMulticaster)b).saveInternal(s, k); 1006 } 1007 else if (b instanceof Serializable) { 1008 s.writeObject(k); 1009 s.writeObject(b); 1010 } 1011 } 1012 1013 /** 1014 * Saves a Serializable listener chain to a serialization stream. 1015 * 1016 * @param s the stream to save to 1017 * @param k a prefix stream to put before each serializable listener 1018 * @param l the listener chain to save 1019 * @throws IOException if serialization fails 1020 */ 1021 protected static void save(ObjectOutputStream s, String k, EventListener l) throws IOException { 1022 if (l == null) { 1023 return; 1024 } 1025 else if (l instanceof AWTEventMulticaster) { 1026 ((AWTEventMulticaster)l).saveInternal(s, k); 1027 } 1028 else if (l instanceof Serializable) { 1029 s.writeObject(k); 1030 s.writeObject(l); 1031 } 1032 } 1033 1034 /* 1035 * Recursive method which returns a count of the number of listeners in 1036 * EventListener, handling the (common) case of l actually being an 1037 * AWTEventMulticaster. Additionally, only listeners of type listenerType 1038 * are counted. Method modified to fix bug 4513402. -bchristi 1039 */ 1040 private static int getListenerCount(EventListener l, Class<?> listenerType) { 1041 if (l instanceof AWTEventMulticaster) { 1042 AWTEventMulticaster mc = (AWTEventMulticaster)l; 1043 return getListenerCount(mc.a, listenerType) + 1044 getListenerCount(mc.b, listenerType); 1045 } 1046 else { 1047 // Only count listeners of correct type 1048 return listenerType.isInstance(l) ? 1 : 0; 1049 } 1050 } 1051 1052 /* 1053 * Recusive method which populates EventListener array a with EventListeners 1054 * from l. l is usually an AWTEventMulticaster. Bug 4513402 revealed that 1055 * if l differed in type from the element type of a, an ArrayStoreException 1056 * would occur. Now l is only inserted into a if it's of the appropriate 1057 * type. -bchristi 1058 */ 1059 private static int populateListenerArray(EventListener[] a, EventListener l, int index) { 1060 if (l instanceof AWTEventMulticaster) { 1061 AWTEventMulticaster mc = (AWTEventMulticaster)l; 1062 int lhs = populateListenerArray(a, mc.a, index); 1063 return populateListenerArray(a, mc.b, lhs); 1064 } 1065 else if (a.getClass().getComponentType().isInstance(l)) { 1066 a[index] = l; 1067 return index + 1; 1068 } 1069 // Skip nulls, instances of wrong class 1070 else { 1071 return index; 1072 } 1073 } 1074 1075 /** 1076 * Returns an array of all the objects chained as 1077 * <code><em>Foo</em>Listener</code>s by the specified 1078 * <code>java.util.EventListener</code>. 1079 * <code><em>Foo</em>Listener</code>s are chained by the 1080 * <code>AWTEventMulticaster</code> using the 1081 * <code>add<em>Foo</em>Listener</code> method. 1082 * If a <code>null</code> listener is specified, this method returns an 1083 * empty array. If the specified listener is not an instance of 1084 * <code>AWTEventMulticaster</code>, this method returns an array which 1085 * contains only the specified listener. If no such listeners are chained, 1086 * this method returns an empty array. 1087 * 1088 * @param l the specified <code>java.util.EventListener</code> 1089 * @param listenerType the type of listeners requested; this parameter 1090 * should specify an interface that descends from 1091 * <code>java.util.EventListener</code> 1092 * @return an array of all objects chained as 1093 * <code><em>Foo</em>Listener</code>s by the specified multicast 1094 * listener, or an empty array if no such listeners have been 1095 * chained by the specified multicast listener 1096 * @exception NullPointerException if the specified 1097 * {@code listenertype} parameter is {@code null} 1098 * @exception ClassCastException if <code>listenerType</code> 1099 * doesn't specify a class or interface that implements 1100 * <code>java.util.EventListener</code> 1101 * 1102 * @since 1.4 1103 */ 1104 @SuppressWarnings("unchecked") 1105 public static <T extends EventListener> T[] 1106 getListeners(EventListener l, Class<T> listenerType) 1107 { 1108 if (listenerType == null) { 1109 throw new NullPointerException ("Listener type should not be null"); 1110 } 1111 1112 int n = getListenerCount(l, listenerType); 1113 T[] result = (T[])Array.newInstance(listenerType, n); 1114 populateListenerArray(result, l, 0); 1115 return result; 1116 } 1117 }