Source for java.awt.Checkbox

   1: /* Checkbox.java -- An AWT checkbox widget
   2:    Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006
   3:    Free Software Foundation, Inc.
   4: 
   5: This file is part of GNU Classpath.
   6: 
   7: GNU Classpath is free software; you can redistribute it and/or modify
   8: it under the terms of the GNU General Public License as published by
   9: the Free Software Foundation; either version 2, or (at your option)
  10: any later version.
  11: 
  12: GNU Classpath is distributed in the hope that it will be useful, but
  13: WITHOUT ANY WARRANTY; without even the implied warranty of
  14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15: General Public License for more details.
  16: 
  17: You should have received a copy of the GNU General Public License
  18: along with GNU Classpath; see the file COPYING.  If not, write to the
  19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20: 02110-1301 USA.
  21: 
  22: Linking this library statically or dynamically with other modules is
  23: making a combined work based on this library.  Thus, the terms and
  24: conditions of the GNU General Public License cover the whole
  25: combination.
  26: 
  27: As a special exception, the copyright holders of this library give you
  28: permission to link this library with independent modules to produce an
  29: executable, regardless of the license terms of these independent
  30: modules, and to copy and distribute the resulting executable under
  31: terms of your choice, provided that you also meet, for each linked
  32: independent module, the terms and conditions of the license of that
  33: module.  An independent module is a module which is not derived from
  34: or based on this library.  If you modify this library, you may extend
  35: this exception to your version of the library, but you are not
  36: obligated to do so.  If you do not wish to do so, delete this
  37: exception statement from your version. */
  38: 
  39: 
  40: package java.awt;
  41: 
  42: import java.awt.event.ItemEvent;
  43: import java.awt.event.ItemListener;
  44: import java.awt.peer.CheckboxPeer;
  45: import java.io.Serializable;
  46: 
  47: import javax.accessibility.Accessible;
  48: import javax.accessibility.AccessibleAction;
  49: import javax.accessibility.AccessibleContext;
  50: import javax.accessibility.AccessibleRole;
  51: import javax.accessibility.AccessibleState;
  52: import javax.accessibility.AccessibleStateSet;
  53: import javax.accessibility.AccessibleValue;
  54: 
  55: /**
  56:  * This class implements a component which has an on/off state.  Two
  57:  * or more Checkboxes can be grouped by a CheckboxGroup.
  58:  *
  59:  * @author Aaron M. Renn (arenn@urbanophile.com)
  60:  * @author Tom Tromey (tromey@redhat.com)
  61:  */
  62: public class Checkbox extends Component
  63:   implements ItemSelectable, Accessible, Serializable
  64: {
  65: 
  66: // FIXME: Need readObject/writeObject for this.
  67: 
  68: /*
  69:  * Static Variables
  70:  */
  71: 
  72: // Serialization Constant
  73: private static final long serialVersionUID = 7270714317450821763L;
  74: 
  75: /*************************************************************************/
  76: 
  77: /*
  78:  * Instance Variables
  79:  */
  80: 
  81: /**
  82:   * @serial The checkbox group for this checkbox.
  83:   */
  84: private CheckboxGroup group;
  85: 
  86: /**
  87:   * @serial The label on this checkbox.
  88:   */
  89: private String label;
  90: 
  91: /**
  92:   * @serial The state of this checkbox.
  93:   * This is package-private to avoid an accessor method.
  94:   */
  95: boolean state;
  96: 
  97: // The list of listeners for this object.
  98: private transient ItemListener item_listeners;
  99: 
 100:   /*
 101:    * The number used to generate the name returned by getName.
 102:    */
 103:   private static transient long next_checkbox_number;
 104: 
 105: /**
 106:  * This class provides accessibility support for the
 107:  * checkbox.
 108:  *
 109:  * @author Jerry Quinn  (jlquinn@optonline.net)
 110:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 111:  */
 112: protected class AccessibleAWTCheckbox
 113:   extends AccessibleAWTComponent
 114:   implements ItemListener, AccessibleAction, AccessibleValue
 115: {
 116:   /**
 117:    * Serialization constant to match JDK 1.5
 118:    */
 119:   private static final long serialVersionUID = 7881579233144754107L;
 120: 
 121:   /**
 122:    * Default constructor which simply calls the
 123:    * super class for generic component accessibility
 124:    * handling.
 125:    */
 126:   public AccessibleAWTCheckbox()
 127:   {
 128:     super();
 129:   }
 130: 
 131:   /**
 132:    * Captures changes to the state of the checkbox and
 133:    * fires appropriate accessible property change events.
 134:    *
 135:    * @param event the event fired.
 136:    * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
 137:    */
 138:   public void itemStateChanged(ItemEvent event)
 139:   {
 140:     firePropertyChange(ACCESSIBLE_STATE_PROPERTY,
 141:                state ? null : AccessibleState.CHECKED,
 142:                        state ? AccessibleState.CHECKED : null);
 143:   }
 144:   
 145:   /**
 146:    * Returns an implementation of the <code>AccessibleAction</code>
 147:    * interface for this accessible object.  In this case, the
 148:    * current instance is simply returned (with a more appropriate
 149:    * type), as it also implements the accessible action as well as
 150:    * the context.
 151:    *
 152:    * @return the accessible action associated with this context.
 153:    * @see javax.accessibility.AccessibleAction
 154:    */
 155:   public AccessibleAction getAccessibleAction()
 156:   {
 157:     return this;
 158:   }
 159:   
 160:   /**
 161:    * Returns an implementation of the <code>AccessibleValue</code>
 162:    * interface for this accessible object.  In this case, the
 163:    * current instance is simply returned (with a more appropriate
 164:    * type), as it also implements the accessible value as well as
 165:    * the context.
 166:    *
 167:    * @return the accessible value associated with this context.
 168:    * @see javax.accessibility.AccessibleValue
 169:    */
 170:   public AccessibleValue getAccessibleValue()
 171:   {
 172:     return this;
 173:   }
 174:   
 175:   /* 
 176:    * The following methods are implemented in the JDK (up to
 177:    * 1.5) as stubs.  We do likewise here.
 178:    */
 179: 
 180:   /**
 181:    * Returns the number of actions associated with this accessible
 182:    * object.  This default implementation returns 0.
 183:    *
 184:    * @return the number of accessible actions available.
 185:    * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
 186:    */
 187:   public int getAccessibleActionCount()
 188:   {
 189:     // 1.4.1 and 1.5 do this
 190:     return 0;
 191:   }
 192: 
 193:   /**
 194:    * Returns a description of the action with the supplied id.
 195:    * This default implementation always returns null.
 196:    *
 197:    * @param i the id of the action whose description should be
 198:    *          retrieved.
 199:    * @return a <code>String</code> describing the action.
 200:    * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
 201:    */
 202:   public String getAccessibleActionDescription(int i)
 203:   {
 204:     // 1.5 does this
 205:     return null;
 206:   }
 207: 
 208:   /**
 209:    * Executes the action with the specified id.  This
 210:    * default implementation simply returns false.
 211:    *
 212:    * @param i the id of the action to perform.
 213:    * @return true if the action was performed.
 214:    * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
 215:    */
 216:   public boolean doAccessibleAction(int i)
 217:   {
 218:     // 1.5 does this
 219:     return false;
 220:   }
 221: 
 222:   /**
 223:    * Returns the current value of this accessible object.
 224:    * If no value has been set, null is returned.  This
 225:    * default implementation always returns null, regardless.
 226:    *
 227:    * @return the numeric value of this object, or null if
 228:    *         no value has been set.
 229:    * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
 230:    */
 231:   public Number getCurrentAccessibleValue()
 232:   {
 233:     // 1.5 does this
 234:     return null;
 235:   }
 236: 
 237:   /**
 238:    * Sets the current value of this accessible object
 239:    * to that supplied.  In this default implementation,
 240:    * the value is never set and the method always returns
 241:    * false.
 242:    *
 243:    * @param number the new accessible value.
 244:    * @return true if the value was set.
 245:    * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
 246:    */
 247:   public boolean setCurrentAccessibleValue(Number number)
 248:   {
 249:     // 1.5 does this
 250:     return false;
 251:   }
 252: 
 253:   /**
 254:    * Returns the minimum acceptable accessible value used
 255:    * by this object, or null if no minimum value exists.
 256:    * This default implementation always returns null.
 257:    *
 258:    * @return the minimum acceptable accessible value, or null
 259:    *         if there is no minimum.
 260:    * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
 261:    */
 262:   public Number getMinimumAccessibleValue()
 263:   {
 264:     return null;
 265:   }
 266: 
 267:   /**
 268:    * Returns the maximum acceptable accessible value used
 269:    * by this object, or null if no maximum value exists.
 270:    * This default implementation always returns null.
 271:    *
 272:    * @return the maximum acceptable accessible value, or null
 273:    *         if there is no maximum.
 274:    * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
 275:    */
 276:   public Number getMaximumAccessibleValue()
 277:   {
 278:     return null;
 279:   }
 280:   
 281:   /**
 282:    * Returns the role of this accessible object.
 283:    *
 284:    * @return the instance of <code>AccessibleRole</code>,
 285:    *         which describes this object.
 286:    * @see javax.accessibility.AccessibleRole
 287:    */
 288:   public AccessibleRole getAccessibleRole() 
 289:   {
 290:     return AccessibleRole.CHECK_BOX;
 291:   }
 292:   
 293:   /**
 294:    * Returns the state set of this accessible object.
 295:    *
 296:    * @return a set of <code>AccessibleState</code>s
 297:    *         which represent the current state of the
 298:    *         accessible object.
 299:    * @see javax.accessibility.AccessibleState
 300:    * @see javax.accessibility.AccessibleStateSet
 301:    */
 302:   public AccessibleStateSet getAccessibleStateSet()
 303:   {
 304:     AccessibleStateSet set = super.getAccessibleStateSet();
 305:     if (state)
 306:       set.add(AccessibleState.CHECKED);
 307:     return set;
 308:   }
 309: 
 310: }
 311: 
 312: /*************************************************************************/
 313: 
 314: /*
 315:  * Constructors
 316:  */
 317: 
 318: /**
 319:   * Initializes a new instance of <code>Checkbox</code> with no label,
 320:   * an initial state of off, and that is not part of any checkbox group.
 321:   */
 322: public 
 323: Checkbox()
 324: {
 325:   this("", false, null);
 326: }
 327: 
 328: /*************************************************************************/
 329: 
 330: /**
 331:   * Initializes a new instance of <code>Checkbox</code> with the specified
 332:   * label, an initial state of off, and that is not part of any checkbox
 333:   * group.
 334:   *
 335:   * @param label The label for this checkbox.
 336:   */
 337: public
 338: Checkbox(String label)
 339: {
 340:   this(label, false, null);
 341: }
 342: 
 343: /*************************************************************************/
 344: 
 345: /**
 346:   * Initializes a new instance of <code>Checkbox</code> with the specified
 347:   * label and initial state, and that is not part of any checkbox
 348:   * group.
 349:   *
 350:   * @param label The label for this checkbox.
 351:   * @param state The initial state of the checkbox, <code>true</code> for
 352:   * on, <code>false</code> for off.
 353:   */
 354: public
 355: Checkbox(String label, boolean state)
 356: {
 357:   this(label, state, null);
 358: }
 359: 
 360: /*************************************************************************/
 361: 
 362: /**
 363:   * Initializes a new instance of <code>Checkbox</code> with the specified
 364:   * label, initial state, and checkbox group.
 365:   *
 366:   * @param label The label for this checkbox.
 367:   * @param group The checkbox group for this box, or <code>null</code>
 368:   * if there is no checkbox group.
 369:   * @param state The initial state of the checkbox, <code>true</code> for
 370:   * on, <code>false</code> for off.
 371:   */
 372: public
 373: Checkbox(String label, CheckboxGroup group, boolean state)
 374: {
 375:   this(label, state, group);
 376: }
 377: 
 378: /*************************************************************************/
 379: 
 380: /**
 381:   * Initializes a new instance of <code>Checkbox</code> with the specified
 382:   * label, initial state, and checkbox group.
 383:   *
 384:   * @param label The label for this checkbox.
 385:   * @param state The initial state of the checkbox, <code>true</code> for
 386:   * on, <code>false</code> for off.
 387:   * @param group The checkbox group for this box, or <code>null</code>
 388:   * if there is no checkbox group.
 389:   */
 390: public
 391: Checkbox(String label, boolean state, CheckboxGroup group)
 392: {
 393:   this.label = label;
 394:   this.state = state;
 395:   this.group = group;
 396: 
 397:   if ( state && group != null )
 398:     {
 399:       group.setSelectedCheckbox(this);
 400:     }
 401: }
 402: 
 403: /*************************************************************************/
 404: 
 405: /*
 406:  * Instance Variables
 407:  */
 408: 
 409: /**
 410:   * Returns the label for this checkbox.
 411:   *
 412:   * @return The label for this checkbox.
 413:   */
 414: public String
 415: getLabel()
 416: {
 417:   return(label);
 418: }
 419: 
 420: /*************************************************************************/
 421: 
 422: /**
 423:   * Sets the label for this checkbox to the specified value.
 424:   *
 425:   * @param label The new checkbox label.
 426:   */
 427: public synchronized void
 428: setLabel(String label)
 429: {
 430:   this.label = label;
 431:   if (peer != null)
 432:     {
 433:       CheckboxPeer cp = (CheckboxPeer) peer;
 434:       cp.setLabel(label);
 435:     }
 436: }
 437: 
 438: /*************************************************************************/
 439: 
 440: /**
 441:   * Returns the state of this checkbox.
 442:   *
 443:   * @return The state of this checkbox, which will be <code>true</code> for
 444:   * on and <code>false</code> for off.
 445:   */
 446: public boolean
 447: getState()
 448: {
 449:   return(state);
 450: }
 451: 
 452: /*************************************************************************/
 453: 
 454: /**
 455:   * Sets the state of this checkbox to the specified value.
 456:   *
 457:   * @param state The new state of the checkbox, which will be <code>true</code>
 458:   * for on or <code>false</code> for off.
 459:   */
 460: public synchronized void
 461: setState(boolean state)
 462: {
 463:   if (this.state != state)
 464:     {
 465:       this.state = state;
 466:       if (peer != null)
 467:     {
 468:       CheckboxPeer cp = (CheckboxPeer) peer;
 469:       cp.setState (state);
 470:     }
 471:     }
 472: }
 473: 
 474: /*************************************************************************/
 475: 
 476: /**
 477:   * Returns an array of length one containing the checkbox label if this
 478:   * checkbox is selected.  Otherwise <code>null</code> is returned.
 479:   *
 480:   * @return The selection state of this checkbox.
 481:   */
 482: public Object[]
 483: getSelectedObjects()
 484: {
 485:   if (state == false)
 486:     return(null);
 487: 
 488:   Object[] objs = new Object[1];
 489:   objs[0] = label;
 490: 
 491:   return(objs);
 492: }
 493: 
 494: /*************************************************************************/
 495: 
 496: /**
 497:   * Returns the checkbox group this object is a member of, if any.
 498:   *
 499:   * @return This object's checkbox group, of <code>null</code> if it is
 500:   * not a member of any group.
 501:   */
 502: public CheckboxGroup
 503: getCheckboxGroup()
 504: {
 505:   return(group);
 506: }
 507: 
 508: /*************************************************************************/
 509: 
 510: /**
 511:   * Sets this object's checkbox group to the specified group.
 512:   *
 513:   * @param group The new checkbox group, or <code>null</code> to make this
 514:   * object part of no checkbox group.
 515:   */
 516: public synchronized void
 517: setCheckboxGroup(CheckboxGroup group)
 518: {
 519:   this.group = group;
 520:   if (peer != null)
 521:     {
 522:       CheckboxPeer cp = (CheckboxPeer) peer;
 523:       cp.setCheckboxGroup (group);
 524:     }
 525: }
 526: 
 527: /*************************************************************************/
 528: 
 529: /**
 530:   * Creates this object's native peer.
 531:   */
 532: public void
 533: addNotify()
 534: {
 535:   if (peer == null)
 536:     peer = getToolkit ().createCheckbox (this);
 537:   super.addNotify ();
 538: }
 539: 
 540:   public ItemListener[] getItemListeners ()
 541:   {
 542:     return (ItemListener[])
 543:       AWTEventMulticaster.getListeners (item_listeners, ItemListener.class);
 544:   }
 545: 
 546: /**
 547:   * Adds a new listeners to the list of registered listeners for this object.
 548:   *
 549:   * @param listener The new listener to add.
 550:   */
 551: public synchronized void
 552: addItemListener(ItemListener listener)
 553: {
 554:   item_listeners = AWTEventMulticaster.add(item_listeners, listener);
 555: }
 556: 
 557: /*************************************************************************/
 558: 
 559: /**
 560:   * Removes a listener from the list of registered listeners for this object.
 561:   *
 562:   * @param listener The listener to remove.
 563:   */
 564: public synchronized void
 565: removeItemListener(ItemListener listener)
 566: {
 567:   item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
 568: }
 569: 
 570: /*************************************************************************/
 571: 
 572: /**
 573:   * Processes this event by calling <code>processItemEvent()</code> if it
 574:   * is any instance of <code>ItemEvent</code>.  Otherwise it is passed to
 575:   * the superclass for processing.
 576:   *
 577:   * @param event The event to process.
 578:   */
 579: protected void
 580: processEvent(AWTEvent event)
 581: {
 582:   if (event instanceof ItemEvent)
 583:     processItemEvent((ItemEvent)event);
 584:   else
 585:     super.processEvent(event);
 586: }
 587: 
 588: /*************************************************************************/
 589: 
 590: /**
 591:   * Processes this event by dispatching it to any registered listeners.
 592:   *
 593:   * @param event The <code>ItemEvent</code> to process.
 594:   */
 595: protected void
 596: processItemEvent(ItemEvent event)
 597: {
 598:   if (item_listeners != null)
 599:     item_listeners.itemStateChanged(event);
 600: }
 601: 
 602: void
 603: dispatchEventImpl(AWTEvent e)
 604: {
 605:   if (e.id <= ItemEvent.ITEM_LAST
 606:       && e.id >= ItemEvent.ITEM_FIRST)
 607:     {
 608:       ItemEvent ie = (ItemEvent) e;
 609:       int itemState = ie.getStateChange();
 610:       setState(itemState == ItemEvent.SELECTED ? true : false);
 611:       if (item_listeners != null 
 612:       || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0)
 613:     processEvent(e);
 614:     }
 615:   else
 616:     super.dispatchEventImpl(e);
 617: }
 618: 
 619: /*************************************************************************/
 620: 
 621: /**
 622:   * Returns a debugging string for this object.
 623:   */
 624: protected String
 625: paramString()
 626: {
 627:   // Note: We cannot add the checkbox group information here because this
 628:   // would trigger infinite recursion when CheckboxGroup.toString() is
 629:   // called and the box is in its selected state.
 630:   return ("label=" + label + ",state=" + state + "," + super.paramString());
 631: }
 632: 
 633: /**
 634:  * Gets the AccessibleContext associated with this <code>Checkbox</code>.
 635:  * The context is created, if necessary.
 636:  *
 637:  * @return the associated context
 638:  */
 639: public AccessibleContext getAccessibleContext()
 640: {
 641:   /* Create the context if this is the first request */
 642:   if (accessibleContext == null)
 643:   {
 644:     AccessibleAWTCheckbox ac = new AccessibleAWTCheckbox();
 645:     accessibleContext = ac;
 646:     addItemListener(ac);
 647:   }
 648:   return accessibleContext;
 649: }
 650: 
 651:   /**
 652:    * Generate a unique name for this checkbox.
 653:    *
 654:    * @return A unique name for this checkbox.
 655:    */
 656:   String generateName()
 657:   {
 658:     return "checkbox" + getUniqueLong();
 659:   }
 660: 
 661:   private static synchronized long getUniqueLong()
 662:   {
 663:     return next_checkbox_number++;
 664:   }
 665: }