0001 /*
0002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025 package java.awt;
0026
0027 import java.awt.event.*;
0028 import java.lang.reflect.Array;
0029 import java.util.EventListener;
0030 import java.io.Serializable;
0031 import java.io.ObjectOutputStream;
0032 import java.io.IOException;
0033 import java.util.EventListener;
0034
0035 /**
0036 * {@code AWTEventMulticaster} implements efficient and thread-safe multi-cast
0037 * event dispatching for the AWT events defined in the {@code java.awt.event}
0038 * package.
0039 * <p>
0040 * The following example illustrates how to use this class:
0041 *
0042 * <pre><code>
0043 * public myComponent extends Component {
0044 * ActionListener actionListener = null;
0045 *
0046 * public synchronized void addActionListener(ActionListener l) {
0047 * actionListener = AWTEventMulticaster.add(actionListener, l);
0048 * }
0049 * public synchronized void removeActionListener(ActionListener l) {
0050 * actionListener = AWTEventMulticaster.remove(actionListener, l);
0051 * }
0052 * public void processEvent(AWTEvent e) {
0053 * // when event occurs which causes "action" semantic
0054 * ActionListener listener = actionListener;
0055 * if (listener != null) {
0056 * listener.actionPerformed(new ActionEvent());
0057 * }
0058 * }
0059 * }
0060 * </code></pre>
0061 * The important point to note is the first argument to the {@code
0062 * add} and {@code remove} methods is the field maintaining the
0063 * listeners. In addition you must assign the result of the {@code add}
0064 * and {@code remove} methods to the field maintaining the listeners.
0065 * <p>
0066 * {@code AWTEventMulticaster} is implemented as a pair of {@code
0067 * EventListeners} that are set at construction time. {@code
0068 * AWTEventMulticaster} is immutable. The {@code add} and {@code
0069 * remove} methods do not alter {@code AWTEventMulticaster} in
0070 * anyway. If necessary, a new {@code AWTEventMulticaster} is
0071 * created. In this way it is safe to add and remove listeners during
0072 * the process of an event dispatching. However, event listeners
0073 * added during the process of an event dispatch operation are not
0074 * notified of the event currently being dispatched.
0075 * <p>
0076 * All of the {@code add} methods allow {@code null} arguments. If the
0077 * first argument is {@code null}, the second argument is returned. If
0078 * the first argument is not {@code null} and the second argument is
0079 * {@code null}, the first argument is returned. If both arguments are
0080 * {@code non-null}, a new {@code AWTEventMulticaster} is created using
0081 * the two arguments and returned.
0082 * <p>
0083 * For the {@code remove} methods that take two arguments, the following is
0084 * returned:
0085 * <ul>
0086 * <li>{@code null}, if the first argument is {@code null}, or
0087 * the arguments are equal, by way of {@code ==}.
0088 * <li>the first argument, if the first argument is not an instance of
0089 * {@code AWTEventMulticaster}.
0090 * <li>result of invoking {@code remove(EventListener)} on the
0091 * first argument, supplying the second argument to the
0092 * {@code remove(EventListener)} method.
0093 * </ul>
0094 * <p>Swing makes use of
0095 * {@link javax.swing.event.EventListenerList EventListenerList} for
0096 * similar logic. Refer to it for details.
0097 *
0098 * @see javax.swing.event.EventListenerList
0099 *
0100 * @author John Rose
0101 * @author Amy Fowler
0102 * @version 1.47, 05/05/07
0103 * @since 1.1
0104 */
0105
0106 public class AWTEventMulticaster implements ComponentListener,
0107 ContainerListener, FocusListener, KeyListener, MouseListener,
0108 MouseMotionListener, WindowListener, WindowFocusListener,
0109 WindowStateListener, ActionListener, ItemListener,
0110 AdjustmentListener, TextListener, InputMethodListener,
0111 HierarchyListener, HierarchyBoundsListener, MouseWheelListener {
0112
0113 protected final EventListener a, b;
0114
0115 /**
0116 * Creates an event multicaster instance which chains listener-a
0117 * with listener-b. Input parameters <code>a</code> and <code>b</code>
0118 * should not be <code>null</code>, though implementations may vary in
0119 * choosing whether or not to throw <code>NullPointerException</code>
0120 * in that case.
0121 * @param a listener-a
0122 * @param b listener-b
0123 */
0124 protected AWTEventMulticaster(EventListener a, EventListener b) {
0125 this .a = a;
0126 this .b = b;
0127 }
0128
0129 /**
0130 * Removes a listener from this multicaster.
0131 * <p>
0132 * The returned multicaster contains all the listeners in this
0133 * multicaster with the exception of all occurrences of {@code oldl}.
0134 * If the resulting multicaster contains only one regular listener
0135 * the regular listener may be returned. If the resulting multicaster
0136 * is empty, then {@code null} may be returned instead.
0137 * <p>
0138 * No exception is thrown if {@code oldl} is {@code null}.
0139 *
0140 * @param oldl the listener to be removed
0141 * @return resulting listener
0142 */
0143 protected EventListener remove(EventListener oldl) {
0144 if (oldl == a)
0145 return b;
0146 if (oldl == b)
0147 return a;
0148 EventListener a2 = removeInternal(a, oldl);
0149 EventListener b2 = removeInternal(b, oldl);
0150 if (a2 == a && b2 == b) {
0151 return this ; // it's not here
0152 }
0153 return addInternal(a2, b2);
0154 }
0155
0156 /**
0157 * Handles the componentResized event by invoking the
0158 * componentResized methods on listener-a and listener-b.
0159 * @param e the component event
0160 */
0161 public void componentResized(ComponentEvent e) {
0162 ((ComponentListener) a).componentResized(e);
0163 ((ComponentListener) b).componentResized(e);
0164 }
0165
0166 /**
0167 * Handles the componentMoved event by invoking the
0168 * componentMoved methods on listener-a and listener-b.
0169 * @param e the component event
0170 */
0171 public void componentMoved(ComponentEvent e) {
0172 ((ComponentListener) a).componentMoved(e);
0173 ((ComponentListener) b).componentMoved(e);
0174 }
0175
0176 /**
0177 * Handles the componentShown event by invoking the
0178 * componentShown methods on listener-a and listener-b.
0179 * @param e the component event
0180 */
0181 public void componentShown(ComponentEvent e) {
0182 ((ComponentListener) a).componentShown(e);
0183 ((ComponentListener) b).componentShown(e);
0184 }
0185
0186 /**
0187 * Handles the componentHidden event by invoking the
0188 * componentHidden methods on listener-a and listener-b.
0189 * @param e the component event
0190 */
0191 public void componentHidden(ComponentEvent e) {
0192 ((ComponentListener) a).componentHidden(e);
0193 ((ComponentListener) b).componentHidden(e);
0194 }
0195
0196 /**
0197 * Handles the componentAdded container event by invoking the
0198 * componentAdded methods on listener-a and listener-b.
0199 * @param e the component event
0200 */
0201 public void componentAdded(ContainerEvent e) {
0202 ((ContainerListener) a).componentAdded(e);
0203 ((ContainerListener) b).componentAdded(e);
0204 }
0205
0206 /**
0207 * Handles the componentRemoved container event by invoking the
0208 * componentRemoved methods on listener-a and listener-b.
0209 * @param e the component event
0210 */
0211 public void componentRemoved(ContainerEvent e) {
0212 ((ContainerListener) a).componentRemoved(e);
0213 ((ContainerListener) b).componentRemoved(e);
0214 }
0215
0216 /**
0217 * Handles the focusGained event by invoking the
0218 * focusGained methods on listener-a and listener-b.
0219 * @param e the focus event
0220 */
0221 public void focusGained(FocusEvent e) {
0222 ((FocusListener) a).focusGained(e);
0223 ((FocusListener) b).focusGained(e);
0224 }
0225
0226 /**
0227 * Handles the focusLost event by invoking the
0228 * focusLost methods on listener-a and listener-b.
0229 * @param e the focus event
0230 */
0231 public void focusLost(FocusEvent e) {
0232 ((FocusListener) a).focusLost(e);
0233 ((FocusListener) b).focusLost(e);
0234 }
0235
0236 /**
0237 * Handles the keyTyped event by invoking the
0238 * keyTyped methods on listener-a and listener-b.
0239 * @param e the key event
0240 */
0241 public void keyTyped(KeyEvent e) {
0242 ((KeyListener) a).keyTyped(e);
0243 ((KeyListener) b).keyTyped(e);
0244 }
0245
0246 /**
0247 * Handles the keyPressed event by invoking the
0248 * keyPressed methods on listener-a and listener-b.
0249 * @param e the key event
0250 */
0251 public void keyPressed(KeyEvent e) {
0252 ((KeyListener) a).keyPressed(e);
0253 ((KeyListener) b).keyPressed(e);
0254 }
0255
0256 /**
0257 * Handles the keyReleased event by invoking the
0258 * keyReleased methods on listener-a and listener-b.
0259 * @param e the key event
0260 */
0261 public void keyReleased(KeyEvent e) {
0262 ((KeyListener) a).keyReleased(e);
0263 ((KeyListener) b).keyReleased(e);
0264 }
0265
0266 /**
0267 * Handles the mouseClicked event by invoking the
0268 * mouseClicked methods on listener-a and listener-b.
0269 * @param e the mouse event
0270 */
0271 public void mouseClicked(MouseEvent e) {
0272 ((MouseListener) a).mouseClicked(e);
0273 ((MouseListener) b).mouseClicked(e);
0274 }
0275
0276 /**
0277 * Handles the mousePressed event by invoking the
0278 * mousePressed methods on listener-a and listener-b.
0279 * @param e the mouse event
0280 */
0281 public void mousePressed(MouseEvent e) {
0282 ((MouseListener) a).mousePressed(e);
0283 ((MouseListener) b).mousePressed(e);
0284 }
0285
0286 /**
0287 * Handles the mouseReleased event by invoking the
0288 * mouseReleased methods on listener-a and listener-b.
0289 * @param e the mouse event
0290 */
0291 public void mouseReleased(MouseEvent e) {
0292 ((MouseListener) a).mouseReleased(e);
0293 ((MouseListener) b).mouseReleased(e);
0294 }
0295
0296 /**
0297 * Handles the mouseEntered event by invoking the
0298 * mouseEntered methods on listener-a and listener-b.
0299 * @param e the mouse event
0300 */
0301 public void mouseEntered(MouseEvent e) {
0302 ((MouseListener) a).mouseEntered(e);
0303 ((MouseListener) b).mouseEntered(e);
0304 }
0305
0306 /**
0307 * Handles the mouseExited event by invoking the
0308 * mouseExited methods on listener-a and listener-b.
0309 * @param e the mouse event
0310 */
0311 public void mouseExited(MouseEvent e) {
0312 ((MouseListener) a).mouseExited(e);
0313 ((MouseListener) b).mouseExited(e);
0314 }
0315
0316 /**
0317 * Handles the mouseDragged event by invoking the
0318 * mouseDragged methods on listener-a and listener-b.
0319 * @param e the mouse event
0320 */
0321 public void mouseDragged(MouseEvent e) {
0322 ((MouseMotionListener) a).mouseDragged(e);
0323 ((MouseMotionListener) b).mouseDragged(e);
0324 }
0325
0326 /**
0327 * Handles the mouseMoved event by invoking the
0328 * mouseMoved methods on listener-a and listener-b.
0329 * @param e the mouse event
0330 */
0331 public void mouseMoved(MouseEvent e) {
0332 ((MouseMotionListener) a).mouseMoved(e);
0333 ((MouseMotionListener) b).mouseMoved(e);
0334 }
0335
0336 /**
0337 * Handles the windowOpened event by invoking the
0338 * windowOpened methods on listener-a and listener-b.
0339 * @param e the window event
0340 */
0341 public void windowOpened(WindowEvent e) {
0342 ((WindowListener) a).windowOpened(e);
0343 ((WindowListener) b).windowOpened(e);
0344 }
0345
0346 /**
0347 * Handles the windowClosing event by invoking the
0348 * windowClosing methods on listener-a and listener-b.
0349 * @param e the window event
0350 */
0351 public void windowClosing(WindowEvent e) {
0352 ((WindowListener) a).windowClosing(e);
0353 ((WindowListener) b).windowClosing(e);
0354 }
0355
0356 /**
0357 * Handles the windowClosed event by invoking the
0358 * windowClosed methods on listener-a and listener-b.
0359 * @param e the window event
0360 */
0361 public void windowClosed(WindowEvent e) {
0362 ((WindowListener) a).windowClosed(e);
0363 ((WindowListener) b).windowClosed(e);
0364 }
0365
0366 /**
0367 * Handles the windowIconified event by invoking the
0368 * windowIconified methods on listener-a and listener-b.
0369 * @param e the window event
0370 */
0371 public void windowIconified(WindowEvent e) {
0372 ((WindowListener) a).windowIconified(e);
0373 ((WindowListener) b).windowIconified(e);
0374 }
0375
0376 /**
0377 * Handles the windowDeiconfied event by invoking the
0378 * windowDeiconified methods on listener-a and listener-b.
0379 * @param e the window event
0380 */
0381 public void windowDeiconified(WindowEvent e) {
0382 ((WindowListener) a).windowDeiconified(e);
0383 ((WindowListener) b).windowDeiconified(e);
0384 }
0385
0386 /**
0387 * Handles the windowActivated event by invoking the
0388 * windowActivated methods on listener-a and listener-b.
0389 * @param e the window event
0390 */
0391 public void windowActivated(WindowEvent e) {
0392 ((WindowListener) a).windowActivated(e);
0393 ((WindowListener) b).windowActivated(e);
0394 }
0395
0396 /**
0397 * Handles the windowDeactivated event by invoking the
0398 * windowDeactivated methods on listener-a and listener-b.
0399 * @param e the window event
0400 */
0401 public void windowDeactivated(WindowEvent e) {
0402 ((WindowListener) a).windowDeactivated(e);
0403 ((WindowListener) b).windowDeactivated(e);
0404 }
0405
0406 /**
0407 * Handles the windowStateChanged event by invoking the
0408 * windowStateChanged methods on listener-a and listener-b.
0409 * @param e the window event
0410 * @since 1.4
0411 */
0412 public void windowStateChanged(WindowEvent e) {
0413 ((WindowStateListener) a).windowStateChanged(e);
0414 ((WindowStateListener) b).windowStateChanged(e);
0415 }
0416
0417 /**
0418 * Handles the windowGainedFocus event by invoking the windowGainedFocus
0419 * methods on listener-a and listener-b.
0420 * @param e the window event
0421 * @since 1.4
0422 */
0423 public void windowGainedFocus(WindowEvent e) {
0424 ((WindowFocusListener) a).windowGainedFocus(e);
0425 ((WindowFocusListener) b).windowGainedFocus(e);
0426 }
0427
0428 /**
0429 * Handles the windowLostFocus event by invoking the windowLostFocus
0430 * methods on listener-a and listener-b.
0431 * @param e the window event
0432 * @since 1.4
0433 */
0434 public void windowLostFocus(WindowEvent e) {
0435 ((WindowFocusListener) a).windowLostFocus(e);
0436 ((WindowFocusListener) b).windowLostFocus(e);
0437 }
0438
0439 /**
0440 * Handles the actionPerformed event by invoking the
0441 * actionPerformed methods on listener-a and listener-b.
0442 * @param e the action event
0443 */
0444 public void actionPerformed(ActionEvent e) {
0445 ((ActionListener) a).actionPerformed(e);
0446 ((ActionListener) b).actionPerformed(e);
0447 }
0448
0449 /**
0450 * Handles the itemStateChanged event by invoking the
0451 * itemStateChanged methods on listener-a and listener-b.
0452 * @param e the item event
0453 */
0454 public void itemStateChanged(ItemEvent e) {
0455 ((ItemListener) a).itemStateChanged(e);
0456 ((ItemListener) b).itemStateChanged(e);
0457 }
0458
0459 /**
0460 * Handles the adjustmentValueChanged event by invoking the
0461 * adjustmentValueChanged methods on listener-a and listener-b.
0462 * @param e the adjustment event
0463 */
0464 public void adjustmentValueChanged(AdjustmentEvent e) {
0465 ((AdjustmentListener) a).adjustmentValueChanged(e);
0466 ((AdjustmentListener) b).adjustmentValueChanged(e);
0467 }
0468
0469 public void textValueChanged(TextEvent e) {
0470 ((TextListener) a).textValueChanged(e);
0471 ((TextListener) b).textValueChanged(e);
0472 }
0473
0474 /**
0475 * Handles the inputMethodTextChanged event by invoking the
0476 * inputMethodTextChanged methods on listener-a and listener-b.
0477 * @param e the item event
0478 */
0479 public void inputMethodTextChanged(InputMethodEvent e) {
0480 ((InputMethodListener) a).inputMethodTextChanged(e);
0481 ((InputMethodListener) b).inputMethodTextChanged(e);
0482 }
0483
0484 /**
0485 * Handles the caretPositionChanged event by invoking the
0486 * caretPositionChanged methods on listener-a and listener-b.
0487 * @param e the item event
0488 */
0489 public void caretPositionChanged(InputMethodEvent e) {
0490 ((InputMethodListener) a).caretPositionChanged(e);
0491 ((InputMethodListener) b).caretPositionChanged(e);
0492 }
0493
0494 /**
0495 * Handles the hierarchyChanged event by invoking the
0496 * hierarchyChanged methods on listener-a and listener-b.
0497 * @param e the item event
0498 * @since 1.3
0499 */
0500 public void hierarchyChanged(HierarchyEvent e) {
0501 ((HierarchyListener) a).hierarchyChanged(e);
0502 ((HierarchyListener) b).hierarchyChanged(e);
0503 }
0504
0505 /**
0506 * Handles the ancestorMoved event by invoking the
0507 * ancestorMoved methods on listener-a and listener-b.
0508 * @param e the item event
0509 * @since 1.3
0510 */
0511 public void ancestorMoved(HierarchyEvent e) {
0512 ((HierarchyBoundsListener) a).ancestorMoved(e);
0513 ((HierarchyBoundsListener) b).ancestorMoved(e);
0514 }
0515
0516 /**
0517 * Handles the ancestorResized event by invoking the
0518 * ancestorResized methods on listener-a and listener-b.
0519 * @param e the item event
0520 * @since 1.3
0521 */
0522 public void ancestorResized(HierarchyEvent e) {
0523 ((HierarchyBoundsListener) a).ancestorResized(e);
0524 ((HierarchyBoundsListener) b).ancestorResized(e);
0525 }
0526
0527 /**
0528 * Handles the mouseWheelMoved event by invoking the
0529 * mouseWheelMoved methods on listener-a and listener-b.
0530 * @param e the mouse event
0531 * @since 1.4
0532 */
0533 public void mouseWheelMoved(MouseWheelEvent e) {
0534 ((MouseWheelListener) a).mouseWheelMoved(e);
0535 ((MouseWheelListener) b).mouseWheelMoved(e);
0536 }
0537
0538 /**
0539 * Adds component-listener-a with component-listener-b and
0540 * returns the resulting multicast listener.
0541 * @param a component-listener-a
0542 * @param b component-listener-b
0543 */
0544 public static ComponentListener add(ComponentListener a,
0545 ComponentListener b) {
0546 return (ComponentListener) addInternal(a, b);
0547 }
0548
0549 /**
0550 * Adds container-listener-a with container-listener-b and
0551 * returns the resulting multicast listener.
0552 * @param a container-listener-a
0553 * @param b container-listener-b
0554 */
0555 public static ContainerListener add(ContainerListener a,
0556 ContainerListener b) {
0557 return (ContainerListener) addInternal(a, b);
0558 }
0559
0560 /**
0561 * Adds focus-listener-a with focus-listener-b and
0562 * returns the resulting multicast listener.
0563 * @param a focus-listener-a
0564 * @param b focus-listener-b
0565 */
0566 public static FocusListener add(FocusListener a, FocusListener b) {
0567 return (FocusListener) addInternal(a, b);
0568 }
0569
0570 /**
0571 * Adds key-listener-a with key-listener-b and
0572 * returns the resulting multicast listener.
0573 * @param a key-listener-a
0574 * @param b key-listener-b
0575 */
0576 public static KeyListener add(KeyListener a, KeyListener b) {
0577 return (KeyListener) addInternal(a, b);
0578 }
0579
0580 /**
0581 * Adds mouse-listener-a with mouse-listener-b and
0582 * returns the resulting multicast listener.
0583 * @param a mouse-listener-a
0584 * @param b mouse-listener-b
0585 */
0586 public static MouseListener add(MouseListener a, MouseListener b) {
0587 return (MouseListener) addInternal(a, b);
0588 }
0589
0590 /**
0591 * Adds mouse-motion-listener-a with mouse-motion-listener-b and
0592 * returns the resulting multicast listener.
0593 * @param a mouse-motion-listener-a
0594 * @param b mouse-motion-listener-b
0595 */
0596 public static MouseMotionListener add(MouseMotionListener a,
0597 MouseMotionListener b) {
0598 return (MouseMotionListener) addInternal(a, b);
0599 }
0600
0601 /**
0602 * Adds window-listener-a with window-listener-b and
0603 * returns the resulting multicast listener.
0604 * @param a window-listener-a
0605 * @param b window-listener-b
0606 */
0607 public static WindowListener add(WindowListener a, WindowListener b) {
0608 return (WindowListener) addInternal(a, b);
0609 }
0610
0611 /**
0612 * Adds window-state-listener-a with window-state-listener-b
0613 * and returns the resulting multicast listener.
0614 * @param a window-state-listener-a
0615 * @param b window-state-listener-b
0616 * @since 1.4
0617 */
0618 public static WindowStateListener add(WindowStateListener a,
0619 WindowStateListener b) {
0620 return (WindowStateListener) addInternal(a, b);
0621 }
0622
0623 /**
0624 * Adds window-focus-listener-a with window-focus-listener-b
0625 * and returns the resulting multicast listener.
0626 * @param a window-focus-listener-a
0627 * @param b window-focus-listener-b
0628 * @since 1.4
0629 */
0630 public static WindowFocusListener add(WindowFocusListener a,
0631 WindowFocusListener b) {
0632 return (WindowFocusListener) addInternal(a, b);
0633 }
0634
0635 /**
0636 * Adds action-listener-a with action-listener-b and
0637 * returns the resulting multicast listener.
0638 * @param a action-listener-a
0639 * @param b action-listener-b
0640 */
0641 public static ActionListener add(ActionListener a, ActionListener b) {
0642 return (ActionListener) addInternal(a, b);
0643 }
0644
0645 /**
0646 * Adds item-listener-a with item-listener-b and
0647 * returns the resulting multicast listener.
0648 * @param a item-listener-a
0649 * @param b item-listener-b
0650 */
0651 public static ItemListener add(ItemListener a, ItemListener b) {
0652 return (ItemListener) addInternal(a, b);
0653 }
0654
0655 /**
0656 * Adds adjustment-listener-a with adjustment-listener-b and
0657 * returns the resulting multicast listener.
0658 * @param a adjustment-listener-a
0659 * @param b adjustment-listener-b
0660 */
0661 public static AdjustmentListener add(AdjustmentListener a,
0662 AdjustmentListener b) {
0663 return (AdjustmentListener) addInternal(a, b);
0664 }
0665
0666 public static TextListener add(TextListener a, TextListener b) {
0667 return (TextListener) addInternal(a, b);
0668 }
0669
0670 /**
0671 * Adds input-method-listener-a with input-method-listener-b and
0672 * returns the resulting multicast listener.
0673 * @param a input-method-listener-a
0674 * @param b input-method-listener-b
0675 */
0676 public static InputMethodListener add(InputMethodListener a,
0677 InputMethodListener b) {
0678 return (InputMethodListener) addInternal(a, b);
0679 }
0680
0681 /**
0682 * Adds hierarchy-listener-a with hierarchy-listener-b and
0683 * returns the resulting multicast listener.
0684 * @param a hierarchy-listener-a
0685 * @param b hierarchy-listener-b
0686 * @since 1.3
0687 */
0688 public static HierarchyListener add(HierarchyListener a,
0689 HierarchyListener b) {
0690 return (HierarchyListener) addInternal(a, b);
0691 }
0692
0693 /**
0694 * Adds hierarchy-bounds-listener-a with hierarchy-bounds-listener-b and
0695 * returns the resulting multicast listener.
0696 * @param a hierarchy-bounds-listener-a
0697 * @param b hierarchy-bounds-listener-b
0698 * @since 1.3
0699 */
0700 public static HierarchyBoundsListener add(
0701 HierarchyBoundsListener a, HierarchyBoundsListener b) {
0702 return (HierarchyBoundsListener) addInternal(a, b);
0703 }
0704
0705 /**
0706 * Adds mouse-wheel-listener-a with mouse-wheel-listener-b and
0707 * returns the resulting multicast listener.
0708 * @param a mouse-wheel-listener-a
0709 * @param b mouse-wheel-listener-b
0710 * @since 1.4
0711 */
0712 public static MouseWheelListener add(MouseWheelListener a,
0713 MouseWheelListener b) {
0714 return (MouseWheelListener) addInternal(a, b);
0715 }
0716
0717 /**
0718 * Removes the old component-listener from component-listener-l and
0719 * returns the resulting multicast listener.
0720 * @param l component-listener-l
0721 * @param oldl the component-listener being removed
0722 */
0723 public static ComponentListener remove(ComponentListener l,
0724 ComponentListener oldl) {
0725 return (ComponentListener) removeInternal(l, oldl);
0726 }
0727
0728 /**
0729 * Removes the old container-listener from container-listener-l and
0730 * returns the resulting multicast listener.
0731 * @param l container-listener-l
0732 * @param oldl the container-listener being removed
0733 */
0734 public static ContainerListener remove(ContainerListener l,
0735 ContainerListener oldl) {
0736 return (ContainerListener) removeInternal(l, oldl);
0737 }
0738
0739 /**
0740 * Removes the old focus-listener from focus-listener-l and
0741 * returns the resulting multicast listener.
0742 * @param l focus-listener-l
0743 * @param oldl the focus-listener being removed
0744 */
0745 public static FocusListener remove(FocusListener l,
0746 FocusListener oldl) {
0747 return (FocusListener) removeInternal(l, oldl);
0748 }
0749
0750 /**
0751 * Removes the old key-listener from key-listener-l and
0752 * returns the resulting multicast listener.
0753 * @param l key-listener-l
0754 * @param oldl the key-listener being removed
0755 */
0756 public static KeyListener remove(KeyListener l, KeyListener oldl) {
0757 return (KeyListener) removeInternal(l, oldl);
0758 }
0759
0760 /**
0761 * Removes the old mouse-listener from mouse-listener-l and
0762 * returns the resulting multicast listener.
0763 * @param l mouse-listener-l
0764 * @param oldl the mouse-listener being removed
0765 */
0766 public static MouseListener remove(MouseListener l,
0767 MouseListener oldl) {
0768 return (MouseListener) removeInternal(l, oldl);
0769 }
0770
0771 /**
0772 * Removes the old mouse-motion-listener from mouse-motion-listener-l
0773 * and returns the resulting multicast listener.
0774 * @param l mouse-motion-listener-l
0775 * @param oldl the mouse-motion-listener being removed
0776 */
0777 public static MouseMotionListener remove(MouseMotionListener l,
0778 MouseMotionListener oldl) {
0779 return (MouseMotionListener) removeInternal(l, oldl);
0780 }
0781
0782 /**
0783 * Removes the old window-listener from window-listener-l and
0784 * returns the resulting multicast listener.
0785 * @param l window-listener-l
0786 * @param oldl the window-listener being removed
0787 */
0788 public static WindowListener remove(WindowListener l,
0789 WindowListener oldl) {
0790 return (WindowListener) removeInternal(l, oldl);
0791 }
0792
0793 /**
0794 * Removes the old window-state-listener from window-state-listener-l
0795 * and returns the resulting multicast listener.
0796 * @param l window-state-listener-l
0797 * @param oldl the window-state-listener being removed
0798 * @since 1.4
0799 */
0800 public static WindowStateListener remove(WindowStateListener l,
0801 WindowStateListener oldl) {
0802 return (WindowStateListener) removeInternal(l, oldl);
0803 }
0804
0805 /**
0806 * Removes the old window-focus-listener from window-focus-listener-l
0807 * and returns the resulting multicast listener.
0808 * @param l window-focus-listener-l
0809 * @param oldl the window-focus-listener being removed
0810 * @since 1.4
0811 */
0812 public static WindowFocusListener remove(WindowFocusListener l,
0813 WindowFocusListener oldl) {
0814 return (WindowFocusListener) removeInternal(l, oldl);
0815 }
0816
0817 /**
0818 * Removes the old action-listener from action-listener-l and
0819 * returns the resulting multicast listener.
0820 * @param l action-listener-l
0821 * @param oldl the action-listener being removed
0822 */
0823 public static ActionListener remove(ActionListener l,
0824 ActionListener oldl) {
0825 return (ActionListener) removeInternal(l, oldl);
0826 }
0827
0828 /**
0829 * Removes the old item-listener from item-listener-l and
0830 * returns the resulting multicast listener.
0831 * @param l item-listener-l
0832 * @param oldl the item-listener being removed
0833 */
0834 public static ItemListener remove(ItemListener l, ItemListener oldl) {
0835 return (ItemListener) removeInternal(l, oldl);
0836 }
0837
0838 /**
0839 * Removes the old adjustment-listener from adjustment-listener-l and
0840 * returns the resulting multicast listener.
0841 * @param l adjustment-listener-l
0842 * @param oldl the adjustment-listener being removed
0843 */
0844 public static AdjustmentListener remove(AdjustmentListener l,
0845 AdjustmentListener oldl) {
0846 return (AdjustmentListener) removeInternal(l, oldl);
0847 }
0848
0849 public static TextListener remove(TextListener l, TextListener oldl) {
0850 return (TextListener) removeInternal(l, oldl);
0851 }
0852
0853 /**
0854 * Removes the old input-method-listener from input-method-listener-l and
0855 * returns the resulting multicast listener.
0856 * @param l input-method-listener-l
0857 * @param oldl the input-method-listener being removed
0858 */
0859 public static InputMethodListener remove(InputMethodListener l,
0860 InputMethodListener oldl) {
0861 return (InputMethodListener) removeInternal(l, oldl);
0862 }
0863
0864 /**
0865 * Removes the old hierarchy-listener from hierarchy-listener-l and
0866 * returns the resulting multicast listener.
0867 * @param l hierarchy-listener-l
0868 * @param oldl the hierarchy-listener being removed
0869 * @since 1.3
0870 */
0871 public static HierarchyListener remove(HierarchyListener l,
0872 HierarchyListener oldl) {
0873 return (HierarchyListener) removeInternal(l, oldl);
0874 }
0875
0876 /**
0877 * Removes the old hierarchy-bounds-listener from
0878 * hierarchy-bounds-listener-l and returns the resulting multicast
0879 * listener.
0880 * @param l hierarchy-bounds-listener-l
0881 * @param oldl the hierarchy-bounds-listener being removed
0882 * @since 1.3
0883 */
0884 public static HierarchyBoundsListener remove(
0885 HierarchyBoundsListener l, HierarchyBoundsListener oldl) {
0886 return (HierarchyBoundsListener) removeInternal(l, oldl);
0887 }
0888
0889 /**
0890 * Removes the old mouse-wheel-listener from mouse-wheel-listener-l
0891 * and returns the resulting multicast listener.
0892 * @param l mouse-wheel-listener-l
0893 * @param oldl the mouse-wheel-listener being removed
0894 * @since 1.4
0895 */
0896 public static MouseWheelListener remove(MouseWheelListener l,
0897 MouseWheelListener oldl) {
0898 return (MouseWheelListener) removeInternal(l, oldl);
0899 }
0900
0901 /**
0902 * Returns the resulting multicast listener from adding listener-a
0903 * and listener-b together.
0904 * If listener-a is null, it returns listener-b;
0905 * If listener-b is null, it returns listener-a
0906 * If neither are null, then it creates and returns
0907 * a new AWTEventMulticaster instance which chains a with b.
0908 * @param a event listener-a
0909 * @param b event listener-b
0910 */
0911 protected static EventListener addInternal(EventListener a,
0912 EventListener b) {
0913 if (a == null)
0914 return b;
0915 if (b == null)
0916 return a;
0917 return new AWTEventMulticaster(a, b);
0918 }
0919
0920 /**
0921 * Returns the resulting multicast listener after removing the
0922 * old listener from listener-l.
0923 * If listener-l equals the old listener OR listener-l is null,
0924 * returns null.
0925 * Else if listener-l is an instance of AWTEventMulticaster,
0926 * then it removes the old listener from it.
0927 * Else, returns listener l.
0928 * @param l the listener being removed from
0929 * @param oldl the listener being removed
0930 */
0931 protected static EventListener removeInternal(EventListener l,
0932 EventListener oldl) {
0933 if (l == oldl || l == null) {
0934 return null;
0935 } else if (l instanceof AWTEventMulticaster) {
0936 return ((AWTEventMulticaster) l).remove(oldl);
0937 } else {
0938 return l; // it's not here
0939 }
0940 }
0941
0942 /* Serialization support.
0943 */
0944
0945 protected void saveInternal(ObjectOutputStream s, String k)
0946 throws IOException {
0947 if (a instanceof AWTEventMulticaster) {
0948 ((AWTEventMulticaster) a).saveInternal(s, k);
0949 } else if (a instanceof Serializable) {
0950 s.writeObject(k);
0951 s.writeObject(a);
0952 }
0953
0954 if (b instanceof AWTEventMulticaster) {
0955 ((AWTEventMulticaster) b).saveInternal(s, k);
0956 } else if (b instanceof Serializable) {
0957 s.writeObject(k);
0958 s.writeObject(b);
0959 }
0960 }
0961
0962 protected static void save(ObjectOutputStream s, String k,
0963 EventListener l) throws IOException {
0964 if (l == null) {
0965 return;
0966 } else if (l instanceof AWTEventMulticaster) {
0967 ((AWTEventMulticaster) l).saveInternal(s, k);
0968 } else if (l instanceof Serializable) {
0969 s.writeObject(k);
0970 s.writeObject(l);
0971 }
0972 }
0973
0974 /*
0975 * Recursive method which returns a count of the number of listeners in
0976 * EventListener, handling the (common) case of l actually being an
0977 * AWTEventMulticaster. Additionally, only listeners of type listenerType
0978 * are counted. Method modified to fix bug 4513402. -bchristi
0979 */
0980 private static int getListenerCount(EventListener l,
0981 Class listenerType) {
0982 if (l instanceof AWTEventMulticaster) {
0983 AWTEventMulticaster mc = (AWTEventMulticaster) l;
0984 return getListenerCount(mc.a, listenerType)
0985 + getListenerCount(mc.b, listenerType);
0986 } else {
0987 // Only count listeners of correct type
0988 return listenerType.isInstance(l) ? 1 : 0;
0989 }
0990 }
0991
0992 /*
0993 * Recusive method which populates EventListener array a with EventListeners
0994 * from l. l is usually an AWTEventMulticaster. Bug 4513402 revealed that
0995 * if l differed in type from the element type of a, an ArrayStoreException
0996 * would occur. Now l is only inserted into a if it's of the appropriate
0997 * type. -bchristi
0998 */
0999 private static int populateListenerArray(EventListener[] a,
1000 EventListener l, int index) {
1001 if (l instanceof AWTEventMulticaster) {
1002 AWTEventMulticaster mc = (AWTEventMulticaster) l;
1003 int lhs = populateListenerArray(a, mc.a, index);
1004 return populateListenerArray(a, mc.b, lhs);
1005 } else if (a.getClass().getComponentType().isInstance(l)) {
1006 a[index] = l;
1007 return index + 1;
1008 }
1009 // Skip nulls, instances of wrong class
1010 else {
1011 return index;
1012 }
1013 }
1014
1015 /**
1016 * Returns an array of all the objects chained as
1017 * <code><em>Foo</em>Listener</code>s by the specified
1018 * <code>java.util.EventListener</code>.
1019 * <code><em>Foo</em>Listener</code>s are chained by the
1020 * <code>AWTEventMulticaster</code> using the
1021 * <code>add<em>Foo</em>Listener</code> method.
1022 * If a <code>null</code> listener is specified, this method returns an
1023 * empty array. If the specified listener is not an instance of
1024 * <code>AWTEventMulticaster</code>, this method returns an array which
1025 * contains only the specified listener. If no such listeners are chanined,
1026 * this method returns an empty array.
1027 *
1028 * @param l the specified <code>java.util.EventListener</code>
1029 * @param listenerType the type of listeners requested; this parameter
1030 * should specify an interface that descends from
1031 * <code>java.util.EventListener</code>
1032 * @return an array of all objects chained as
1033 * <code><em>Foo</em>Listener</code>s by the specified multicast
1034 * listener, or an empty array if no such listeners have been
1035 * chained by the specified multicast listener
1036 * @exception NullPointerException if the specified
1037 * {@code listenertype} parameter is {@code null}
1038 * @exception ClassCastException if <code>listenerType</code>
1039 * doesn't specify a class or interface that implements
1040 * <code>java.util.EventListener</code>
1041 *
1042 * @since 1.4
1043 */
1044 public static <T extends EventListener> T[] getListeners(
1045 EventListener l, Class<T> listenerType) {
1046 if (listenerType == null) {
1047 throw new NullPointerException(
1048 "Listener type should not be null");
1049 }
1050
1051 int n = getListenerCount(l, listenerType);
1052 T[] result = (T[]) Array.newInstance(listenerType, n);
1053 populateListenerArray(result, l, 0);
1054 return result;
1055 }
1056 }
|