1. /*
  2. * @(#)CheckboxMenuItem.java 1.69 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.peer.CheckboxMenuItemPeer;
  9. import java.awt.event.*;
  10. import java.util.EventListener;
  11. import java.io.ObjectOutputStream;
  12. import java.io.ObjectInputStream;
  13. import java.io.IOException;
  14. import javax.accessibility.*;
  15. /**
  16. * This class represents a check box that can be included in a menu.
  17. * Selecting the check box in the menu changes its state from
  18. * "on" to "off" or from "off" to "on."
  19. * <p>
  20. * The following picture depicts a menu which contains an instance
  21. * of <code>CheckBoxMenuItem</code>:
  22. * <p>
  23. * <img src="doc-files/MenuBar-1.gif"
  24. * alt="Menu labeled Examples, containing items Basic, Simple, Check, and More Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
  25. * ALIGN=center HSPACE=10 VSPACE=7>
  26. * <p>
  27. * The item labeled <code>Check</code> shows a check box menu item
  28. * in its "off" state.
  29. * <p>
  30. * When a check box menu item is selected, AWT sends an item event to
  31. * the item. Since the event is an instance of <code>ItemEvent</code>,
  32. * the <code>processEvent</code> method examines the event and passes
  33. * it along to <code>processItemEvent</code>. The latter method redirects
  34. * the event to any <code>ItemListener</code> objects that have
  35. * registered an interest in item events generated by this menu item.
  36. *
  37. * @version 1.69, 05/05/04
  38. * @author Sami Shaio
  39. * @see java.awt.event.ItemEvent
  40. * @see java.awt.event.ItemListener
  41. * @since JDK1.0
  42. */
  43. public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Accessible {
  44. static {
  45. /* ensure that the necessary native libraries are loaded */
  46. Toolkit.loadLibraries();
  47. if (!GraphicsEnvironment.isHeadless()) {
  48. initIDs();
  49. }
  50. }
  51. /**
  52. * The state of a checkbox menu item
  53. * @serial
  54. * @see #getState()
  55. * @see #setState(boolean)
  56. */
  57. boolean state = false;
  58. transient ItemListener itemListener;
  59. private static final String base = "chkmenuitem";
  60. private static int nameCounter = 0;
  61. /*
  62. * JDK 1.1 serialVersionUID
  63. */
  64. private static final long serialVersionUID = 6190621106981774043L;
  65. /**
  66. * Create a check box menu item with an empty label.
  67. * The item's state is initially set to "off."
  68. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  69. * returns true
  70. * @see java.awt.GraphicsEnvironment#isHeadless
  71. * @since JDK1.1
  72. */
  73. public CheckboxMenuItem() throws HeadlessException {
  74. this("", false);
  75. }
  76. /**
  77. * Create a check box menu item with the specified label.
  78. * The item's state is initially set to "off."
  79. * @param label a string label for the check box menu item,
  80. * or <code>null</code> for an unlabeled menu item.
  81. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  82. * returns true
  83. * @see java.awt.GraphicsEnvironment#isHeadless
  84. */
  85. public CheckboxMenuItem(String label) throws HeadlessException {
  86. this(label, false);
  87. }
  88. /**
  89. * Create a check box menu item with the specified label and state.
  90. * @param label a string label for the check box menu item,
  91. * or <code>null</code> for an unlabeled menu item.
  92. * @param state the initial state of the menu item, where
  93. * <code>true</code> indicates "on" and
  94. * <code>false</code> indicates "off."
  95. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  96. * returns true
  97. * @see java.awt.GraphicsEnvironment#isHeadless
  98. * @since JDK1.1
  99. */
  100. public CheckboxMenuItem(String label, boolean state)
  101. throws HeadlessException {
  102. super(label);
  103. this.state = state;
  104. }
  105. /**
  106. * Construct a name for this MenuComponent. Called by getName() when
  107. * the name is null.
  108. */
  109. String constructComponentName() {
  110. synchronized (getClass()) {
  111. return base + nameCounter++;
  112. }
  113. }
  114. /**
  115. * Creates the peer of the checkbox item. This peer allows us to
  116. * change the look of the checkbox item without changing its
  117. * functionality.
  118. * Most applications do not call this method directly.
  119. * @see java.awt.Toolkit#createCheckboxMenuItem(java.awt.CheckboxMenuItem)
  120. * @see java.awt.Component#getToolkit()
  121. */
  122. public void addNotify() {
  123. synchronized (getTreeLock()) {
  124. if (peer == null)
  125. peer = Toolkit.getDefaultToolkit().createCheckboxMenuItem(this);
  126. super.addNotify();
  127. }
  128. }
  129. /**
  130. * Determines whether the state of this check box menu item
  131. * is "on" or "off."
  132. *
  133. * @return the state of this check box menu item, where
  134. * <code>true</code> indicates "on" and
  135. * <code>false</code> indicates "off"
  136. * @see #setState
  137. */
  138. public boolean getState() {
  139. return state;
  140. }
  141. /**
  142. * Sets this check box menu item to the specifed state.
  143. * The boolean value <code>true</code> indicates "on" while
  144. * <code>false</code> indicates "off."
  145. *
  146. * <p>Note that this method should be primarily used to
  147. * initialize the state of the check box menu item.
  148. * Programmatically setting the state of the check box
  149. * menu item will <i>not</i> trigger
  150. * an <code>ItemEvent</code>. The only way to trigger an
  151. * <code>ItemEvent</code> is by user interaction.
  152. *
  153. * @param b <code>true</code> if the check box
  154. * menu item is on, otherwise <code>false</code>
  155. * @see #getState
  156. */
  157. public synchronized void setState(boolean b) {
  158. state = b;
  159. CheckboxMenuItemPeer peer = (CheckboxMenuItemPeer)this.peer;
  160. if (peer != null) {
  161. peer.setState(b);
  162. }
  163. }
  164. /**
  165. * Returns the an array (length 1) containing the checkbox menu item
  166. * label or null if the checkbox is not selected.
  167. * @see ItemSelectable
  168. */
  169. public synchronized Object[] getSelectedObjects() {
  170. if (state) {
  171. Object[] items = new Object[1];
  172. items[0] = label;
  173. return items;
  174. }
  175. return null;
  176. }
  177. /**
  178. * Adds the specified item listener to receive item events from
  179. * this check box menu item. Item events are sent in response to user
  180. * actions, but not in response to calls to setState().
  181. * If l is null, no exception is thrown and no action is performed.
  182. *
  183. * @param l the item listener
  184. * @see #removeItemListener
  185. * @see #getItemListeners
  186. * @see #setState
  187. * @see java.awt.event.ItemEvent
  188. * @see java.awt.event.ItemListener
  189. * @since JDK1.1
  190. */
  191. public synchronized void addItemListener(ItemListener l) {
  192. if (l == null) {
  193. return;
  194. }
  195. itemListener = AWTEventMulticaster.add(itemListener, l);
  196. newEventsOnly = true;
  197. }
  198. /**
  199. * Removes the specified item listener so that it no longer receives
  200. * item events from this check box menu item.
  201. * If l is null, no exception is thrown and no action is performed.
  202. *
  203. * @param l the item listener
  204. * @see #addItemListener
  205. * @see #getItemListeners
  206. * @see java.awt.event.ItemEvent
  207. * @see java.awt.event.ItemListener
  208. * @since JDK1.1
  209. */
  210. public synchronized void removeItemListener(ItemListener l) {
  211. if (l == null) {
  212. return;
  213. }
  214. itemListener = AWTEventMulticaster.remove(itemListener, l);
  215. }
  216. /**
  217. * Returns an array of all the item listeners
  218. * registered on this checkbox menuitem.
  219. *
  220. * @return all of this checkbox menuitem's <code>ItemListener</code>s
  221. * or an empty array if no item
  222. * listeners are currently registered
  223. *
  224. * @see #addItemListener
  225. * @see #removeItemListener
  226. * @see java.awt.event.ItemEvent
  227. * @see java.awt.event.ItemListener
  228. * @since 1.4
  229. */
  230. public synchronized ItemListener[] getItemListeners() {
  231. return (ItemListener[])(getListeners(ItemListener.class));
  232. }
  233. /**
  234. * Returns an array of all the objects currently registered
  235. * as <code><em>Foo</em>Listener</code>s
  236. * upon this <code>CheckboxMenuItem</code>.
  237. * <code><em>Foo</em>Listener</code>s are registered using the
  238. * <code>add<em>Foo</em>Listener</code> method.
  239. *
  240. * <p>
  241. * You can specify the <code>listenerType</code> argument
  242. * with a class literal, such as
  243. * <code><em>Foo</em>Listener.class</code>.
  244. * For example, you can query a
  245. * <code>CheckboxMenuItem</code> <code>c</code>
  246. * for its item listeners with the following code:
  247. *
  248. * <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre>
  249. *
  250. * If no such listeners exist, this method returns an empty array.
  251. *
  252. * @param listenerType the type of listeners requested; this parameter
  253. * should specify an interface that descends from
  254. * <code>java.util.EventListener</code>
  255. * @return an array of all objects registered as
  256. * <code><em>Foo</em>Listener</code>s on this checkbox menuitem,
  257. * or an empty array if no such
  258. * listeners have been added
  259. * @exception ClassCastException if <code>listenerType</code>
  260. * doesn't specify a class or interface that implements
  261. * <code>java.util.EventListener</code>
  262. *
  263. * @see #getItemListeners
  264. * @since 1.3
  265. */
  266. public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
  267. EventListener l = null;
  268. if (listenerType == ItemListener.class) {
  269. l = itemListener;
  270. } else {
  271. return super.getListeners(listenerType);
  272. }
  273. return AWTEventMulticaster.getListeners(l, listenerType);
  274. }
  275. // REMIND: remove when filtering is done at lower level
  276. boolean eventEnabled(AWTEvent e) {
  277. if (e.id == ItemEvent.ITEM_STATE_CHANGED) {
  278. if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 ||
  279. itemListener != null) {
  280. return true;
  281. }
  282. return false;
  283. }
  284. return super.eventEnabled(e);
  285. }
  286. /**
  287. * Processes events on this check box menu item.
  288. * If the event is an instance of <code>ItemEvent</code>,
  289. * this method invokes the <code>processItemEvent</code> method.
  290. * If the event is not an item event,
  291. * it invokes <code>processEvent</code> on the superclass.
  292. * <p>
  293. * Check box menu items currently support only item events.
  294. * <p>Note that if the event parameter is <code>null</code>
  295. * the behavior is unspecified and may result in an
  296. * exception.
  297. *
  298. * @param e the event
  299. * @see java.awt.event.ItemEvent
  300. * @see #processItemEvent
  301. * @since JDK1.1
  302. */
  303. protected void processEvent(AWTEvent e) {
  304. if (e instanceof ItemEvent) {
  305. processItemEvent((ItemEvent)e);
  306. return;
  307. }
  308. super.processEvent(e);
  309. }
  310. /**
  311. * Processes item events occurring on this check box menu item by
  312. * dispatching them to any registered <code>ItemListener</code> objects.
  313. * <p>
  314. * This method is not called unless item events are
  315. * enabled for this menu item. Item events are enabled
  316. * when one of the following occurs:
  317. * <p><ul>
  318. * <li>An <code>ItemListener</code> object is registered
  319. * via <code>addItemListener</code>.
  320. * <li>Item events are enabled via <code>enableEvents</code>.
  321. * </ul>
  322. * <p>Note that if the event parameter is <code>null</code>
  323. * the behavior is unspecified and may result in an
  324. * exception.
  325. *
  326. * @param e the item event
  327. * @see java.awt.event.ItemEvent
  328. * @see java.awt.event.ItemListener
  329. * @see #addItemListener
  330. * @see java.awt.MenuItem#enableEvents
  331. * @since JDK1.1
  332. */
  333. protected void processItemEvent(ItemEvent e) {
  334. ItemListener listener = itemListener;
  335. if (listener != null) {
  336. listener.itemStateChanged(e);
  337. }
  338. }
  339. /*
  340. * Post an ItemEvent and toggle state.
  341. */
  342. void doMenuEvent(long when, int modifiers) {
  343. setState(!state);
  344. Toolkit.getEventQueue().postEvent(
  345. new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
  346. getLabel(),
  347. state ? ItemEvent.SELECTED :
  348. ItemEvent.DESELECTED));
  349. }
  350. /**
  351. * Returns a string representing the state of this
  352. * <code>CheckBoxMenuItem</code>. This
  353. * method is intended to be used only for debugging purposes, and the
  354. * content and format of the returned string may vary between
  355. * implementations. The returned string may be empty but may not be
  356. * <code>null</code>.
  357. *
  358. * @return the parameter string of this check box menu item
  359. */
  360. public String paramString() {
  361. return super.paramString() + ",state=" + state;
  362. }
  363. /* Serialization support.
  364. */
  365. /*
  366. * Serial Data Version
  367. * @serial
  368. */
  369. private int checkboxMenuItemSerializedDataVersion = 1;
  370. /**
  371. * Writes default serializable fields to stream. Writes
  372. * a list of serializable <code>ItemListeners</code>
  373. * as optional data. The non-serializable
  374. * <code>ItemListeners</code> are detected and
  375. * no attempt is made to serialize them.
  376. *
  377. * @param s the <code>ObjectOutputStream</code> to write
  378. * @serialData <code>null</code> terminated sequence of
  379. * 0 or more pairs; the pair consists of a <code>String</code>
  380. * and an <code>Object</code> the <code>String</code> indicates
  381. * the type of object and is one of the following:
  382. * <code>itemListenerK</code> indicating an
  383. * <code>ItemListener</code> object
  384. *
  385. * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
  386. * @see java.awt.Component#itemListenerK
  387. * @see #readObject(ObjectInputStream)
  388. */
  389. private void writeObject(ObjectOutputStream s)
  390. throws java.io.IOException
  391. {
  392. s.defaultWriteObject();
  393. AWTEventMulticaster.save(s, itemListenerK, itemListener);
  394. s.writeObject(null);
  395. }
  396. /*
  397. * Reads the <code>ObjectInputStream</code> and if it
  398. * isn't <code>null</code> adds a listener to receive
  399. * item events fired by the <code>Checkbox</code> menu item.
  400. * Unrecognized keys or values will be ignored.
  401. *
  402. * @param s the <code>ObjectInputStream</code> to read
  403. * @serial
  404. * @see removeActionListener()
  405. * @see addActionListener()
  406. * @see #writeObject
  407. */
  408. private void readObject(ObjectInputStream s)
  409. throws ClassNotFoundException, IOException
  410. {
  411. s.defaultReadObject();
  412. Object keyOrNull;
  413. while(null != (keyOrNull = s.readObject())) {
  414. String key = ((String)keyOrNull).intern();
  415. if (itemListenerK == key)
  416. addItemListener((ItemListener)(s.readObject()));
  417. else // skip value for unrecognized key
  418. s.readObject();
  419. }
  420. }
  421. /**
  422. * Initialize JNI field and method IDs
  423. */
  424. private static native void initIDs();
  425. /////////////////
  426. // Accessibility support
  427. ////////////////
  428. /**
  429. * Gets the AccessibleContext associated with this CheckboxMenuItem.
  430. * For checkbox menu items, the AccessibleContext takes the
  431. * form of an AccessibleAWTCheckboxMenuItem.
  432. * A new AccessibleAWTCheckboxMenuItem is created if necessary.
  433. *
  434. * @return an AccessibleAWTCheckboxMenuItem that serves as the
  435. * AccessibleContext of this CheckboxMenuItem
  436. */
  437. public AccessibleContext getAccessibleContext() {
  438. if (accessibleContext == null) {
  439. accessibleContext = new AccessibleAWTCheckboxMenuItem();
  440. }
  441. return accessibleContext;
  442. }
  443. /**
  444. * Inner class of CheckboxMenuItem used to provide default support for
  445. * accessibility. This class is not meant to be used directly by
  446. * application developers, but is instead meant only to be
  447. * subclassed by menu component developers.
  448. * <p>
  449. * This class implements accessibility support for the
  450. * <code>CheckboxMenuItem</code> class. It provides an implementation
  451. * of the Java Accessibility API appropriate to checkbox menu item
  452. * user-interface elements.
  453. */
  454. protected class AccessibleAWTCheckboxMenuItem extends AccessibleAWTMenuItem
  455. implements AccessibleAction, AccessibleValue
  456. {
  457. /*
  458. * JDK 1.3 serialVersionUID
  459. */
  460. private static final long serialVersionUID = -1122642964303476L;
  461. /**
  462. * Get the AccessibleAction associated with this object. In the
  463. * implementation of the Java Accessibility API for this class,
  464. * return this object, which is responsible for implementing the
  465. * AccessibleAction interface on behalf of itself.
  466. *
  467. * @return this object
  468. */
  469. public AccessibleAction getAccessibleAction() {
  470. return this;
  471. }
  472. /**
  473. * Get the AccessibleValue associated with this object. In the
  474. * implementation of the Java Accessibility API for this class,
  475. * return this object, which is responsible for implementing the
  476. * AccessibleValue interface on behalf of itself.
  477. *
  478. * @return this object
  479. */
  480. public AccessibleValue getAccessibleValue() {
  481. return this;
  482. }
  483. /**
  484. * Returns the number of Actions available in this object.
  485. * If there is more than one, the first one is the "default"
  486. * action.
  487. *
  488. * @return the number of Actions in this object
  489. */
  490. public int getAccessibleActionCount() {
  491. return 0; // To be fully implemented in a future release
  492. }
  493. /**
  494. * Return a description of the specified action of the object.
  495. *
  496. * @param i zero-based index of the actions
  497. */
  498. public String getAccessibleActionDescription(int i) {
  499. return null; // To be fully implemented in a future release
  500. }
  501. /**
  502. * Perform the specified Action on the object
  503. *
  504. * @param i zero-based index of actions
  505. * @return true if the action was performed; otherwise false.
  506. */
  507. public boolean doAccessibleAction(int i) {
  508. return false; // To be fully implemented in a future release
  509. }
  510. /**
  511. * Get the value of this object as a Number. If the value has not been
  512. * set, the return value will be null.
  513. *
  514. * @return value of the object
  515. * @see #setCurrentAccessibleValue
  516. */
  517. public Number getCurrentAccessibleValue() {
  518. return null; // To be fully implemented in a future release
  519. }
  520. /**
  521. * Set the value of this object as a Number.
  522. *
  523. * @return true if the value was set; otherwise false
  524. * @see #getCurrentAccessibleValue
  525. */
  526. public boolean setCurrentAccessibleValue(Number n) {
  527. return false; // To be fully implemented in a future release
  528. }
  529. /**
  530. * Get the minimum value of this object as a Number.
  531. *
  532. * @return Minimum value of the object; null if this object does not
  533. * have a minimum value
  534. * @see #getMaximumAccessibleValue
  535. */
  536. public Number getMinimumAccessibleValue() {
  537. return null; // To be fully implemented in a future release
  538. }
  539. /**
  540. * Get the maximum value of this object as a Number.
  541. *
  542. * @return Maximum value of the object; null if this object does not
  543. * have a maximum value
  544. * @see #getMinimumAccessibleValue
  545. */
  546. public Number getMaximumAccessibleValue() {
  547. return null; // To be fully implemented in a future release
  548. }
  549. /**
  550. * Get the role of this object.
  551. *
  552. * @return an instance of AccessibleRole describing the role of the
  553. * object
  554. */
  555. public AccessibleRole getAccessibleRole() {
  556. return AccessibleRole.CHECK_BOX;
  557. }
  558. } // class AccessibleAWTMenuItem
  559. }