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