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 protected final EventListener a, b; 114 115 /** 116 * Creates an event multicaster instance which chains listener-a 117 * with listener-b. Input parameters <code>a</code> and <code>b</code> 118 * should not be <code>null</code>, though implementations may vary in 119 * choosing whether or not to throw <code>NullPointerException</code> 120 * in that case. 121 * @param a listener-a 122 * @param b listener-b 123 */ 124 protected AWTEventMulticaster(EventListener a, EventListener b) { 125 this.a = a; this.b = b; 126 } 127 128 /** 129 * Removes a listener from this multicaster. 130 * <p> 131 * The returned multicaster contains all the listeners in this 132 * multicaster with the exception of all occurrences of {@code oldl}. 133 * If the resulting multicaster contains only one regular listener 134 * the regular listener may be returned. If the resulting multicaster 135 * is empty, then {@code null} may be returned instead. 136 * <p> 137 * No exception is thrown if {@code oldl} is {@code null}. 138 * 139 * @param oldl the listener to be removed 140 * @return resulting listener 141 */ 142 protected EventListener remove(EventListener oldl) { 143 if (oldl == a) return b; 144 if (oldl == b) return a; 145 EventListener a2 = removeInternal(a, oldl); 146 EventListener b2 = removeInternal(b, oldl); 147 if (a2 == a && b2 == b) { 148 return this; // it's not here 149 } 150 return addInternal(a2, b2); 151 } 152 153 /** 154 * Handles the componentResized event by invoking the 155 * componentResized methods on listener-a and listener-b. 156 * @param e the component event 157 */ 158 public void componentResized(ComponentEvent e) { 159 ((ComponentListener)a).componentResized(e); 160 ((ComponentListener)b).componentResized(e); 161 } 162 163 /** 164 * Handles the componentMoved event by invoking the 165 * componentMoved methods on listener-a and listener-b. 166 * @param e the component event 167 */ 168 public void componentMoved(ComponentEvent e) { 169 ((ComponentListener)a).componentMoved(e); 170 ((ComponentListener)b).componentMoved(e); 171 } 172 173 /** 174 * Handles the componentShown event by invoking the 175 * componentShown methods on listener-a and listener-b. 176 * @param e the component event 177 */ 178 public void componentShown(ComponentEvent e) { 179 ((ComponentListener)a).componentShown(e); 180 ((ComponentListener)b).componentShown(e); 181 } 182 183 /** 184 * Handles the componentHidden event by invoking the 185 * componentHidden methods on listener-a and listener-b. 186 * @param e the component event 187 */ 188 public void componentHidden(ComponentEvent e) { 189 ((ComponentListener)a).componentHidden(e); 190 ((ComponentListener)b).componentHidden(e); 191 } 192 193 /** 194 * Handles the componentAdded container event by invoking the 195 * componentAdded methods on listener-a and listener-b. 196 * @param e the component event 197 */ 198 public void componentAdded(ContainerEvent e) { 199 ((ContainerListener)a).componentAdded(e); 200 ((ContainerListener)b).componentAdded(e); 201 } 202 203 /** 204 * Handles the componentRemoved container event by invoking the 205 * componentRemoved methods on listener-a and listener-b. 206 * @param e the component event 207 */ 208 public void componentRemoved(ContainerEvent e) { 209 ((ContainerListener)a).componentRemoved(e); 210 ((ContainerListener)b).componentRemoved(e); 211 } 212 213 /** 214 * Handles the focusGained event by invoking the 215 * focusGained methods on listener-a and listener-b. 216 * @param e the focus event 217 */ 218 public void focusGained(FocusEvent e) { 219 ((FocusListener)a).focusGained(e); 220 ((FocusListener)b).focusGained(e); 221 } 222 223 /** 224 * Handles the focusLost event by invoking the 225 * focusLost methods on listener-a and listener-b. 226 * @param e the focus event 227 */ 228 public void focusLost(FocusEvent e) { 229 ((FocusListener)a).focusLost(e); 230 ((FocusListener)b).focusLost(e); 231 } 232 233 /** 234 * Handles the keyTyped event by invoking the 235 * keyTyped methods on listener-a and listener-b. 236 * @param e the key event 237 */ 238 public void keyTyped(KeyEvent e) { 239 ((KeyListener)a).keyTyped(e); 240 ((KeyListener)b).keyTyped(e); 241 } 242 243 /** 244 * Handles the keyPressed event by invoking the 245 * keyPressed methods on listener-a and listener-b. 246 * @param e the key event 247 */ 248 public void keyPressed(KeyEvent e) { 249 ((KeyListener)a).keyPressed(e); 250 ((KeyListener)b).keyPressed(e); 251 } 252 253 /** 254 * Handles the keyReleased event by invoking the 255 * keyReleased methods on listener-a and listener-b. 256 * @param e the key event 257 */ 258 public void keyReleased(KeyEvent e) { 259 ((KeyListener)a).keyReleased(e); 260 ((KeyListener)b).keyReleased(e); 261 } 262 263 /** 264 * Handles the mouseClicked event by invoking the 265 * mouseClicked methods on listener-a and listener-b. 266 * @param e the mouse event 267 */ 268 public void mouseClicked(MouseEvent e) { 269 ((MouseListener)a).mouseClicked(e); 270 ((MouseListener)b).mouseClicked(e); 271 } 272 273 /** 274 * Handles the mousePressed event by invoking the 275 * mousePressed methods on listener-a and listener-b. 276 * @param e the mouse event 277 */ 278 public void mousePressed(MouseEvent e) { 279 ((MouseListener)a).mousePressed(e); 280 ((MouseListener)b).mousePressed(e); 281 } 282 283 /** 284 * Handles the mouseReleased event by invoking the 285 * mouseReleased methods on listener-a and listener-b. 286 * @param e the mouse event 287 */ 288 public void mouseReleased(MouseEvent e) { 289 ((MouseListener)a).mouseReleased(e); 290 ((MouseListener)b).mouseReleased(e); 291 } 292 293 /** 294 * Handles the mouseEntered event by invoking the 295 * mouseEntered methods on listener-a and listener-b. 296 * @param e the mouse event 297 */ 298 public void mouseEntered(MouseEvent e) { 299 ((MouseListener)a).mouseEntered(e); 300 ((MouseListener)b).mouseEntered(e); 301 } 302 303 /** 304 * Handles the mouseExited event by invoking the 305 * mouseExited methods on listener-a and listener-b. 306 * @param e the mouse event 307 */ 308 public void mouseExited(MouseEvent e) { 309 ((MouseListener)a).mouseExited(e); 310 ((MouseListener)b).mouseExited(e); 311 } 312 313 /** 314 * Handles the mouseDragged event by invoking the 315 * mouseDragged methods on listener-a and listener-b. 316 * @param e the mouse event 317 */ 318 public void mouseDragged(MouseEvent e) { 319 ((MouseMotionListener)a).mouseDragged(e); 320 ((MouseMotionListener)b).mouseDragged(e); 321 } 322 323 /** 324 * Handles the mouseMoved event by invoking the 325 * mouseMoved methods on listener-a and listener-b. 326 * @param e the mouse event 327 */ 328 public void mouseMoved(MouseEvent e) { 329 ((MouseMotionListener)a).mouseMoved(e); 330 ((MouseMotionListener)b).mouseMoved(e); 331 } 332 333 /** 334 * Handles the windowOpened event by invoking the 335 * windowOpened methods on listener-a and listener-b. 336 * @param e the window event 337 */ 338 public void windowOpened(WindowEvent e) { 339 ((WindowListener)a).windowOpened(e); 340 ((WindowListener)b).windowOpened(e); 341 } 342 343 /** 344 * Handles the windowClosing event by invoking the 345 * windowClosing methods on listener-a and listener-b. 346 * @param e the window event 347 */ 348 public void windowClosing(WindowEvent e) { 349 ((WindowListener)a).windowClosing(e); 350 ((WindowListener)b).windowClosing(e); 351 } 352 353 /** 354 * Handles the windowClosed event by invoking the 355 * windowClosed methods on listener-a and listener-b. 356 * @param e the window event 357 */ 358 public void windowClosed(WindowEvent e) { 359 ((WindowListener)a).windowClosed(e); 360 ((WindowListener)b).windowClosed(e); 361 } 362 363 /** 364 * Handles the windowIconified event by invoking the 365 * windowIconified methods on listener-a and listener-b. 366 * @param e the window event 367 */ 368 public void windowIconified(WindowEvent e) { 369 ((WindowListener)a).windowIconified(e); 370 ((WindowListener)b).windowIconified(e); 371 } 372 373 /** 374 * Handles the windowDeiconfied event by invoking the 375 * windowDeiconified methods on listener-a and listener-b. 376 * @param e the window event 377 */ 378 public void windowDeiconified(WindowEvent e) { 379 ((WindowListener)a).windowDeiconified(e); 380 ((WindowListener)b).windowDeiconified(e); 381 } 382 383 /** 384 * Handles the windowActivated event by invoking the 385 * windowActivated methods on listener-a and listener-b. 386 * @param e the window event 387 */ 388 public void windowActivated(WindowEvent e) { 389 ((WindowListener)a).windowActivated(e); 390 ((WindowListener)b).windowActivated(e); 391 } 392 393 /** 394 * Handles the windowDeactivated event by invoking the 395 * windowDeactivated methods on listener-a and listener-b. 396 * @param e the window event 397 */ 398 public void windowDeactivated(WindowEvent e) { 399 ((WindowListener)a).windowDeactivated(e); 400 ((WindowListener)b).windowDeactivated(e); 401 } 402 403 /** 404 * Handles the windowStateChanged event by invoking the 405 * windowStateChanged methods on listener-a and listener-b. 406 * @param e the window event 407 * @since 1.4 408 */ 409 public void windowStateChanged(WindowEvent e) { 410 ((WindowStateListener)a).windowStateChanged(e); 411 ((WindowStateListener)b).windowStateChanged(e); 412 } 413 414 415 /** 416 * Handles the windowGainedFocus event by invoking the windowGainedFocus 417 * methods on listener-a and listener-b. 418 * @param e the window event 419 * @since 1.4 420 */ 421 public void windowGainedFocus(WindowEvent e) { 422 ((WindowFocusListener)a).windowGainedFocus(e); 423 ((WindowFocusListener)b).windowGainedFocus(e); 424 } 425 426 /** 427 * Handles the windowLostFocus event by invoking the windowLostFocus 428 * methods on listener-a and listener-b. 429 * @param e the window event 430 * @since 1.4 431 */ 432 public void windowLostFocus(WindowEvent e) { 433 ((WindowFocusListener)a).windowLostFocus(e); 434 ((WindowFocusListener)b).windowLostFocus(e); 435 } 436 437 /** 438 * Handles the actionPerformed event by invoking the 439 * actionPerformed methods on listener-a and listener-b. 440 * @param e the action event 441 */ 442 public void actionPerformed(ActionEvent e) { 443 ((ActionListener)a).actionPerformed(e); 444 ((ActionListener)b).actionPerformed(e); 445 } 446 447 /** 448 * Handles the itemStateChanged event by invoking the 449 * itemStateChanged methods on listener-a and listener-b. 450 * @param e the item event 451 */ 452 public void itemStateChanged(ItemEvent e) { 453 ((ItemListener)a).itemStateChanged(e); 454 ((ItemListener)b).itemStateChanged(e); 455 } 456 457 /** 458 * Handles the adjustmentValueChanged event by invoking the 459 * adjustmentValueChanged methods on listener-a and listener-b. 460 * @param e the adjustment event 461 */ 462 public void adjustmentValueChanged(AdjustmentEvent e) { 463 ((AdjustmentListener)a).adjustmentValueChanged(e); 464 ((AdjustmentListener)b).adjustmentValueChanged(e); 465 } 466 public void textValueChanged(TextEvent e) { 467 ((TextListener)a).textValueChanged(e); 468 ((TextListener)b).textValueChanged(e); 469 } 470 471 /** 472 * Handles the inputMethodTextChanged event by invoking the 473 * inputMethodTextChanged methods on listener-a and listener-b. 474 * @param e the item event 475 */ 476 public void inputMethodTextChanged(InputMethodEvent e) { 477 ((InputMethodListener)a).inputMethodTextChanged(e); 478 ((InputMethodListener)b).inputMethodTextChanged(e); 479 } 480 481 /** 482 * Handles the caretPositionChanged event by invoking the 483 * caretPositionChanged methods on listener-a and listener-b. 484 * @param e the item event 485 */ 486 public void caretPositionChanged(InputMethodEvent e) { 487 ((InputMethodListener)a).caretPositionChanged(e); 488 ((InputMethodListener)b).caretPositionChanged(e); 489 } 490 491 /** 492 * Handles the hierarchyChanged event by invoking the 493 * hierarchyChanged methods on listener-a and listener-b. 494 * @param e the item event 495 * @since 1.3 496 */ 497 public void hierarchyChanged(HierarchyEvent e) { 498 ((HierarchyListener)a).hierarchyChanged(e); 499 ((HierarchyListener)b).hierarchyChanged(e); 500 } 501 502 /** 503 * Handles the ancestorMoved event by invoking the 504 * ancestorMoved methods on listener-a and listener-b. 505 * @param e the item event 506 * @since 1.3 507 */ 508 public void ancestorMoved(HierarchyEvent e) { 509 ((HierarchyBoundsListener)a).ancestorMoved(e); 510 ((HierarchyBoundsListener)b).ancestorMoved(e); 511 } 512 513 /** 514 * Handles the ancestorResized event by invoking the 515 * ancestorResized methods on listener-a and listener-b. 516 * @param e the item event 517 * @since 1.3 518 */ 519 public void ancestorResized(HierarchyEvent e) { 520 ((HierarchyBoundsListener)a).ancestorResized(e); 521 ((HierarchyBoundsListener)b).ancestorResized(e); 522 } 523 524 /** 525 * Handles the mouseWheelMoved event by invoking the 526 * mouseWheelMoved methods on listener-a and listener-b. 527 * @param e the mouse event 528 * @since 1.4 529 */ 530 public void mouseWheelMoved(MouseWheelEvent e) { 531 ((MouseWheelListener)a).mouseWheelMoved(e); 532 ((MouseWheelListener)b).mouseWheelMoved(e); 533 } 534 535 /** 536 * Adds component-listener-a with component-listener-b and 537 * returns the resulting multicast listener. 538 * @param a component-listener-a 539 * @param b component-listener-b 540 */ 541 public static ComponentListener add(ComponentListener a, ComponentListener b) { 542 return (ComponentListener)addInternal(a, b); 543 } 544 545 /** 546 * Adds container-listener-a with container-listener-b and 547 * returns the resulting multicast listener. 548 * @param a container-listener-a 549 * @param b container-listener-b 550 */ 551 public static ContainerListener add(ContainerListener a, ContainerListener b) { 552 return (ContainerListener)addInternal(a, b); 553 } 554 555 /** 556 * Adds focus-listener-a with focus-listener-b and 557 * returns the resulting multicast listener. 558 * @param a focus-listener-a 559 * @param b focus-listener-b 560 */ 561 public static FocusListener add(FocusListener a, FocusListener b) { 562 return (FocusListener)addInternal(a, b); 563 } 564 565 /** 566 * Adds key-listener-a with key-listener-b and 567 * returns the resulting multicast listener. 568 * @param a key-listener-a 569 * @param b key-listener-b 570 */ 571 public static KeyListener add(KeyListener a, KeyListener b) { 572 return (KeyListener)addInternal(a, b); 573 } 574 575 /** 576 * Adds mouse-listener-a with mouse-listener-b and 577 * returns the resulting multicast listener. 578 * @param a mouse-listener-a 579 * @param b mouse-listener-b 580 */ 581 public static MouseListener add(MouseListener a, MouseListener b) { 582 return (MouseListener)addInternal(a, b); 583 } 584 585 /** 586 * Adds mouse-motion-listener-a with mouse-motion-listener-b and 587 * returns the resulting multicast listener. 588 * @param a mouse-motion-listener-a 589 * @param b mouse-motion-listener-b 590 */ 591 public static MouseMotionListener add(MouseMotionListener a, MouseMotionListener b) { 592 return (MouseMotionListener)addInternal(a, b); 593 } 594 595 /** 596 * Adds window-listener-a with window-listener-b and 597 * returns the resulting multicast listener. 598 * @param a window-listener-a 599 * @param b window-listener-b 600 */ 601 public static WindowListener add(WindowListener a, WindowListener b) { 602 return (WindowListener)addInternal(a, b); 603 } 604 605 /** 606 * Adds window-state-listener-a with window-state-listener-b 607 * and returns the resulting multicast listener. 608 * @param a window-state-listener-a 609 * @param b window-state-listener-b 610 * @since 1.4 611 */ 612 @SuppressWarnings("overloads") 613 public static WindowStateListener add(WindowStateListener a, 614 WindowStateListener b) { 615 return (WindowStateListener)addInternal(a, b); 616 } 617 618 /** 619 * Adds window-focus-listener-a with window-focus-listener-b 620 * and returns the resulting multicast listener. 621 * @param a window-focus-listener-a 622 * @param b window-focus-listener-b 623 * @since 1.4 624 */ 625 public static WindowFocusListener add(WindowFocusListener a, 626 WindowFocusListener b) { 627 return (WindowFocusListener)addInternal(a, b); 628 } 629 630 /** 631 * Adds action-listener-a with action-listener-b and 632 * returns the resulting multicast listener. 633 * @param a action-listener-a 634 * @param b action-listener-b 635 */ 636 @SuppressWarnings("overloads") 637 public static ActionListener add(ActionListener a, ActionListener b) { 638 return (ActionListener)addInternal(a, b); 639 } 640 641 /** 642 * Adds item-listener-a with item-listener-b and 643 * returns the resulting multicast listener. 644 * @param a item-listener-a 645 * @param b item-listener-b 646 */ 647 @SuppressWarnings("overloads") 648 public static ItemListener add(ItemListener a, ItemListener b) { 649 return (ItemListener)addInternal(a, b); 650 } 651 652 /** 653 * Adds adjustment-listener-a with adjustment-listener-b and 654 * returns the resulting multicast listener. 655 * @param a adjustment-listener-a 656 * @param b adjustment-listener-b 657 */ 658 @SuppressWarnings("overloads") 659 public static AdjustmentListener add(AdjustmentListener a, AdjustmentListener b) { 660 return (AdjustmentListener)addInternal(a, b); 661 } 662 @SuppressWarnings("overloads") 663 public static TextListener add(TextListener a, TextListener b) { 664 return (TextListener)addInternal(a, b); 665 } 666 667 /** 668 * Adds input-method-listener-a with input-method-listener-b and 669 * returns the resulting multicast listener. 670 * @param a input-method-listener-a 671 * @param b input-method-listener-b 672 */ 673 public static InputMethodListener add(InputMethodListener a, InputMethodListener b) { 674 return (InputMethodListener)addInternal(a, b); 675 } 676 677 /** 678 * Adds hierarchy-listener-a with hierarchy-listener-b and 679 * returns the resulting multicast listener. 680 * @param a hierarchy-listener-a 681 * @param b hierarchy-listener-b 682 * @since 1.3 683 */ 684 @SuppressWarnings("overloads") 685 public static HierarchyListener add(HierarchyListener a, HierarchyListener b) { 686 return (HierarchyListener)addInternal(a, b); 687 } 688 689 /** 690 * Adds hierarchy-bounds-listener-a with hierarchy-bounds-listener-b and 691 * returns the resulting multicast listener. 692 * @param a hierarchy-bounds-listener-a 693 * @param b hierarchy-bounds-listener-b 694 * @since 1.3 695 */ 696 public static HierarchyBoundsListener add(HierarchyBoundsListener a, HierarchyBoundsListener b) { 697 return (HierarchyBoundsListener)addInternal(a, b); 698 } 699 700 /** 701 * Adds mouse-wheel-listener-a with mouse-wheel-listener-b and 702 * returns the resulting multicast listener. 703 * @param a mouse-wheel-listener-a 704 * @param b mouse-wheel-listener-b 705 * @since 1.4 706 */ 707 @SuppressWarnings("overloads") 708 public static MouseWheelListener add(MouseWheelListener a, 709 MouseWheelListener b) { 710 return (MouseWheelListener)addInternal(a, b); 711 } 712 713 /** 714 * Removes the old component-listener from component-listener-l and 715 * returns the resulting multicast listener. 716 * @param l component-listener-l 717 * @param oldl the component-listener being removed 718 */ 719 public static ComponentListener remove(ComponentListener l, ComponentListener oldl) { 720 return (ComponentListener) removeInternal(l, oldl); 721 } 722 723 /** 724 * Removes the old container-listener from container-listener-l and 725 * returns the resulting multicast listener. 726 * @param l container-listener-l 727 * @param oldl the container-listener being removed 728 */ 729 public static ContainerListener remove(ContainerListener l, ContainerListener oldl) { 730 return (ContainerListener) removeInternal(l, oldl); 731 } 732 733 /** 734 * Removes the old focus-listener from focus-listener-l and 735 * returns the resulting multicast listener. 736 * @param l focus-listener-l 737 * @param oldl the focus-listener being removed 738 */ 739 public static FocusListener remove(FocusListener l, FocusListener oldl) { 740 return (FocusListener) removeInternal(l, oldl); 741 } 742 743 /** 744 * Removes the old key-listener from key-listener-l and 745 * returns the resulting multicast listener. 746 * @param l key-listener-l 747 * @param oldl the key-listener being removed 748 */ 749 public static KeyListener remove(KeyListener l, KeyListener oldl) { 750 return (KeyListener) removeInternal(l, oldl); 751 } 752 753 /** 754 * Removes the old mouse-listener from mouse-listener-l and 755 * returns the resulting multicast listener. 756 * @param l mouse-listener-l 757 * @param oldl the mouse-listener being removed 758 */ 759 public static MouseListener remove(MouseListener l, MouseListener oldl) { 760 return (MouseListener) removeInternal(l, oldl); 761 } 762 763 /** 764 * Removes the old mouse-motion-listener from mouse-motion-listener-l 765 * and returns the resulting multicast listener. 766 * @param l mouse-motion-listener-l 767 * @param oldl the mouse-motion-listener being removed 768 */ 769 public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) { 770 return (MouseMotionListener) removeInternal(l, oldl); 771 } 772 773 /** 774 * Removes the old window-listener from window-listener-l and 775 * returns the resulting multicast listener. 776 * @param l window-listener-l 777 * @param oldl the window-listener being removed 778 */ 779 public static WindowListener remove(WindowListener l, WindowListener oldl) { 780 return (WindowListener) removeInternal(l, oldl); 781 } 782 783 /** 784 * Removes the old window-state-listener from window-state-listener-l 785 * and returns the resulting multicast listener. 786 * @param l window-state-listener-l 787 * @param oldl the window-state-listener being removed 788 * @since 1.4 789 */ 790 @SuppressWarnings("overloads") 791 public static WindowStateListener remove(WindowStateListener l, 792 WindowStateListener oldl) { 793 return (WindowStateListener) removeInternal(l, oldl); 794 } 795 796 /** 797 * Removes the old window-focus-listener from window-focus-listener-l 798 * and returns the resulting multicast listener. 799 * @param l window-focus-listener-l 800 * @param oldl the window-focus-listener being removed 801 * @since 1.4 802 */ 803 public static WindowFocusListener remove(WindowFocusListener l, 804 WindowFocusListener oldl) { 805 return (WindowFocusListener) removeInternal(l, oldl); 806 } 807 808 /** 809 * Removes the old action-listener from action-listener-l and 810 * returns the resulting multicast listener. 811 * @param l action-listener-l 812 * @param oldl the action-listener being removed 813 */ 814 @SuppressWarnings("overloads") 815 public static ActionListener remove(ActionListener l, ActionListener oldl) { 816 return (ActionListener) removeInternal(l, oldl); 817 } 818 819 /** 820 * Removes the old item-listener from item-listener-l and 821 * returns the resulting multicast listener. 822 * @param l item-listener-l 823 * @param oldl the item-listener being removed 824 */ 825 @SuppressWarnings("overloads") 826 public static ItemListener remove(ItemListener l, ItemListener oldl) { 827 return (ItemListener) removeInternal(l, oldl); 828 } 829 830 /** 831 * Removes the old adjustment-listener from adjustment-listener-l and 832 * returns the resulting multicast listener. 833 * @param l adjustment-listener-l 834 * @param oldl the adjustment-listener being removed 835 */ 836 @SuppressWarnings("overloads") 837 public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) { 838 return (AdjustmentListener) removeInternal(l, oldl); 839 } 840 @SuppressWarnings("overloads") 841 public static TextListener remove(TextListener l, TextListener oldl) { 842 return (TextListener) removeInternal(l, oldl); 843 } 844 845 /** 846 * Removes the old input-method-listener from input-method-listener-l and 847 * returns the resulting multicast listener. 848 * @param l input-method-listener-l 849 * @param oldl the input-method-listener being removed 850 */ 851 public static InputMethodListener remove(InputMethodListener l, InputMethodListener oldl) { 852 return (InputMethodListener) removeInternal(l, oldl); 853 } 854 855 /** 856 * Removes the old hierarchy-listener from hierarchy-listener-l and 857 * returns the resulting multicast listener. 858 * @param l hierarchy-listener-l 859 * @param oldl the hierarchy-listener being removed 860 * @since 1.3 861 */ 862 @SuppressWarnings("overloads") 863 public static HierarchyListener remove(HierarchyListener l, HierarchyListener oldl) { 864 return (HierarchyListener) removeInternal(l, oldl); 865 } 866 867 /** 868 * Removes the old hierarchy-bounds-listener from 869 * hierarchy-bounds-listener-l and returns the resulting multicast 870 * listener. 871 * @param l hierarchy-bounds-listener-l 872 * @param oldl the hierarchy-bounds-listener being removed 873 * @since 1.3 874 */ 875 public static HierarchyBoundsListener remove(HierarchyBoundsListener l, HierarchyBoundsListener oldl) { 876 return (HierarchyBoundsListener) removeInternal(l, oldl); 877 } 878 879 /** 880 * Removes the old mouse-wheel-listener from mouse-wheel-listener-l 881 * and returns the resulting multicast listener. 882 * @param l mouse-wheel-listener-l 883 * @param oldl the mouse-wheel-listener being removed 884 * @since 1.4 885 */ 886 @SuppressWarnings("overloads") 887 public static MouseWheelListener remove(MouseWheelListener l, 888 MouseWheelListener oldl) { 889 return (MouseWheelListener) removeInternal(l, oldl); 890 } 891 892 /** 893 * Returns the resulting multicast listener from adding listener-a 894 * and listener-b together. 895 * If listener-a is null, it returns listener-b; 896 * If listener-b is null, it returns listener-a 897 * If neither are null, then it creates and returns 898 * a new AWTEventMulticaster instance which chains a with b. 899 * @param a event listener-a 900 * @param b event listener-b 901 */ 902 protected static EventListener addInternal(EventListener a, EventListener b) { 903 if (a == null) return b; 904 if (b == null) return a; 905 return new AWTEventMulticaster(a, b); 906 } 907 908 /** 909 * Returns the resulting multicast listener after removing the 910 * old listener from listener-l. 911 * If listener-l equals the old listener OR listener-l is null, 912 * returns null. 913 * Else if listener-l is an instance of AWTEventMulticaster, 914 * then it removes the old listener from it. 915 * Else, returns listener l. 916 * @param l the listener being removed from 917 * @param oldl the listener being removed 918 */ 919 protected static EventListener removeInternal(EventListener l, EventListener oldl) { 920 if (l == oldl || l == null) { 921 return null; 922 } else if (l instanceof AWTEventMulticaster) { 923 return ((AWTEventMulticaster)l).remove(oldl); 924 } else { 925 return l; // it's not here 926 } 927 } 928 929 930 /* Serialization support. 931 */ 932 933 protected void saveInternal(ObjectOutputStream s, String k) throws IOException { 934 if (a instanceof AWTEventMulticaster) { 935 ((AWTEventMulticaster)a).saveInternal(s, k); 936 } 937 else if (a instanceof Serializable) { 938 s.writeObject(k); 939 s.writeObject(a); 940 } 941 942 if (b instanceof AWTEventMulticaster) { 943 ((AWTEventMulticaster)b).saveInternal(s, k); 944 } 945 else if (b instanceof Serializable) { 946 s.writeObject(k); 947 s.writeObject(b); 948 } 949 } 950 951 protected static void save(ObjectOutputStream s, String k, EventListener l) throws IOException { 952 if (l == null) { 953 return; 954 } 955 else if (l instanceof AWTEventMulticaster) { 956 ((AWTEventMulticaster)l).saveInternal(s, k); 957 } 958 else if (l instanceof Serializable) { 959 s.writeObject(k); 960 s.writeObject(l); 961 } 962 } 963 964 /* 965 * Recursive method which returns a count of the number of listeners in 966 * EventListener, handling the (common) case of l actually being an 967 * AWTEventMulticaster. Additionally, only listeners of type listenerType 968 * are counted. Method modified to fix bug 4513402. -bchristi 969 */ 970 private static int getListenerCount(EventListener l, Class<?> listenerType) { 971 if (l instanceof AWTEventMulticaster) { 972 AWTEventMulticaster mc = (AWTEventMulticaster)l; 973 return getListenerCount(mc.a, listenerType) + 974 getListenerCount(mc.b, listenerType); 975 } 976 else { 977 // Only count listeners of correct type 978 return listenerType.isInstance(l) ? 1 : 0; 979 } 980 } 981 982 /* 983 * Recusive method which populates EventListener array a with EventListeners 984 * from l. l is usually an AWTEventMulticaster. Bug 4513402 revealed that 985 * if l differed in type from the element type of a, an ArrayStoreException 986 * would occur. Now l is only inserted into a if it's of the appropriate 987 * type. -bchristi 988 */ 989 private static int populateListenerArray(EventListener[] a, EventListener l, int index) { 990 if (l instanceof AWTEventMulticaster) { 991 AWTEventMulticaster mc = (AWTEventMulticaster)l; 992 int lhs = populateListenerArray(a, mc.a, index); 993 return populateListenerArray(a, mc.b, lhs); 994 } 995 else if (a.getClass().getComponentType().isInstance(l)) { 996 a[index] = l; 997 return index + 1; 998 } 999 // Skip nulls, instances of wrong class 1000 else { 1001 return index; 1002 } 1003 } 1004 1005 /** 1006 * Returns an array of all the objects chained as 1007 * <code><em>Foo</em>Listener</code>s by the specified 1008 * <code>java.util.EventListener</code>. 1009 * <code><em>Foo</em>Listener</code>s are chained by the 1010 * <code>AWTEventMulticaster</code> using the 1011 * <code>add<em>Foo</em>Listener</code> method. 1012 * If a <code>null</code> listener is specified, this method returns an 1013 * empty array. If the specified listener is not an instance of 1014 * <code>AWTEventMulticaster</code>, this method returns an array which 1015 * contains only the specified listener. If no such listeners are chained, 1016 * this method returns an empty array. 1017 * 1018 * @param l the specified <code>java.util.EventListener</code> 1019 * @param listenerType the type of listeners requested; this parameter 1020 * should specify an interface that descends from 1021 * <code>java.util.EventListener</code> 1022 * @return an array of all objects chained as 1023 * <code><em>Foo</em>Listener</code>s by the specified multicast 1024 * listener, or an empty array if no such listeners have been 1025 * chained by the specified multicast listener 1026 * @exception NullPointerException if the specified 1027 * {@code listenertype} parameter is {@code null} 1028 * @exception ClassCastException if <code>listenerType</code> 1029 * doesn't specify a class or interface that implements 1030 * <code>java.util.EventListener</code> 1031 * 1032 * @since 1.4 1033 */ 1034 @SuppressWarnings("unchecked") 1035 public static <T extends EventListener> T[] 1036 getListeners(EventListener l, Class<T> listenerType) 1037 { 1038 if (listenerType == null) { 1039 throw new NullPointerException ("Listener type should not be null"); 1040 } 1041 1042 int n = getListenerCount(l, listenerType); 1043 T[] result = (T[])Array.newInstance(listenerType, n); 1044 populateListenerArray(result, l, 0); 1045 return result; 1046 } 1047 }