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