1. /*
  2. * @(#)AWTEventMulticaster.java 1.37 04/05/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.awt.event.*;
  9. import java.lang.reflect.Array;
  10. import java.util.EventListener;
  11. import java.io.Serializable;
  12. import java.io.ObjectOutputStream;
  13. import java.io.IOException;
  14. import java.util.EventListener;
  15. /**
  16. * A class which implements efficient and thread-safe multi-cast event
  17. * dispatching for the AWT events defined in the java.awt.event package.
  18. * This class will manage an immutable structure consisting of a chain of
  19. * event listeners and will dispatch events to those listeners. Because
  20. * the structure is immutable, it is safe to use this API to add/remove
  21. * listeners during the process of an event dispatch operation.
  22. * However, event listeners added during the process of an event dispatch
  23. * operation will not be notified of the event currently being dispatched.
  24. *
  25. * An example of how this class could be used to implement a new
  26. * component which fires "action" events:
  27. *
  28. * <pre><code>
  29. * public myComponent extends Component {
  30. * ActionListener actionListener = null;
  31. *
  32. * public synchronized void addActionListener(ActionListener l) {
  33. * actionListener = AWTEventMulticaster.add(actionListener, l);
  34. * }
  35. * public synchronized void removeActionListener(ActionListener l) {
  36. * actionListener = AWTEventMulticaster.remove(actionListener, l);
  37. * }
  38. * public void processEvent(AWTEvent e) {
  39. * // when event occurs which causes "action" semantic
  40. * ActionListener listener = actionListener;
  41. * if (listener != null) {
  42. * listener.actionPerformed(new ActionEvent());
  43. * }
  44. * }
  45. * }
  46. * </code></pre>
  47. *
  48. * @author John Rose
  49. * @author Amy Fowler
  50. * @version 1.37, 05/05/04
  51. * @since 1.1
  52. */
  53. public class AWTEventMulticaster implements
  54. ComponentListener, ContainerListener, FocusListener, KeyListener,
  55. MouseListener, MouseMotionListener, WindowListener, WindowFocusListener,
  56. WindowStateListener, ActionListener, ItemListener, AdjustmentListener,
  57. TextListener, InputMethodListener, HierarchyListener,
  58. HierarchyBoundsListener, MouseWheelListener {
  59. protected final EventListener a, b;
  60. /**
  61. * Creates an event multicaster instance which chains listener-a
  62. * with listener-b. Input parameters <code>a</code> and <code>b</code>
  63. * should not be <code>null</code>, though implementations may vary in
  64. * choosing whether or not to throw <code>NullPointerException</code>
  65. * in that case.
  66. * @param a listener-a
  67. * @param b listener-b
  68. */
  69. protected AWTEventMulticaster(EventListener a, EventListener b) {
  70. this.a = a; this.b = b;
  71. }
  72. /**
  73. * Removes a listener from this multicaster and returns the
  74. * resulting multicast listener.
  75. * @param oldl the listener to be removed
  76. */
  77. protected EventListener remove(EventListener oldl) {
  78. if (oldl == a) return b;
  79. if (oldl == b) return a;
  80. EventListener a2 = removeInternal(a, oldl);
  81. EventListener b2 = removeInternal(b, oldl);
  82. if (a2 == a && b2 == b) {
  83. return this; // it's not here
  84. }
  85. return addInternal(a2, b2);
  86. }
  87. /**
  88. * Handles the componentResized event by invoking the
  89. * componentResized methods on listener-a and listener-b.
  90. * @param e the component event
  91. */
  92. public void componentResized(ComponentEvent e) {
  93. ((ComponentListener)a).componentResized(e);
  94. ((ComponentListener)b).componentResized(e);
  95. }
  96. /**
  97. * Handles the componentMoved event by invoking the
  98. * componentMoved methods on listener-a and listener-b.
  99. * @param e the component event
  100. */
  101. public void componentMoved(ComponentEvent e) {
  102. ((ComponentListener)a).componentMoved(e);
  103. ((ComponentListener)b).componentMoved(e);
  104. }
  105. /**
  106. * Handles the componentShown event by invoking the
  107. * componentShown methods on listener-a and listener-b.
  108. * @param e the component event
  109. */
  110. public void componentShown(ComponentEvent e) {
  111. ((ComponentListener)a).componentShown(e);
  112. ((ComponentListener)b).componentShown(e);
  113. }
  114. /**
  115. * Handles the componentHidden event by invoking the
  116. * componentHidden methods on listener-a and listener-b.
  117. * @param e the component event
  118. */
  119. public void componentHidden(ComponentEvent e) {
  120. ((ComponentListener)a).componentHidden(e);
  121. ((ComponentListener)b).componentHidden(e);
  122. }
  123. /**
  124. * Handles the componentAdded container event by invoking the
  125. * componentAdded methods on listener-a and listener-b.
  126. * @param e the component event
  127. */
  128. public void componentAdded(ContainerEvent e) {
  129. ((ContainerListener)a).componentAdded(e);
  130. ((ContainerListener)b).componentAdded(e);
  131. }
  132. /**
  133. * Handles the componentRemoved container event by invoking the
  134. * componentRemoved methods on listener-a and listener-b.
  135. * @param e the component event
  136. */
  137. public void componentRemoved(ContainerEvent e) {
  138. ((ContainerListener)a).componentRemoved(e);
  139. ((ContainerListener)b).componentRemoved(e);
  140. }
  141. /**
  142. * Handles the focusGained event by invoking the
  143. * focusGained methods on listener-a and listener-b.
  144. * @param e the focus event
  145. */
  146. public void focusGained(FocusEvent e) {
  147. ((FocusListener)a).focusGained(e);
  148. ((FocusListener)b).focusGained(e);
  149. }
  150. /**
  151. * Handles the focusLost event by invoking the
  152. * focusLost methods on listener-a and listener-b.
  153. * @param e the focus event
  154. */
  155. public void focusLost(FocusEvent e) {
  156. ((FocusListener)a).focusLost(e);
  157. ((FocusListener)b).focusLost(e);
  158. }
  159. /**
  160. * Handles the keyTyped event by invoking the
  161. * keyTyped methods on listener-a and listener-b.
  162. * @param e the key event
  163. */
  164. public void keyTyped(KeyEvent e) {
  165. ((KeyListener)a).keyTyped(e);
  166. ((KeyListener)b).keyTyped(e);
  167. }
  168. /**
  169. * Handles the keyPressed event by invoking the
  170. * keyPressed methods on listener-a and listener-b.
  171. * @param e the key event
  172. */
  173. public void keyPressed(KeyEvent e) {
  174. ((KeyListener)a).keyPressed(e);
  175. ((KeyListener)b).keyPressed(e);
  176. }
  177. /**
  178. * Handles the keyReleased event by invoking the
  179. * keyReleased methods on listener-a and listener-b.
  180. * @param e the key event
  181. */
  182. public void keyReleased(KeyEvent e) {
  183. ((KeyListener)a).keyReleased(e);
  184. ((KeyListener)b).keyReleased(e);
  185. }
  186. /**
  187. * Handles the mouseClicked event by invoking the
  188. * mouseClicked methods on listener-a and listener-b.
  189. * @param e the mouse event
  190. */
  191. public void mouseClicked(MouseEvent e) {
  192. ((MouseListener)a).mouseClicked(e);
  193. ((MouseListener)b).mouseClicked(e);
  194. }
  195. /**
  196. * Handles the mousePressed event by invoking the
  197. * mousePressed methods on listener-a and listener-b.
  198. * @param e the mouse event
  199. */
  200. public void mousePressed(MouseEvent e) {
  201. ((MouseListener)a).mousePressed(e);
  202. ((MouseListener)b).mousePressed(e);
  203. }
  204. /**
  205. * Handles the mouseReleased event by invoking the
  206. * mouseReleased methods on listener-a and listener-b.
  207. * @param e the mouse event
  208. */
  209. public void mouseReleased(MouseEvent e) {
  210. ((MouseListener)a).mouseReleased(e);
  211. ((MouseListener)b).mouseReleased(e);
  212. }
  213. /**
  214. * Handles the mouseEntered event by invoking the
  215. * mouseEntered methods on listener-a and listener-b.
  216. * @param e the mouse event
  217. */
  218. public void mouseEntered(MouseEvent e) {
  219. ((MouseListener)a).mouseEntered(e);
  220. ((MouseListener)b).mouseEntered(e);
  221. }
  222. /**
  223. * Handles the mouseExited event by invoking the
  224. * mouseExited methods on listener-a and listener-b.
  225. * @param e the mouse event
  226. */
  227. public void mouseExited(MouseEvent e) {
  228. ((MouseListener)a).mouseExited(e);
  229. ((MouseListener)b).mouseExited(e);
  230. }
  231. /**
  232. * Handles the mouseDragged event by invoking the
  233. * mouseDragged methods on listener-a and listener-b.
  234. * @param e the mouse event
  235. */
  236. public void mouseDragged(MouseEvent e) {
  237. ((MouseMotionListener)a).mouseDragged(e);
  238. ((MouseMotionListener)b).mouseDragged(e);
  239. }
  240. /**
  241. * Handles the mouseMoved event by invoking the
  242. * mouseMoved methods on listener-a and listener-b.
  243. * @param e the mouse event
  244. */
  245. public void mouseMoved(MouseEvent e) {
  246. ((MouseMotionListener)a).mouseMoved(e);
  247. ((MouseMotionListener)b).mouseMoved(e);
  248. }
  249. /**
  250. * Handles the windowOpened event by invoking the
  251. * windowOpened methods on listener-a and listener-b.
  252. * @param e the window event
  253. */
  254. public void windowOpened(WindowEvent e) {
  255. ((WindowListener)a).windowOpened(e);
  256. ((WindowListener)b).windowOpened(e);
  257. }
  258. /**
  259. * Handles the windowClosing event by invoking the
  260. * windowClosing methods on listener-a and listener-b.
  261. * @param e the window event
  262. */
  263. public void windowClosing(WindowEvent e) {
  264. ((WindowListener)a).windowClosing(e);
  265. ((WindowListener)b).windowClosing(e);
  266. }
  267. /**
  268. * Handles the windowClosed event by invoking the
  269. * windowClosed methods on listener-a and listener-b.
  270. * @param e the window event
  271. */
  272. public void windowClosed(WindowEvent e) {
  273. ((WindowListener)a).windowClosed(e);
  274. ((WindowListener)b).windowClosed(e);
  275. }
  276. /**
  277. * Handles the windowIconified event by invoking the
  278. * windowIconified methods on listener-a and listener-b.
  279. * @param e the window event
  280. */
  281. public void windowIconified(WindowEvent e) {
  282. ((WindowListener)a).windowIconified(e);
  283. ((WindowListener)b).windowIconified(e);
  284. }
  285. /**
  286. * Handles the windowDeiconfied event by invoking the
  287. * windowDeiconified methods on listener-a and listener-b.
  288. * @param e the window event
  289. */
  290. public void windowDeiconified(WindowEvent e) {
  291. ((WindowListener)a).windowDeiconified(e);
  292. ((WindowListener)b).windowDeiconified(e);
  293. }
  294. /**
  295. * Handles the windowActivated event by invoking the
  296. * windowActivated methods on listener-a and listener-b.
  297. * @param e the window event
  298. */
  299. public void windowActivated(WindowEvent e) {
  300. ((WindowListener)a).windowActivated(e);
  301. ((WindowListener)b).windowActivated(e);
  302. }
  303. /**
  304. * Handles the windowDeactivated event by invoking the
  305. * windowDeactivated methods on listener-a and listener-b.
  306. * @param e the window event
  307. */
  308. public void windowDeactivated(WindowEvent e) {
  309. ((WindowListener)a).windowDeactivated(e);
  310. ((WindowListener)b).windowDeactivated(e);
  311. }
  312. /**
  313. * Handles the windowStateChanged event by invoking the
  314. * windowStateChanged methods on listener-a and listener-b.
  315. * @param e the window event
  316. */
  317. public void windowStateChanged(WindowEvent e) {
  318. ((WindowStateListener)a).windowStateChanged(e);
  319. ((WindowStateListener)b).windowStateChanged(e);
  320. }
  321. /**
  322. * Handles the windowGainedFocus event by invoking the windowGainedFocus
  323. * methods on listener-a and listener-b.
  324. * @param e the window event
  325. */
  326. public void windowGainedFocus(WindowEvent e) {
  327. ((WindowFocusListener)a).windowGainedFocus(e);
  328. ((WindowFocusListener)b).windowGainedFocus(e);
  329. }
  330. /**
  331. * Handles the windowLostFocus event by invoking the windowLostFocus
  332. * methods on listener-a and listener-b.
  333. * @param e the window event
  334. */
  335. public void windowLostFocus(WindowEvent e) {
  336. ((WindowFocusListener)a).windowLostFocus(e);
  337. ((WindowFocusListener)b).windowLostFocus(e);
  338. }
  339. /**
  340. * Handles the actionPerformed event by invoking the
  341. * actionPerformed methods on listener-a and listener-b.
  342. * @param e the action event
  343. */
  344. public void actionPerformed(ActionEvent e) {
  345. ((ActionListener)a).actionPerformed(e);
  346. ((ActionListener)b).actionPerformed(e);
  347. }
  348. /**
  349. * Handles the itemStateChanged event by invoking the
  350. * itemStateChanged methods on listener-a and listener-b.
  351. * @param e the item event
  352. */
  353. public void itemStateChanged(ItemEvent e) {
  354. ((ItemListener)a).itemStateChanged(e);
  355. ((ItemListener)b).itemStateChanged(e);
  356. }
  357. /**
  358. * Handles the adjustmentValueChanged event by invoking the
  359. * adjustmentValueChanged methods on listener-a and listener-b.
  360. * @param e the adjustment event
  361. */
  362. public void adjustmentValueChanged(AdjustmentEvent e) {
  363. ((AdjustmentListener)a).adjustmentValueChanged(e);
  364. ((AdjustmentListener)b).adjustmentValueChanged(e);
  365. }
  366. public void textValueChanged(TextEvent e) {
  367. ((TextListener)a).textValueChanged(e);
  368. ((TextListener)b).textValueChanged(e);
  369. }
  370. /**
  371. * Handles the inputMethodTextChanged event by invoking the
  372. * inputMethodTextChanged methods on listener-a and listener-b.
  373. * @param e the item event
  374. */
  375. public void inputMethodTextChanged(InputMethodEvent e) {
  376. ((InputMethodListener)a).inputMethodTextChanged(e);
  377. ((InputMethodListener)b).inputMethodTextChanged(e);
  378. }
  379. /**
  380. * Handles the caretPositionChanged event by invoking the
  381. * caretPositionChanged methods on listener-a and listener-b.
  382. * @param e the item event
  383. */
  384. public void caretPositionChanged(InputMethodEvent e) {
  385. ((InputMethodListener)a).caretPositionChanged(e);
  386. ((InputMethodListener)b).caretPositionChanged(e);
  387. }
  388. /**
  389. * Handles the hierarchyChanged event by invoking the
  390. * hierarchyChanged methods on listener-a and listener-b.
  391. * @param e the item event
  392. */
  393. public void hierarchyChanged(HierarchyEvent e) {
  394. ((HierarchyListener)a).hierarchyChanged(e);
  395. ((HierarchyListener)b).hierarchyChanged(e);
  396. }
  397. /**
  398. * Handles the ancestorMoved event by invoking the
  399. * ancestorMoved methods on listener-a and listener-b.
  400. * @param e the item event
  401. */
  402. public void ancestorMoved(HierarchyEvent e) {
  403. ((HierarchyBoundsListener)a).ancestorMoved(e);
  404. ((HierarchyBoundsListener)b).ancestorMoved(e);
  405. }
  406. /**
  407. * Handles the ancestorResized event by invoking the
  408. * ancestorResized methods on listener-a and listener-b.
  409. * @param e the item event
  410. */
  411. public void ancestorResized(HierarchyEvent e) {
  412. ((HierarchyBoundsListener)a).ancestorResized(e);
  413. ((HierarchyBoundsListener)b).ancestorResized(e);
  414. }
  415. /**
  416. * Handles the mouseWheelMoved event by invoking the
  417. * mouseWheelMoved methods on listener-a and listener-b.
  418. * @param e the mouse event
  419. * @since 1.4
  420. */
  421. public void mouseWheelMoved(MouseWheelEvent e) {
  422. ((MouseWheelListener)a).mouseWheelMoved(e);
  423. ((MouseWheelListener)b).mouseWheelMoved(e);
  424. }
  425. /**
  426. * Adds component-listener-a with component-listener-b and
  427. * returns the resulting multicast listener.
  428. * @param a component-listener-a
  429. * @param b component-listener-b
  430. */
  431. public static ComponentListener add(ComponentListener a, ComponentListener b) {
  432. return (ComponentListener)addInternal(a, b);
  433. }
  434. /**
  435. * Adds container-listener-a with container-listener-b and
  436. * returns the resulting multicast listener.
  437. * @param a container-listener-a
  438. * @param b container-listener-b
  439. */
  440. public static ContainerListener add(ContainerListener a, ContainerListener b) {
  441. return (ContainerListener)addInternal(a, b);
  442. }
  443. /**
  444. * Adds focus-listener-a with focus-listener-b and
  445. * returns the resulting multicast listener.
  446. * @param a focus-listener-a
  447. * @param b focus-listener-b
  448. */
  449. public static FocusListener add(FocusListener a, FocusListener b) {
  450. return (FocusListener)addInternal(a, b);
  451. }
  452. /**
  453. * Adds key-listener-a with key-listener-b and
  454. * returns the resulting multicast listener.
  455. * @param a key-listener-a
  456. * @param b key-listener-b
  457. */
  458. public static KeyListener add(KeyListener a, KeyListener b) {
  459. return (KeyListener)addInternal(a, b);
  460. }
  461. /**
  462. * Adds mouse-listener-a with mouse-listener-b and
  463. * returns the resulting multicast listener.
  464. * @param a mouse-listener-a
  465. * @param b mouse-listener-b
  466. */
  467. public static MouseListener add(MouseListener a, MouseListener b) {
  468. return (MouseListener)addInternal(a, b);
  469. }
  470. /**
  471. * Adds mouse-motion-listener-a with mouse-motion-listener-b and
  472. * returns the resulting multicast listener.
  473. * @param a mouse-motion-listener-a
  474. * @param b mouse-motion-listener-b
  475. */
  476. public static MouseMotionListener add(MouseMotionListener a, MouseMotionListener b) {
  477. return (MouseMotionListener)addInternal(a, b);
  478. }
  479. /**
  480. * Adds window-listener-a with window-listener-b and
  481. * returns the resulting multicast listener.
  482. * @param a window-listener-a
  483. * @param b window-listener-b
  484. */
  485. public static WindowListener add(WindowListener a, WindowListener b) {
  486. return (WindowListener)addInternal(a, b);
  487. }
  488. /**
  489. * Adds window-state-listener-a with window-state-listener-b
  490. * and returns the resulting multicast listener.
  491. * @param a window-state-listener-a
  492. * @param b window-state-listener-b
  493. */
  494. public static WindowStateListener add(WindowStateListener a,
  495. WindowStateListener b) {
  496. return (WindowStateListener)addInternal(a, b);
  497. }
  498. /**
  499. * Adds window-focus-listener-a with window-focus-listener-b
  500. * and returns the resulting multicast listener.
  501. * @param a window-focus-listener-a
  502. * @param b window-focus-listener-b
  503. */
  504. public static WindowFocusListener add(WindowFocusListener a,
  505. WindowFocusListener b) {
  506. return (WindowFocusListener)addInternal(a, b);
  507. }
  508. /**
  509. * Adds action-listener-a with action-listener-b and
  510. * returns the resulting multicast listener.
  511. * @param a action-listener-a
  512. * @param b action-listener-b
  513. */
  514. public static ActionListener add(ActionListener a, ActionListener b) {
  515. return (ActionListener)addInternal(a, b);
  516. }
  517. /**
  518. * Adds item-listener-a with item-listener-b and
  519. * returns the resulting multicast listener.
  520. * @param a item-listener-a
  521. * @param b item-listener-b
  522. */
  523. public static ItemListener add(ItemListener a, ItemListener b) {
  524. return (ItemListener)addInternal(a, b);
  525. }
  526. /**
  527. * Adds adjustment-listener-a with adjustment-listener-b and
  528. * returns the resulting multicast listener.
  529. * @param a adjustment-listener-a
  530. * @param b adjustment-listener-b
  531. */
  532. public static AdjustmentListener add(AdjustmentListener a, AdjustmentListener b) {
  533. return (AdjustmentListener)addInternal(a, b);
  534. }
  535. public static TextListener add(TextListener a, TextListener b) {
  536. return (TextListener)addInternal(a, b);
  537. }
  538. /**
  539. * Adds input-method-listener-a with input-method-listener-b and
  540. * returns the resulting multicast listener.
  541. * @param a input-method-listener-a
  542. * @param b input-method-listener-b
  543. */
  544. public static InputMethodListener add(InputMethodListener a, InputMethodListener b) {
  545. return (InputMethodListener)addInternal(a, b);
  546. }
  547. /**
  548. * Adds hierarchy-listener-a with hierarchy-listener-b and
  549. * returns the resulting multicast listener.
  550. * @param a hierarchy-listener-a
  551. * @param b hierarchy-listener-b
  552. */
  553. public static HierarchyListener add(HierarchyListener a, HierarchyListener b) {
  554. return (HierarchyListener)addInternal(a, b);
  555. }
  556. /**
  557. * Adds hierarchy-bounds-listener-a with hierarchy-bounds-listener-b and
  558. * returns the resulting multicast listener.
  559. * @param a hierarchy-bounds-listener-a
  560. * @param b hierarchy-bounds-listener-b
  561. */
  562. public static HierarchyBoundsListener add(HierarchyBoundsListener a, HierarchyBoundsListener b) {
  563. return (HierarchyBoundsListener)addInternal(a, b);
  564. }
  565. /**
  566. * Adds mouse-wheel-listener-a with mouse-wheel-listener-b and
  567. * returns the resulting multicast listener.
  568. * @param a mouse-wheel-listener-a
  569. * @param b mouse-wheel-listener-b
  570. * @since 1.4
  571. */
  572. public static MouseWheelListener add(MouseWheelListener a,
  573. MouseWheelListener b) {
  574. return (MouseWheelListener)addInternal(a, b);
  575. }
  576. /**
  577. * Removes the old component-listener from component-listener-l and
  578. * returns the resulting multicast listener.
  579. * @param l component-listener-l
  580. * @param oldl the component-listener being removed
  581. */
  582. public static ComponentListener remove(ComponentListener l, ComponentListener oldl) {
  583. return (ComponentListener) removeInternal(l, oldl);
  584. }
  585. /**
  586. * Removes the old container-listener from container-listener-l and
  587. * returns the resulting multicast listener.
  588. * @param l container-listener-l
  589. * @param oldl the container-listener being removed
  590. */
  591. public static ContainerListener remove(ContainerListener l, ContainerListener oldl) {
  592. return (ContainerListener) removeInternal(l, oldl);
  593. }
  594. /**
  595. * Removes the old focus-listener from focus-listener-l and
  596. * returns the resulting multicast listener.
  597. * @param l focus-listener-l
  598. * @param oldl the focus-listener being removed
  599. */
  600. public static FocusListener remove(FocusListener l, FocusListener oldl) {
  601. return (FocusListener) removeInternal(l, oldl);
  602. }
  603. /**
  604. * Removes the old key-listener from key-listener-l and
  605. * returns the resulting multicast listener.
  606. * @param l key-listener-l
  607. * @param oldl the key-listener being removed
  608. */
  609. public static KeyListener remove(KeyListener l, KeyListener oldl) {
  610. return (KeyListener) removeInternal(l, oldl);
  611. }
  612. /**
  613. * Removes the old mouse-listener from mouse-listener-l and
  614. * returns the resulting multicast listener.
  615. * @param l mouse-listener-l
  616. * @param oldl the mouse-listener being removed
  617. */
  618. public static MouseListener remove(MouseListener l, MouseListener oldl) {
  619. return (MouseListener) removeInternal(l, oldl);
  620. }
  621. /**
  622. * Removes the old mouse-motion-listener from mouse-motion-listener-l
  623. * and returns the resulting multicast listener.
  624. * @param l mouse-motion-listener-l
  625. * @param oldl the mouse-motion-listener being removed
  626. */
  627. public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) {
  628. return (MouseMotionListener) removeInternal(l, oldl);
  629. }
  630. /**
  631. * Removes the old window-listener from window-listener-l and
  632. * returns the resulting multicast listener.
  633. * @param l window-listener-l
  634. * @param oldl the window-listener being removed
  635. */
  636. public static WindowListener remove(WindowListener l, WindowListener oldl) {
  637. return (WindowListener) removeInternal(l, oldl);
  638. }
  639. /**
  640. * Removes the old window-state-listener from window-state-listener-l
  641. * and returns the resulting multicast listener.
  642. * @param l window-state-listener-l
  643. * @param oldl the window-state-listener being removed
  644. */
  645. public static WindowStateListener remove(WindowStateListener l,
  646. WindowStateListener oldl) {
  647. return (WindowStateListener) removeInternal(l, oldl);
  648. }
  649. /**
  650. * Removes the old window-focus-listener from window-focus-listener-l
  651. * and returns the resulting multicast listener.
  652. * @param l window-focus-listener-l
  653. * @param oldl the window-focus-listener being removed
  654. */
  655. public static WindowFocusListener remove(WindowFocusListener l,
  656. WindowFocusListener oldl) {
  657. return (WindowFocusListener) removeInternal(l, oldl);
  658. }
  659. /**
  660. * Removes the old action-listener from action-listener-l and
  661. * returns the resulting multicast listener.
  662. * @param l action-listener-l
  663. * @param oldl the action-listener being removed
  664. */
  665. public static ActionListener remove(ActionListener l, ActionListener oldl) {
  666. return (ActionListener) removeInternal(l, oldl);
  667. }
  668. /**
  669. * Removes the old item-listener from item-listener-l and
  670. * returns the resulting multicast listener.
  671. * @param l item-listener-l
  672. * @param oldl the item-listener being removed
  673. */
  674. public static ItemListener remove(ItemListener l, ItemListener oldl) {
  675. return (ItemListener) removeInternal(l, oldl);
  676. }
  677. /**
  678. * Removes the old adjustment-listener from adjustment-listener-l and
  679. * returns the resulting multicast listener.
  680. * @param l adjustment-listener-l
  681. * @param oldl the adjustment-listener being removed
  682. */
  683. public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) {
  684. return (AdjustmentListener) removeInternal(l, oldl);
  685. }
  686. public static TextListener remove(TextListener l, TextListener oldl) {
  687. return (TextListener) removeInternal(l, oldl);
  688. }
  689. /**
  690. * Removes the old input-method-listener from input-method-listener-l and
  691. * returns the resulting multicast listener.
  692. * @param l input-method-listener-l
  693. * @param oldl the input-method-listener being removed
  694. */
  695. public static InputMethodListener remove(InputMethodListener l, InputMethodListener oldl) {
  696. return (InputMethodListener) removeInternal(l, oldl);
  697. }
  698. /**
  699. * Removes the old hierarchy-listener from hierarchy-listener-l and
  700. * returns the resulting multicast listener.
  701. * @param l hierarchy-listener-l
  702. * @param oldl the hierarchy-listener being removed
  703. */
  704. public static HierarchyListener remove(HierarchyListener l, HierarchyListener oldl) {
  705. return (HierarchyListener) removeInternal(l, oldl);
  706. }
  707. /**
  708. * Removes the old hierarchy-bounds-listener from
  709. * hierarchy-bounds-listener-l and returns the resulting multicast
  710. * listener.
  711. * @param l hierarchy-bounds-listener-l
  712. * @param oldl the hierarchy-bounds-listener being removed
  713. */
  714. public static HierarchyBoundsListener remove(HierarchyBoundsListener l, HierarchyBoundsListener oldl) {
  715. return (HierarchyBoundsListener) removeInternal(l, oldl);
  716. }
  717. /**
  718. * Removes the old mouse-wheel-listener from mouse-wheel-listener-l
  719. * and returns the resulting multicast listener.
  720. * @param l mouse-wheel-listener-l
  721. * @param oldl the mouse-wheel-listener being removed
  722. * @since 1.4
  723. */
  724. public static MouseWheelListener remove(MouseWheelListener l,
  725. MouseWheelListener oldl) {
  726. return (MouseWheelListener) removeInternal(l, oldl);
  727. }
  728. /**
  729. * Returns the resulting multicast listener from adding listener-a
  730. * and listener-b together.
  731. * If listener-a is null, it returns listener-b;
  732. * If listener-b is null, it returns listener-a
  733. * If neither are null, then it creates and returns
  734. * a new AWTEventMulticaster instance which chains a with b.
  735. * @param a event listener-a
  736. * @param b event listener-b
  737. */
  738. protected static EventListener addInternal(EventListener a, EventListener b) {
  739. if (a == null) return b;
  740. if (b == null) return a;
  741. return new AWTEventMulticaster(a, b);
  742. }
  743. /**
  744. * Returns the resulting multicast listener after removing the
  745. * old listener from listener-l.
  746. * If listener-l equals the old listener OR listener-l is null,
  747. * returns null.
  748. * Else if listener-l is an instance of AWTEventMulticaster,
  749. * then it removes the old listener from it.
  750. * Else, returns listener l.
  751. * @param l the listener being removed from
  752. * @param oldl the listener being removed
  753. */
  754. protected static EventListener removeInternal(EventListener l, EventListener oldl) {
  755. if (l == oldl || l == null) {
  756. return null;
  757. } else if (l instanceof AWTEventMulticaster) {
  758. return ((AWTEventMulticaster)l).remove(oldl);
  759. } else {
  760. return l; // it's not here
  761. }
  762. }
  763. /* Serialization support.
  764. */
  765. protected void saveInternal(ObjectOutputStream s, String k) throws IOException {
  766. if (a instanceof AWTEventMulticaster) {
  767. ((AWTEventMulticaster)a).saveInternal(s, k);
  768. }
  769. else if (a instanceof Serializable) {
  770. s.writeObject(k);
  771. s.writeObject(a);
  772. }
  773. if (b instanceof AWTEventMulticaster) {
  774. ((AWTEventMulticaster)b).saveInternal(s, k);
  775. }
  776. else if (b instanceof Serializable) {
  777. s.writeObject(k);
  778. s.writeObject(b);
  779. }
  780. }
  781. protected static void save(ObjectOutputStream s, String k, EventListener l) throws IOException {
  782. if (l == null) {
  783. return;
  784. }
  785. else if (l instanceof AWTEventMulticaster) {
  786. ((AWTEventMulticaster)l).saveInternal(s, k);
  787. }
  788. else if (l instanceof Serializable) {
  789. s.writeObject(k);
  790. s.writeObject(l);
  791. }
  792. }
  793. /*
  794. * Recursive method which returns a count of the number of listeners in
  795. * EventListener, handling the (common) case of l actually being an
  796. * AWTEventMulticaster. Additionally, only listeners of type listenerType
  797. * are counted. Method modified to fix bug 4513402. -bchristi
  798. */
  799. private static int getListenerCount(EventListener l, Class listenerType) {
  800. if (l instanceof AWTEventMulticaster) {
  801. AWTEventMulticaster mc = (AWTEventMulticaster)l;
  802. return getListenerCount(mc.a, listenerType) +
  803. getListenerCount(mc.b, listenerType);
  804. }
  805. else {
  806. // Only count listeners of correct type
  807. return listenerType.isInstance(l) ? 1 : 0;
  808. }
  809. }
  810. /*
  811. * Recusive method which populates EventListener array a with EventListeners
  812. * from l. l is usually an AWTEventMulticaster. Bug 4513402 revealed that
  813. * if l differed in type from the element type of a, an ArrayStoreException
  814. * would occur. Now l is only inserted into a if it's of the appropriate
  815. * type. -bchristi
  816. */
  817. private static int populateListenerArray(EventListener[] a, EventListener l, int index) {
  818. if (l instanceof AWTEventMulticaster) {
  819. AWTEventMulticaster mc = (AWTEventMulticaster)l;
  820. int lhs = populateListenerArray(a, mc.a, index);
  821. return populateListenerArray(a, mc.b, lhs);
  822. }
  823. else if (a.getClass().getComponentType().isInstance(l)) {
  824. a[index] = l;
  825. return index + 1;
  826. }
  827. // Skip nulls, instances of wrong class
  828. else {
  829. return index;
  830. }
  831. }
  832. /**
  833. * Returns an array of all the objects chained as
  834. * <code><em>Foo</em>Listener</code>s by the specified
  835. * <code>java.util.EventListener</code>.
  836. * <code><em>Foo</em>Listener</code>s are chained by the
  837. * <code>AWTEventMulticaster</code> using the
  838. * <code>add<em>Foo</em>Listener</code> method.
  839. * If a <code>null</code> listener is specified, this method returns an
  840. * empty array. If the specified listener is not an instance of
  841. * <code>AWTEventMulticaster</code>, this method returns an array which
  842. * contains only the specified listener. If no such listeners are chanined,
  843. * this method returns an empty array.
  844. *
  845. * @param l the specified <code>java.util.EventListener</code>
  846. * @param listenerType the type of listeners requested; this parameter
  847. * should specify an interface that descends from
  848. * <code>java.util.EventListener</code>
  849. * @return an array of all objects chained as
  850. * <code><em>Foo</em>Listener</code>s by the specified multicast
  851. * listener, or an empty array if no such listeners have been
  852. * chained by the specified multicast listener
  853. * @exception ClassCastException if <code>listenerType</code>
  854. * doesn't specify a class or interface that implements
  855. * <code>java.util.EventListener</code>
  856. *
  857. * @since 1.4
  858. */
  859. public static <T extends EventListener> T[]
  860. getListeners(EventListener l, Class<T> listenerType)
  861. {
  862. int n = getListenerCount(l, listenerType);
  863. T[] result = (T[])Array.newInstance(listenerType, n);
  864. populateListenerArray(result, l, 0);
  865. return result;
  866. }
  867. }