Frames | No Frames |
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: }