1. /*
  2. * @(#)AWTEventMulticaster.java 1.21 01/11/29
  3. *
  4. * Copyright 2002 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.util.EventListener;
  10. import java.io.Serializable;
  11. import java.io.ObjectOutputStream;
  12. import java.io.IOException;
  13. /**
  14. * A class which implements efficient and thread-safe multi-cast event
  15. * dispatching for the AWT events defined in the java.awt.event package.
  16. * This class will manage an immutable structure consisting of a chain of
  17. * event listeners and will dispatch events to those listeners. Because
  18. * the structure is immutable, it is safe to use this API to add/remove
  19. * listeners during the process of an event dispatch operation.
  20. *
  21. * An example of how this class could be used to implement a new
  22. * component which fires "action" events:
  23. *
  24. * <pre><code>
  25. * public myComponent extends Component {
  26. * ActionListener actionListener = null;
  27. *
  28. * public synchronized void addActionListener(ActionListener l) {
  29. * actionListener = AWTEventMulticaster.add(actionListener, l);
  30. * }
  31. * public synchronized void removeActionListener(ActionListener l) {
  32. * actionListener = AWTEventMulticaster.remove(actionListener, l);
  33. * }
  34. * public void processEvent(AWTEvent e) {
  35. * // when event occurs which causes "action" semantic
  36. * if (actionListener != null) {
  37. * actionListener.actionPerformed(new ActionEvent());
  38. * }
  39. * }
  40. * </code></pre>
  41. *
  42. * @version 1.21, 11/29/01
  43. * @author John Rose
  44. * @author Amy Fowler
  45. */
  46. public class AWTEventMulticaster implements
  47. ComponentListener, ContainerListener, FocusListener, KeyListener,
  48. MouseListener, MouseMotionListener, WindowListener,
  49. ActionListener, ItemListener, AdjustmentListener,
  50. TextListener, InputMethodListener {
  51. protected final EventListener a, b;
  52. /**
  53. * Creates an event multicaster instance which chains listener-a
  54. * with listener-b. Input parameters <code>a</code> and <code>b</code>
  55. * should not be <code>null</code>, though implementations may vary in
  56. * choosing whether or not to throw <code>NullPointerException</code>
  57. * in that case.
  58. * @param a listener-a
  59. * @param b listener-b
  60. */
  61. protected AWTEventMulticaster(EventListener a, EventListener b) {
  62. this.a = a; this.b = b;
  63. }
  64. /**
  65. * Removes a listener from this multicaster and returns the
  66. * resulting multicast listener.
  67. * @param oldl the listener to be removed
  68. */
  69. protected EventListener remove(EventListener oldl) {
  70. if (oldl == a) return b;
  71. if (oldl == b) return a;
  72. EventListener a2 = removeInternal(a, oldl);
  73. EventListener b2 = removeInternal(b, oldl);
  74. if (a2 == a && b2 == b) {
  75. return this; // it's not here
  76. }
  77. return addInternal(a2, b2);
  78. }
  79. /**
  80. * Handles the componentResized event by invoking the
  81. * componentResized methods on listener-a and listener-b.
  82. * @param e the component event
  83. */
  84. public void componentResized(ComponentEvent e) {
  85. ((ComponentListener)a).componentResized(e);
  86. ((ComponentListener)b).componentResized(e);
  87. }
  88. /**
  89. * Handles the componentMoved event by invoking the
  90. * componentMoved methods on listener-a and listener-b.
  91. * @param e the component event
  92. */
  93. public void componentMoved(ComponentEvent e) {
  94. ((ComponentListener)a).componentMoved(e);
  95. ((ComponentListener)b).componentMoved(e);
  96. }
  97. /**
  98. * Handles the componentShown event by invoking the
  99. * componentShown methods on listener-a and listener-b.
  100. * @param e the component event
  101. */
  102. public void componentShown(ComponentEvent e) {
  103. ((ComponentListener)a).componentShown(e);
  104. ((ComponentListener)b).componentShown(e);
  105. }
  106. /**
  107. * Handles the componentHidden event by invoking the
  108. * componentHidden methods on listener-a and listener-b.
  109. * @param e the component event
  110. */
  111. public void componentHidden(ComponentEvent e) {
  112. ((ComponentListener)a).componentHidden(e);
  113. ((ComponentListener)b).componentHidden(e);
  114. }
  115. /**
  116. * Handles the componentAdded container event by invoking the
  117. * componentAdded methods on listener-a and listener-b.
  118. * @param e the component event
  119. */
  120. public void componentAdded(ContainerEvent e) {
  121. ((ContainerListener)a).componentAdded(e);
  122. ((ContainerListener)b).componentAdded(e);
  123. }
  124. /**
  125. * Handles the componentRemoved container event by invoking the
  126. * componentRemoved methods on listener-a and listener-b.
  127. * @param e the component event
  128. */
  129. public void componentRemoved(ContainerEvent e) {
  130. ((ContainerListener)a).componentRemoved(e);
  131. ((ContainerListener)b).componentRemoved(e);
  132. }
  133. /**
  134. * Handles the focusGained event by invoking the
  135. * focusGained methods on listener-a and listener-b.
  136. * @param e the focus event
  137. */
  138. public void focusGained(FocusEvent e) {
  139. ((FocusListener)a).focusGained(e);
  140. ((FocusListener)b).focusGained(e);
  141. }
  142. /**
  143. * Handles the focusLost event by invoking the
  144. * focusLost methods on listener-a and listener-b.
  145. * @param e the focus event
  146. */
  147. public void focusLost(FocusEvent e) {
  148. ((FocusListener)a).focusLost(e);
  149. ((FocusListener)b).focusLost(e);
  150. }
  151. /**
  152. * Handles the keyTyped event by invoking the
  153. * keyTyped methods on listener-a and listener-b.
  154. * @param e the key event
  155. */
  156. public void keyTyped(KeyEvent e) {
  157. ((KeyListener)a).keyTyped(e);
  158. ((KeyListener)b).keyTyped(e);
  159. }
  160. /**
  161. * Handles the keyPressed event by invoking the
  162. * keyPressed methods on listener-a and listener-b.
  163. * @param e the key event
  164. */
  165. public void keyPressed(KeyEvent e) {
  166. ((KeyListener)a).keyPressed(e);
  167. ((KeyListener)b).keyPressed(e);
  168. }
  169. /**
  170. * Handles the keyReleased event by invoking the
  171. * keyReleased methods on listener-a and listener-b.
  172. * @param e the key event
  173. */
  174. public void keyReleased(KeyEvent e) {
  175. ((KeyListener)a).keyReleased(e);
  176. ((KeyListener)b).keyReleased(e);
  177. }
  178. /**
  179. * Handles the mouseClicked event by invoking the
  180. * mouseClicked methods on listener-a and listener-b.
  181. * @param e the mouse event
  182. */
  183. public void mouseClicked(MouseEvent e) {
  184. ((MouseListener)a).mouseClicked(e);
  185. ((MouseListener)b).mouseClicked(e);
  186. }
  187. /**
  188. * Handles the mousePressed event by invoking the
  189. * mousePressed methods on listener-a and listener-b.
  190. * @param e the mouse event
  191. */
  192. public void mousePressed(MouseEvent e) {
  193. ((MouseListener)a).mousePressed(e);
  194. ((MouseListener)b).mousePressed(e);
  195. }
  196. /**
  197. * Handles the mouseReleased event by invoking the
  198. * mouseReleased methods on listener-a and listener-b.
  199. * @param e the mouse event
  200. */
  201. public void mouseReleased(MouseEvent e) {
  202. ((MouseListener)a).mouseReleased(e);
  203. ((MouseListener)b).mouseReleased(e);
  204. }
  205. /**
  206. * Handles the mouseEntered event by invoking the
  207. * mouseEntered methods on listener-a and listener-b.
  208. * @param e the mouse event
  209. */
  210. public void mouseEntered(MouseEvent e) {
  211. ((MouseListener)a).mouseEntered(e);
  212. ((MouseListener)b).mouseEntered(e);
  213. }
  214. /**
  215. * Handles the mouseExited event by invoking the
  216. * mouseExited methods on listener-a and listener-b.
  217. * @param e the mouse event
  218. */
  219. public void mouseExited(MouseEvent e) {
  220. ((MouseListener)a).mouseExited(e);
  221. ((MouseListener)b).mouseExited(e);
  222. }
  223. /**
  224. * Handles the mouseDragged event by invoking the
  225. * mouseDragged methods on listener-a and listener-b.
  226. * @param e the mouse event
  227. */
  228. public void mouseDragged(MouseEvent e) {
  229. ((MouseMotionListener)a).mouseDragged(e);
  230. ((MouseMotionListener)b).mouseDragged(e);
  231. }
  232. /**
  233. * Handles the mouseMoved event by invoking the
  234. * mouseMoved methods on listener-a and listener-b.
  235. * @param e the mouse event
  236. */
  237. public void mouseMoved(MouseEvent e) {
  238. ((MouseMotionListener)a).mouseMoved(e);
  239. ((MouseMotionListener)b).mouseMoved(e);
  240. }
  241. /**
  242. * Handles the windowOpened event by invoking the
  243. * windowOpened methods on listener-a and listener-b.
  244. * @param e the window event
  245. */
  246. public void windowOpened(WindowEvent e) {
  247. ((WindowListener)a).windowOpened(e);
  248. ((WindowListener)b).windowOpened(e);
  249. }
  250. /**
  251. * Handles the windowClosing event by invoking the
  252. * windowClosing methods on listener-a and listener-b.
  253. * @param e the window event
  254. */
  255. public void windowClosing(WindowEvent e) {
  256. ((WindowListener)a).windowClosing(e);
  257. ((WindowListener)b).windowClosing(e);
  258. }
  259. /**
  260. * Handles the windowClosed event by invoking the
  261. * windowClosed methods on listener-a and listener-b.
  262. * @param e the window event
  263. */
  264. public void windowClosed(WindowEvent e) {
  265. ((WindowListener)a).windowClosed(e);
  266. ((WindowListener)b).windowClosed(e);
  267. }
  268. /**
  269. * Handles the windowIconified event by invoking the
  270. * windowIconified methods on listener-a and listener-b.
  271. * @param e the window event
  272. */
  273. public void windowIconified(WindowEvent e) {
  274. ((WindowListener)a).windowIconified(e);
  275. ((WindowListener)b).windowIconified(e);
  276. }
  277. /**
  278. * Handles the windowDeiconfied event by invoking the
  279. * windowDeiconified methods on listener-a and listener-b.
  280. * @param e the window event
  281. */
  282. public void windowDeiconified(WindowEvent e) {
  283. ((WindowListener)a).windowDeiconified(e);
  284. ((WindowListener)b).windowDeiconified(e);
  285. }
  286. /**
  287. * Handles the windowActivated event by invoking the
  288. * windowActivated methods on listener-a and listener-b.
  289. * @param e the window event
  290. */
  291. public void windowActivated(WindowEvent e) {
  292. ((WindowListener)a).windowActivated(e);
  293. ((WindowListener)b).windowActivated(e);
  294. }
  295. /**
  296. * Handles the windowDeactivated event by invoking the
  297. * windowDeactivated methods on listener-a and listener-b.
  298. * @param e the window event
  299. */
  300. public void windowDeactivated(WindowEvent e) {
  301. ((WindowListener)a).windowDeactivated(e);
  302. ((WindowListener)b).windowDeactivated(e);
  303. }
  304. /**
  305. * Handles the actionPerformed event by invoking the
  306. * actionPerformed methods on listener-a and listener-b.
  307. * @param e the action event
  308. */
  309. public void actionPerformed(ActionEvent e) {
  310. ((ActionListener)a).actionPerformed(e);
  311. ((ActionListener)b).actionPerformed(e);
  312. }
  313. /**
  314. * Handles the itemStateChanged event by invoking the
  315. * itemStateChanged methods on listener-a and listener-b.
  316. * @param e the item event
  317. */
  318. public void itemStateChanged(ItemEvent e) {
  319. ((ItemListener)a).itemStateChanged(e);
  320. ((ItemListener)b).itemStateChanged(e);
  321. }
  322. /**
  323. * Handles the adjustmentValueChanged event by invoking the
  324. * adjustmentValueChanged methods on listener-a and listener-b.
  325. * @param e the adjustment event
  326. */
  327. public void adjustmentValueChanged(AdjustmentEvent e) {
  328. ((AdjustmentListener)a).adjustmentValueChanged(e);
  329. ((AdjustmentListener)b).adjustmentValueChanged(e);
  330. }
  331. public void textValueChanged(TextEvent e) {
  332. ((TextListener)a).textValueChanged(e);
  333. ((TextListener)b).textValueChanged(e);
  334. }
  335. /**
  336. * Handles the inputMethodTextChanged event by invoking the
  337. * inputMethodTextChanged methods on listener-a and listener-b.
  338. * @param e the item event
  339. */
  340. public void inputMethodTextChanged(InputMethodEvent e) {
  341. ((InputMethodListener)a).inputMethodTextChanged(e);
  342. ((InputMethodListener)b).inputMethodTextChanged(e);
  343. }
  344. /**
  345. * Handles the caretPositionChanged event by invoking the
  346. * caretPositionChanged methods on listener-a and listener-b.
  347. * @param e the item event
  348. */
  349. public void caretPositionChanged(InputMethodEvent e) {
  350. ((InputMethodListener)a).caretPositionChanged(e);
  351. ((InputMethodListener)b).caretPositionChanged(e);
  352. }
  353. /**
  354. * Adds component-listener-a with component-listener-b and
  355. * returns the resulting multicast listener.
  356. * @param a component-listener-a
  357. * @param b component-listener-b
  358. */
  359. public static ComponentListener add(ComponentListener a, ComponentListener b) {
  360. return (ComponentListener)addInternal(a, b);
  361. }
  362. /**
  363. * Adds container-listener-a with container-listener-b and
  364. * returns the resulting multicast listener.
  365. * @param a container-listener-a
  366. * @param b container-listener-b
  367. */
  368. public static ContainerListener add(ContainerListener a, ContainerListener b) {
  369. return (ContainerListener)addInternal(a, b);
  370. }
  371. /**
  372. * Adds focus-listener-a with focus-listener-b and
  373. * returns the resulting multicast listener.
  374. * @param a focus-listener-a
  375. * @param b focus-listener-b
  376. */
  377. public static FocusListener add(FocusListener a, FocusListener b) {
  378. return (FocusListener)addInternal(a, b);
  379. }
  380. /**
  381. * Adds key-listener-a with key-listener-b and
  382. * returns the resulting multicast listener.
  383. * @param a key-listener-a
  384. * @param b key-listener-b
  385. */
  386. public static KeyListener add(KeyListener a, KeyListener b) {
  387. return (KeyListener)addInternal(a, b);
  388. }
  389. /**
  390. * Adds mouse-listener-a with mouse-listener-b and
  391. * returns the resulting multicast listener.
  392. * @param a mouse-listener-a
  393. * @param b mouse-listener-b
  394. */
  395. public static MouseListener add(MouseListener a, MouseListener b) {
  396. return (MouseListener)addInternal(a, b);
  397. }
  398. /**
  399. * Adds mouse-motion-listener-a with mouse-motion-listener-b and
  400. * returns the resulting multicast listener.
  401. * @param a mouse-motion-listener-a
  402. * @param b mouse-motion-listener-b
  403. */
  404. public static MouseMotionListener add(MouseMotionListener a, MouseMotionListener b) {
  405. return (MouseMotionListener)addInternal(a, b);
  406. }
  407. /**
  408. * Adds window-listener-a with window-listener-b and
  409. * returns the resulting multicast listener.
  410. * @param a window-listener-a
  411. * @param b window-listener-b
  412. */
  413. public static WindowListener add(WindowListener a, WindowListener b) {
  414. return (WindowListener)addInternal(a, b);
  415. }
  416. /**
  417. * Adds action-listener-a with action-listener-b and
  418. * returns the resulting multicast listener.
  419. * @param a action-listener-a
  420. * @param b action-listener-b
  421. */
  422. public static ActionListener add(ActionListener a, ActionListener b) {
  423. return (ActionListener)addInternal(a, b);
  424. }
  425. /**
  426. * Adds item-listener-a with item-listener-b and
  427. * returns the resulting multicast listener.
  428. * @param a item-listener-a
  429. * @param b item-listener-b
  430. */
  431. public static ItemListener add(ItemListener a, ItemListener b) {
  432. return (ItemListener)addInternal(a, b);
  433. }
  434. /**
  435. * Adds adjustment-listener-a with adjustment-listener-b and
  436. * returns the resulting multicast listener.
  437. * @param a adjustment-listener-a
  438. * @param b adjustment-listener-b
  439. */
  440. public static AdjustmentListener add(AdjustmentListener a, AdjustmentListener b) {
  441. return (AdjustmentListener)addInternal(a, b);
  442. }
  443. public static TextListener add(TextListener a, TextListener b) {
  444. return (TextListener)addInternal(a, b);
  445. }
  446. /**
  447. * Adds input-method-listener-a with input-method-listener-b and
  448. * returns the resulting multicast listener.
  449. * @param a input-method-listener-a
  450. * @param b input-method-listener-b
  451. */
  452. public static InputMethodListener add(InputMethodListener a, InputMethodListener b) {
  453. return (InputMethodListener)addInternal(a, b);
  454. }
  455. /**
  456. * Removes the old component-listener from component-listener-l and
  457. * returns the resulting multicast listener.
  458. * @param l component-listener-l
  459. * @param oldl the component-listener being removed
  460. */
  461. public static ComponentListener remove(ComponentListener l, ComponentListener oldl) {
  462. return (ComponentListener) removeInternal(l, oldl);
  463. }
  464. /**
  465. * Removes the old container-listener from container-listener-l and
  466. * returns the resulting multicast listener.
  467. * @param l container-listener-l
  468. * @param oldl the container-listener being removed
  469. */
  470. public static ContainerListener remove(ContainerListener l, ContainerListener oldl) {
  471. return (ContainerListener) removeInternal(l, oldl);
  472. }
  473. /**
  474. * Removes the old focus-listener from focus-listener-l and
  475. * returns the resulting multicast listener.
  476. * @param l focus-listener-l
  477. * @param oldl the focus-listener being removed
  478. */
  479. public static FocusListener remove(FocusListener l, FocusListener oldl) {
  480. return (FocusListener) removeInternal(l, oldl);
  481. }
  482. /**
  483. * Removes the old key-listener from key-listener-l and
  484. * returns the resulting multicast listener.
  485. * @param l key-listener-l
  486. * @param oldl the key-listener being removed
  487. */
  488. public static KeyListener remove(KeyListener l, KeyListener oldl) {
  489. return (KeyListener) removeInternal(l, oldl);
  490. }
  491. /**
  492. * Removes the old mouse-listener from mouse-listener-l and
  493. * returns the resulting multicast listener.
  494. * @param l mouse-listener-l
  495. * @param oldl the mouse-listener being removed
  496. */
  497. public static MouseListener remove(MouseListener l, MouseListener oldl) {
  498. return (MouseListener) removeInternal(l, oldl);
  499. }
  500. /**
  501. * Removes the old mouse-motion-listener from mouse-motion-listener-l
  502. * and returns the resulting multicast listener.
  503. * @param l mouse-motion-listener-l
  504. * @param oldl the mouse-motion-listener being removed
  505. */
  506. public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) {
  507. return (MouseMotionListener) removeInternal(l, oldl);
  508. }
  509. /**
  510. * Removes the old window-listener from window-listener-l and
  511. * returns the resulting multicast listener.
  512. * @param l window-listener-l
  513. * @param oldl the window-listener being removed
  514. */
  515. public static WindowListener remove(WindowListener l, WindowListener oldl) {
  516. return (WindowListener) removeInternal(l, oldl);
  517. }
  518. /**
  519. * Removes the old action-listener from action-listener-l and
  520. * returns the resulting multicast listener.
  521. * @param l action-listener-l
  522. * @param oldl the action-listener being removed
  523. */
  524. public static ActionListener remove(ActionListener l, ActionListener oldl) {
  525. return (ActionListener) removeInternal(l, oldl);
  526. }
  527. /**
  528. * Removes the old item-listener from item-listener-l and
  529. * returns the resulting multicast listener.
  530. * @param l item-listener-l
  531. * @param oldl the item-listener being removed
  532. */
  533. public static ItemListener remove(ItemListener l, ItemListener oldl) {
  534. return (ItemListener) removeInternal(l, oldl);
  535. }
  536. /**
  537. * Removes the old adjustment-listener from adjustment-listener-l and
  538. * returns the resulting multicast listener.
  539. * @param l adjustment-listener-l
  540. * @param oldl the adjustment-listener being removed
  541. */
  542. public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) {
  543. return (AdjustmentListener) removeInternal(l, oldl);
  544. }
  545. public static TextListener remove(TextListener l, TextListener oldl) {
  546. return (TextListener) removeInternal(l, oldl);
  547. }
  548. /**
  549. * Removes the old input-method-listener from input-method-listener-l and
  550. * returns the resulting multicast listener.
  551. * @param l input-method-listener-l
  552. * @param oldl the input-method-listener being removed
  553. */
  554. public static InputMethodListener remove(InputMethodListener l, InputMethodListener oldl) {
  555. return (InputMethodListener) removeInternal(l, oldl);
  556. }
  557. /**
  558. * Returns the resulting multicast listener from adding listener-a
  559. * and listener-b together.
  560. * If listener-a is null, it returns listener-b;
  561. * If listener-b is null, it returns listener-a
  562. * If neither are null, then it creates and returns
  563. * a new AWTEventMulticaster instance which chains a with b.
  564. * @param a event listener-a
  565. * @param b event listener-b
  566. */
  567. protected static EventListener addInternal(EventListener a, EventListener b) {
  568. if (a == null) return b;
  569. if (b == null) return a;
  570. return new AWTEventMulticaster(a, b);
  571. }
  572. /**
  573. * Returns the resulting multicast listener after removing the
  574. * old listener from listener-l.
  575. * If listener-l equals the old listener OR listener-l is null,
  576. * returns null.
  577. * Else if listener-l is an instance of AWTEventMulticaster,
  578. * then it removes the old listener from it.
  579. * Else, returns listener l.
  580. * @param l the listener being removed from
  581. * @param oldl the listener being removed
  582. */
  583. protected static EventListener removeInternal(EventListener l, EventListener oldl) {
  584. if (l == oldl || l == null) {
  585. return null;
  586. } else if (l instanceof AWTEventMulticaster) {
  587. return ((AWTEventMulticaster)l).remove(oldl);
  588. } else {
  589. return l; // it's not here
  590. }
  591. }
  592. /* Serialization support.
  593. */
  594. protected void saveInternal(ObjectOutputStream s, String k) throws IOException {
  595. if (a instanceof AWTEventMulticaster) {
  596. ((AWTEventMulticaster)a).saveInternal(s, k);
  597. }
  598. else if (a instanceof Serializable) {
  599. s.writeObject(k);
  600. s.writeObject(a);
  601. }
  602. if (b instanceof AWTEventMulticaster) {
  603. ((AWTEventMulticaster)b).saveInternal(s, k);
  604. }
  605. else if (b instanceof Serializable) {
  606. s.writeObject(k);
  607. s.writeObject(b);
  608. }
  609. }
  610. protected static void save(ObjectOutputStream s, String k, EventListener l) throws IOException {
  611. if (l == null) {
  612. return;
  613. }
  614. else if (l instanceof AWTEventMulticaster) {
  615. ((AWTEventMulticaster)l).saveInternal(s, k);
  616. }
  617. else if (l instanceof Serializable) {
  618. s.writeObject(k);
  619. s.writeObject(l);
  620. }
  621. }
  622. }