1 /*
   2  * Copyright (c) 1995, 2019, 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.CheckboxPeer;
  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  * A check box is a graphical component that can be in either an
  38  * "on" ({@code true}) or "off" ({@code false}) state.
  39  * Clicking on a check box changes its state from
  40  * "on" to "off," or from "off" to "on."
  41  * <p>
  42  * The following code example creates a set of check boxes in
  43  * a grid layout:
  44  *
  45  * <hr><blockquote><pre>
  46  * setLayout(new GridLayout(3, 1));
  47  * add(new Checkbox("one", null, true));
  48  * add(new Checkbox("two"));
  49  * add(new Checkbox("three"));
  50  * </pre></blockquote><hr>
  51  * <p>
  52  * This image depicts the check boxes and grid layout
  53  * created by this code example:
  54  * <p>
  55  * <img src="doc-files/Checkbox-1.gif" alt="The following context describes the
  56  * graphic." style="margin: 7px 10px;">
  57  * <p>
  58  * The button labeled {@code one} is in the "on" state, and the
  59  * other two are in the "off" state. In this example, which uses the
  60  * {@code GridLayout} class, the states of the three check
  61  * boxes are set independently.
  62  * <p>
  63  * Alternatively, several check boxes can be grouped together under
  64  * the control of a single object, using the
  65  * {@code CheckboxGroup} class.
  66  * In a check box group, at most one button can be in the "on"
  67  * state at any given time. Clicking on a check box to turn it on
  68  * forces any other check box in the same group that is on
  69  * into the "off" state.
  70  *
  71  * @author      Sami Shaio
  72  * @see         java.awt.GridLayout
  73  * @see         java.awt.CheckboxGroup
  74  * @since       1.0
  75  */
  76 public class Checkbox extends Component implements ItemSelectable, Accessible {
  77 
  78     static {
  79         /* ensure that the necessary native libraries are loaded */
  80         Toolkit.loadLibraries();
  81         if (!GraphicsEnvironment.isHeadless()) {
  82             initIDs();
  83         }
  84     }
  85 
  86     /**
  87      * The label of the Checkbox.
  88      * This field can be null.
  89      * @serial
  90      * @see #getLabel()
  91      * @see #setLabel(String)
  92      */
  93     String label;
  94 
  95     /**
  96      * The state of the {@code Checkbox}.
  97      * @serial
  98      * @see #getState()
  99      * @see #setState(boolean)
 100      */
 101     boolean state;
 102 
 103     /**
 104      * The check box group.
 105          * This field can be null indicating that the checkbox
 106          * is not a group checkbox.
 107          * @serial
 108      * @see #getCheckboxGroup()
 109      * @see #setCheckboxGroup(CheckboxGroup)
 110      */
 111     CheckboxGroup group;
 112 
 113     transient ItemListener itemListener;
 114 
 115     private static final String base = "checkbox";
 116     private static int nameCounter = 0;
 117 
 118     /*
 119      * JDK 1.1 serialVersionUID
 120      */
 121     private static final long serialVersionUID = 7270714317450821763L;
 122 
 123     /**
 124      * Helper function for setState and CheckboxGroup.setSelectedCheckbox
 125      * Should remain package-private.
 126      */
 127     void setStateInternal(boolean state) {
 128         this.state = state;
 129         CheckboxPeer peer = (CheckboxPeer)this.peer;
 130         if (peer != null) {
 131             peer.setState(state);
 132         }
 133     }
 134 
 135     /**
 136      * Creates a check box with an empty string for its label.
 137      * The state of this check box is set to "off," and it is not
 138      * part of any check box group.
 139      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
 140      * returns true
 141      * @see java.awt.GraphicsEnvironment#isHeadless
 142      */
 143     public Checkbox() throws HeadlessException {
 144         this("", false, null);
 145     }
 146 
 147     /**
 148      * Creates a check box with the specified label.  The state
 149      * of this check box is set to "off," and it is not part of
 150      * any check box group.
 151      *
 152      * @param     label   a string label for this check box,
 153      *                        or {@code null} for no label.
 154      * @exception HeadlessException if
 155      *      {@code GraphicsEnvironment.isHeadless}
 156      *      returns {@code true}
 157      * @see java.awt.GraphicsEnvironment#isHeadless
 158      */
 159     public Checkbox(String label) throws HeadlessException {
 160         this(label, false, null);
 161     }
 162 
 163     /**
 164      * Creates a check box with the specified label
 165      * and sets the specified state.
 166      * This check box is not part of any check box group.
 167      *
 168      * @param     label   a string label for this check box,
 169      *                        or {@code null} for no label
 170      * @param     state    the initial state of this check box
 171      * @exception HeadlessException if
 172      *     {@code GraphicsEnvironment.isHeadless}
 173      *     returns {@code true}
 174      * @see java.awt.GraphicsEnvironment#isHeadless
 175      */
 176     public Checkbox(String label, boolean state) throws HeadlessException {
 177         this(label, state, null);
 178     }
 179 
 180     /**
 181      * Constructs a Checkbox with the specified label, set to the
 182      * specified state, and in the specified check box group.
 183      *
 184      * @param     label   a string label for this check box,
 185      *                        or {@code null} for no label.
 186      * @param     state   the initial state of this check box.
 187      * @param     group   a check box group for this check box,
 188      *                           or {@code null} for no group.
 189      * @exception HeadlessException if
 190      *     {@code GraphicsEnvironment.isHeadless}
 191      *     returns {@code true}
 192      * @see java.awt.GraphicsEnvironment#isHeadless
 193      * @since     1.1
 194      */
 195     public Checkbox(String label, boolean state, CheckboxGroup group)
 196         throws HeadlessException {
 197         GraphicsEnvironment.checkHeadless();
 198         this.label = label;
 199         this.state = state;
 200         this.group = group;
 201         if (state && (group != null)) {
 202             group.setSelectedCheckbox(this);
 203         }
 204     }
 205 
 206     /**
 207      * Creates a check box with the specified label, in the specified
 208      * check box group, and set to the specified state.
 209      *
 210      * @param     label   a string label for this check box,
 211      *                        or {@code null} for no label.
 212      * @param     group   a check box group for this check box,
 213      *                           or {@code null} for no group.
 214      * @param     state   the initial state of this check box.
 215      * @exception HeadlessException if
 216      *    {@code GraphicsEnvironment.isHeadless}
 217      *    returns {@code true}
 218      * @see java.awt.GraphicsEnvironment#isHeadless
 219      * @since     1.1
 220      */
 221     public Checkbox(String label, CheckboxGroup group, boolean state)
 222         throws HeadlessException {
 223         this(label, state, group);
 224     }
 225 
 226     /**
 227      * Constructs a name for this component.  Called by
 228      * {@code getName} when the name is {@code null}.
 229      *
 230      * @return a name for this component
 231      */
 232     String constructComponentName() {
 233         synchronized (Checkbox.class) {
 234             return base + nameCounter++;
 235         }
 236     }
 237 
 238     /**
 239      * Creates the peer of the Checkbox. The peer allows you to change the
 240      * look of the Checkbox without changing its functionality.
 241      *
 242      * @see     java.awt.Component#getToolkit()
 243      */
 244     public void addNotify() {
 245         synchronized (getTreeLock()) {
 246             if (peer == null)
 247                 peer = getComponentFactory().createCheckbox(this);
 248             super.addNotify();
 249         }
 250     }
 251 
 252     /**
 253      * Gets the label of this check box.
 254      *
 255      * @return   the label of this check box, or {@code null}
 256      *                  if this check box has no label.
 257      * @see      #setLabel(String)
 258      */
 259     public String getLabel() {
 260         return label;
 261     }
 262 
 263     /**
 264      * Sets this check box's label to be the string argument.
 265      *
 266      * @param    label   a string to set as the new label, or
 267      *                        {@code null} for no label.
 268      * @see      #getLabel
 269      */
 270     public void setLabel(String label) {
 271         boolean testvalid = false;
 272 
 273         synchronized (this) {
 274             if (label != this.label && (this.label == null ||
 275                                         !this.label.equals(label))) {
 276                 this.label = label;
 277                 CheckboxPeer peer = (CheckboxPeer)this.peer;
 278                 if (peer != null) {
 279                     peer.setLabel(label);
 280                 }
 281                 testvalid = true;
 282             }
 283         }
 284 
 285         // This could change the preferred size of the Component.
 286         if (testvalid) {
 287             invalidateIfValid();
 288         }
 289     }
 290 
 291     /**
 292      * Determines whether this check box is in the "on" or "off" state.
 293      * The boolean value {@code true} indicates the "on" state,
 294      * and {@code false} indicates the "off" state.
 295      *
 296      * @return    the state of this check box, as a boolean value
 297      * @see       #setState
 298      */
 299     public boolean getState() {
 300         return state;
 301     }
 302 
 303     /**
 304      * Sets the state of this check box to the specified state.
 305      * The boolean value {@code true} indicates the "on" state,
 306      * and {@code false} indicates the "off" state.
 307      *
 308      * <p>Note that this method should be primarily used to
 309      * initialize the state of the checkbox.  Programmatically
 310      * setting the state of the checkbox will <i>not</i> trigger
 311      * an {@code ItemEvent}.  The only way to trigger an
 312      * {@code ItemEvent} is by user interaction.
 313      *
 314      * @param     state   the boolean state of the check box
 315      * @see       #getState
 316      */
 317     public void setState(boolean state) {
 318         /* Cannot hold check box lock when calling group.setSelectedCheckbox. */
 319         CheckboxGroup group = this.group;
 320         if (group != null) {
 321             if (state) {
 322                 group.setSelectedCheckbox(this);
 323             } else if (group.getSelectedCheckbox() == this) {
 324                 state = true;
 325             }
 326         }
 327         setStateInternal(state);
 328     }
 329 
 330     /**
 331      * Returns an array (length 1) containing the checkbox
 332      * label or null if the checkbox is not selected.
 333      * @see ItemSelectable
 334      */
 335     public Object[] getSelectedObjects() {
 336         if (state) {
 337             Object[] items = new Object[1];
 338             items[0] = label;
 339             return items;
 340         }
 341         return null;
 342     }
 343 
 344     /**
 345      * Determines this check box's group.
 346      * @return     this check box's group, or {@code null}
 347      *               if the check box is not part of a check box group.
 348      * @see        #setCheckboxGroup(CheckboxGroup)
 349      */
 350     public CheckboxGroup getCheckboxGroup() {
 351         return group;
 352     }
 353 
 354     /**
 355      * Sets this check box's group to the specified check box group.
 356      * If this check box is already in a different check box group,
 357      * it is first taken out of that group.
 358      * <p>
 359      * If the state of this check box is {@code true} and the new
 360      * group already has a check box selected, this check box's state
 361      * is changed to {@code false}.  If the state of this check
 362      * box is {@code true} and the new group has no check box
 363      * selected, this check box becomes the selected checkbox for
 364      * the new group and its state is {@code true}.
 365      *
 366      * @param     g   the new check box group, or {@code null}
 367      *                to remove this check box from any check box group
 368      * @see       #getCheckboxGroup
 369      */
 370     public void setCheckboxGroup(CheckboxGroup g) {
 371         CheckboxGroup oldGroup;
 372         boolean oldState;
 373 
 374         /* Do nothing if this check box has already belonged
 375          * to the check box group g.
 376          */
 377         if (this.group == g) {
 378             return;
 379         }
 380 
 381         synchronized (this) {
 382             oldGroup = this.group;
 383             oldState = getState();
 384 
 385             this.group = g;
 386             CheckboxPeer peer = (CheckboxPeer)this.peer;
 387             if (peer != null) {
 388                 peer.setCheckboxGroup(g);
 389             }
 390             if (this.group != null && getState()) {
 391                 if (this.group.getSelectedCheckbox() != null) {
 392                     setState(false);
 393                 } else {
 394                     this.group.setSelectedCheckbox(this);
 395                 }
 396             }
 397         }
 398 
 399         /* Locking check box below could cause deadlock with
 400          * CheckboxGroup's setSelectedCheckbox method.
 401          *
 402          * Fix for 4726853 by kdm@sparc.spb.su
 403          * Here we should check if this check box was selected
 404          * in the previous group and set selected check box to
 405          * null for that group if so.
 406          */
 407         if (oldGroup != null && oldState) {
 408             oldGroup.setSelectedCheckbox(null);
 409         }
 410     }
 411 
 412     /**
 413      * Adds the specified item listener to receive item events from
 414      * this check box.  Item events are sent to listeners in response
 415      * to user input, but not in response to calls to setState().
 416      * If l is null, no exception is thrown and no action is performed.
 417      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 418      * >AWT Threading Issues</a> for details on AWT's threading model.
 419      *
 420      * @param         l    the item listener
 421      * @see           #removeItemListener
 422      * @see           #getItemListeners
 423      * @see           #setState
 424      * @see           java.awt.event.ItemEvent
 425      * @see           java.awt.event.ItemListener
 426      * @since         1.1
 427      */
 428     public synchronized void addItemListener(ItemListener l) {
 429         if (l == null) {
 430             return;
 431         }
 432         itemListener = AWTEventMulticaster.add(itemListener, l);
 433         newEventsOnly = true;
 434     }
 435 
 436     /**
 437      * Removes the specified item listener so that the item listener
 438      * no longer receives item events from this check box.
 439      * If l is null, no exception is thrown and no action is performed.
 440      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 441      * >AWT Threading Issues</a> for details on AWT's threading model.
 442      *
 443      * @param         l    the item listener
 444      * @see           #addItemListener
 445      * @see           #getItemListeners
 446      * @see           java.awt.event.ItemEvent
 447      * @see           java.awt.event.ItemListener
 448      * @since         1.1
 449      */
 450     public synchronized void removeItemListener(ItemListener l) {
 451         if (l == null) {
 452             return;
 453         }
 454         itemListener = AWTEventMulticaster.remove(itemListener, l);
 455     }
 456 
 457     /**
 458      * Returns an array of all the item listeners
 459      * registered on this checkbox.
 460      *
 461      * @return all of this checkbox's {@code ItemListener}s
 462      *         or an empty array if no item
 463      *         listeners are currently registered
 464      *
 465      * @see           #addItemListener
 466      * @see           #removeItemListener
 467      * @see           java.awt.event.ItemEvent
 468      * @see           java.awt.event.ItemListener
 469      * @since 1.4
 470      */
 471     public synchronized ItemListener[] getItemListeners() {
 472         return getListeners(ItemListener.class);
 473     }
 474 
 475     /**
 476      * Returns an array of all the objects currently registered
 477      * as <code><em>Foo</em>Listener</code>s
 478      * upon this {@code Checkbox}.
 479      * <code><em>Foo</em>Listener</code>s are registered using the
 480      * <code>add<em>Foo</em>Listener</code> method.
 481      *
 482      * <p>
 483      * You can specify the {@code listenerType} argument
 484      * with a class literal, such as
 485      * <code><em>Foo</em>Listener.class</code>.
 486      * For example, you can query a
 487      * {@code Checkbox c}
 488      * for its item listeners with the following code:
 489      *
 490      * <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre>
 491      *
 492      * If no such listeners exist, this method returns an empty array.
 493      *
 494      * @param listenerType the type of listeners requested; this parameter
 495      *          should specify an interface that descends from
 496      *          {@code java.util.EventListener}
 497      * @return an array of all objects registered as
 498      *          <code><em>Foo</em>Listener</code>s on this checkbox,
 499      *          or an empty array if no such
 500      *          listeners have been added
 501      * @exception ClassCastException if {@code listenerType}
 502      *          doesn't specify a class or interface that implements
 503      *          {@code java.util.EventListener}
 504      *
 505      * @see #getItemListeners
 506      * @since 1.3
 507      */
 508     public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
 509         EventListener l = null;
 510         if  (listenerType == ItemListener.class) {
 511             l = itemListener;
 512         } else {
 513             return super.getListeners(listenerType);
 514         }
 515         return AWTEventMulticaster.getListeners(l, listenerType);
 516     }
 517 
 518     // REMIND: remove when filtering is done at lower level
 519     boolean eventEnabled(AWTEvent e) {
 520         if (e.id == ItemEvent.ITEM_STATE_CHANGED) {
 521             if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 ||
 522                 itemListener != null) {
 523                 return true;
 524             }
 525             return false;
 526         }
 527         return super.eventEnabled(e);
 528     }
 529 
 530     /**
 531      * Processes events on this check box.
 532      * If the event is an instance of {@code ItemEvent},
 533      * this method invokes the {@code processItemEvent} method.
 534      * Otherwise, it calls its superclass's {@code processEvent} method.
 535      * <p>Note that if the event parameter is {@code null}
 536      * the behavior is unspecified and may result in an
 537      * exception.
 538      *
 539      * @param         e the event
 540      * @see           java.awt.event.ItemEvent
 541      * @see           #processItemEvent
 542      * @since         1.1
 543      */
 544     protected void processEvent(AWTEvent e) {
 545         if (e instanceof ItemEvent) {
 546             processItemEvent((ItemEvent)e);
 547             return;
 548         }
 549         super.processEvent(e);
 550     }
 551 
 552     /**
 553      * Processes item events occurring on this check box by
 554      * dispatching them to any registered
 555      * {@code ItemListener} objects.
 556      * <p>
 557      * This method is not called unless item events are
 558      * enabled for this component. Item events are enabled
 559      * when one of the following occurs:
 560      * <ul>
 561      * <li>An {@code ItemListener} object is registered
 562      * via {@code addItemListener}.
 563      * <li>Item events are enabled via {@code enableEvents}.
 564      * </ul>
 565      * <p>Note that if the event parameter is {@code null}
 566      * the behavior is unspecified and may result in an
 567      * exception.
 568      *
 569      * @param       e the item event
 570      * @see         java.awt.event.ItemEvent
 571      * @see         java.awt.event.ItemListener
 572      * @see         #addItemListener
 573      * @see         java.awt.Component#enableEvents
 574      * @since       1.1
 575      */
 576     protected void processItemEvent(ItemEvent e) {
 577         ItemListener listener = itemListener;
 578         if (listener != null) {
 579             listener.itemStateChanged(e);
 580         }
 581     }
 582 
 583     /**
 584      * Returns a string representing the state of this {@code Checkbox}.
 585      * This method is intended to be used only for debugging purposes, and the
 586      * content and format of the returned string may vary between
 587      * implementations. The returned string may be empty but may not be
 588      * {@code null}.
 589      *
 590      * @return    the parameter string of this check box
 591      */
 592     protected String paramString() {
 593         String str = super.paramString();
 594         String label = this.label;
 595         if (label != null) {
 596             str += ",label=" + label;
 597         }
 598         return str + ",state=" + state;
 599     }
 600 
 601 
 602     /* Serialization support.
 603      */
 604 
 605     /*
 606      * Serialized data version
 607      * @serial
 608      */
 609     private int checkboxSerializedDataVersion = 1;
 610 
 611     /**
 612      * Writes default serializable fields to stream.  Writes
 613      * a list of serializable {@code ItemListeners}
 614      * as optional data.  The non-serializable
 615      * {@code ItemListeners} are detected and
 616      * no attempt is made to serialize them.
 617      *
 618      * @param s the {@code ObjectOutputStream} to write
 619      * @serialData {@code null} terminated sequence of 0
 620      *   or more pairs; the pair consists of a {@code String}
 621      *   and an {@code Object}; the {@code String} indicates
 622      *   the type of object and is one of the following:
 623      *   {@code itemListenerK} indicating an
 624      *     {@code ItemListener} object
 625      *
 626      * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
 627      * @see java.awt.Component#itemListenerK
 628      * @see #readObject(ObjectInputStream)
 629      */
 630     private void writeObject(ObjectOutputStream s)
 631       throws java.io.IOException
 632     {
 633       s.defaultWriteObject();
 634 
 635       AWTEventMulticaster.save(s, itemListenerK, itemListener);
 636       s.writeObject(null);
 637     }
 638 
 639     /**
 640      * Reads the {@code ObjectInputStream} and if it
 641      * isn't {@code null} adds a listener to receive
 642      * item events fired by the {@code Checkbox}.
 643      * Unrecognized keys or values will be ignored.
 644      *
 645      * @param s the {@code ObjectInputStream} to read
 646      * @exception HeadlessException if
 647      *   {@code GraphicsEnvironment.isHeadless} returns
 648      *   {@code true}
 649      * @serial
 650      * @see #removeItemListener(ItemListener)
 651      * @see #addItemListener(ItemListener)
 652      * @see java.awt.GraphicsEnvironment#isHeadless
 653      * @see #writeObject(ObjectOutputStream)
 654      */
 655     private void readObject(ObjectInputStream s)
 656       throws ClassNotFoundException, IOException, HeadlessException
 657     {
 658       GraphicsEnvironment.checkHeadless();
 659       s.defaultReadObject();
 660 
 661       Object keyOrNull;
 662       while(null != (keyOrNull = s.readObject())) {
 663         String key = ((String)keyOrNull).intern();
 664 
 665         if (itemListenerK == key)
 666           addItemListener((ItemListener)(s.readObject()));
 667 
 668         else // skip value for unrecognized key
 669           s.readObject();
 670       }
 671     }
 672 
 673     /**
 674      * Initialize JNI field and method ids
 675      */
 676     private static native void initIDs();
 677 
 678 
 679 /////////////////
 680 // Accessibility support
 681 ////////////////
 682 
 683 
 684     /**
 685      * Gets the AccessibleContext associated with this Checkbox.
 686      * For checkboxes, the AccessibleContext takes the form of an
 687      * AccessibleAWTCheckbox.
 688      * A new AccessibleAWTCheckbox is created if necessary.
 689      *
 690      * @return an AccessibleAWTCheckbox that serves as the
 691      *         AccessibleContext of this Checkbox
 692      * @since 1.3
 693      */
 694     public AccessibleContext getAccessibleContext() {
 695         if (accessibleContext == null) {
 696             accessibleContext = new AccessibleAWTCheckbox();
 697         }
 698         return accessibleContext;
 699     }
 700 
 701     /**
 702      * This class implements accessibility support for the
 703      * {@code Checkbox} class.  It provides an implementation of the
 704      * Java Accessibility API appropriate to checkbox user-interface elements.
 705      * @since 1.3
 706      */
 707     protected class AccessibleAWTCheckbox extends AccessibleAWTComponent
 708         implements ItemListener, AccessibleAction, AccessibleValue
 709     {
 710         /*
 711          * JDK 1.3 serialVersionUID
 712          */
 713         private static final long serialVersionUID = 7881579233144754107L;
 714 
 715         /**
 716          * Constructor for {@code AccessibleAWTCheckbox}
 717          */
 718         public AccessibleAWTCheckbox() {
 719             super();
 720             Checkbox.this.addItemListener(this);
 721         }
 722 
 723         /**
 724          * Fire accessible property change events when the state of the
 725          * toggle button changes.
 726          */
 727         public void itemStateChanged(ItemEvent e) {
 728             Checkbox cb = (Checkbox) e.getSource();
 729             if (Checkbox.this.accessibleContext != null) {
 730                 if (cb.getState()) {
 731                     Checkbox.this.accessibleContext.firePropertyChange(
 732                             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 733                             null, AccessibleState.CHECKED);
 734                 } else {
 735                     Checkbox.this.accessibleContext.firePropertyChange(
 736                             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 737                             AccessibleState.CHECKED, null);
 738                 }
 739             }
 740         }
 741 
 742         /**
 743          * Get the AccessibleAction associated with this object.  In the
 744          * implementation of the Java Accessibility API for this class,
 745          * return this object, which is responsible for implementing the
 746          * AccessibleAction interface on behalf of itself.
 747          *
 748          * @return this object
 749          */
 750         public AccessibleAction getAccessibleAction() {
 751             return this;
 752         }
 753 
 754         /**
 755          * Get the AccessibleValue associated with this object.  In the
 756          * implementation of the Java Accessibility API for this class,
 757          * return this object, which is responsible for implementing the
 758          * AccessibleValue interface on behalf of itself.
 759          *
 760          * @return this object
 761          */
 762         public AccessibleValue getAccessibleValue() {
 763             return this;
 764         }
 765 
 766         /**
 767          * Returns the number of Actions available in this object.
 768          * If there is more than one, the first one is the "default"
 769          * action.
 770          *
 771          * @return the number of Actions in this object
 772          */
 773         public int getAccessibleActionCount() {
 774             return 0;  //  To be fully implemented in a future release
 775         }
 776 
 777         /**
 778          * Return a description of the specified action of the object.
 779          *
 780          * @param i zero-based index of the actions
 781          */
 782         public String getAccessibleActionDescription(int i) {
 783             return null;  //  To be fully implemented in a future release
 784         }
 785 
 786         /**
 787          * Perform the specified Action on the object
 788          *
 789          * @param i zero-based index of actions
 790          * @return true if the action was performed; else false.
 791          */
 792         public boolean doAccessibleAction(int i) {
 793             return false;    //  To be fully implemented in a future release
 794         }
 795 
 796         /**
 797          * Get the value of this object as a Number.  If the value has not been
 798          * set, the return value will be null.
 799          *
 800          * @return value of the object
 801          * @see #setCurrentAccessibleValue
 802          */
 803         public Number getCurrentAccessibleValue() {
 804             return null;  //  To be fully implemented in a future release
 805         }
 806 
 807         /**
 808          * Set the value of this object as a Number.
 809          *
 810          * @return True if the value was set; else False
 811          * @see #getCurrentAccessibleValue
 812          */
 813         public boolean setCurrentAccessibleValue(Number n) {
 814             return false;  //  To be fully implemented in a future release
 815         }
 816 
 817         /**
 818          * Get the minimum value of this object as a Number.
 819          *
 820          * @return Minimum value of the object; null if this object does not
 821          * have a minimum value
 822          * @see #getMaximumAccessibleValue
 823          */
 824         public Number getMinimumAccessibleValue() {
 825             return null;  //  To be fully implemented in a future release
 826         }
 827 
 828         /**
 829          * Get the maximum value of this object as a Number.
 830          *
 831          * @return Maximum value of the object; null if this object does not
 832          * have a maximum value
 833          * @see #getMinimumAccessibleValue
 834          */
 835         public Number getMaximumAccessibleValue() {
 836             return null;  //  To be fully implemented in a future release
 837         }
 838 
 839         /**
 840          * Get the role of this object.
 841          *
 842          * @return an instance of AccessibleRole describing the role of
 843          * the object
 844          * @see AccessibleRole
 845          */
 846         public AccessibleRole getAccessibleRole() {
 847             return AccessibleRole.CHECK_BOX;
 848         }
 849 
 850         /**
 851          * Get the state set of this object.
 852          *
 853          * @return an instance of AccessibleState containing the current state
 854          * of the object
 855          * @see AccessibleState
 856          */
 857         public AccessibleStateSet getAccessibleStateSet() {
 858             AccessibleStateSet states = super.getAccessibleStateSet();
 859             if (getState()) {
 860                 states.add(AccessibleState.CHECKED);
 861             }
 862             return states;
 863         }
 864 
 865 
 866     } // inner class AccessibleAWTCheckbox
 867 
 868 }