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</code>) or "off" (<code>false</code>) 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 graphic."
56 * style="float:center; margin: 7px 10px;">
57 * <p>
58 * The button labeled <code>one</code> is in the "on" state, and the
59 * other two are in the "off" state. In this example, which uses the
60 * <code>GridLayout</code> 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</code> 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</code>.
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;
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</code> for no label.
154 * @exception HeadlessException if
155 * <code>GraphicsEnvironment.isHeadless</code>
156 * returns <code>true</code>
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</code> for no label
170 * @param state the initial state of this check box
171 * @exception HeadlessException if
172 * <code>GraphicsEnvironment.isHeadless</code>
173 * returns <code>true</code>
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</code> 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</code> for no group.
189 * @exception HeadlessException if
190 * <code>GraphicsEnvironment.isHeadless</code>
191 * returns <code>true</code>
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</code> for no label.
212 * @param group a check box group for this check box,
213 * or <code>null</code> for no group.
214 * @param state the initial state of this check box.
215 * @exception HeadlessException if
216 * <code>GraphicsEnvironment.isHeadless</code>
217 * returns <code>true</code>
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</code> when the name is <code>null</code>.
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</code>
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</code> 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</code> indicates the "on" state,
294 * and <code>false</code> 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</code> indicates the "on" state,
306 * and <code>false</code> 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</code>. The only way to trigger an
312 * <code>ItemEvent</code> 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</code>
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</code> and the new
360 * group already has a check box selected, this check box's state
361 * is changed to <code>false</code>. If the state of this check
362 * box is <code>true</code> 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</code>.
365 *
366 * @param g the new check box group, or <code>null</code>
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;
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</code>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</code>.
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</code> 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</code> <code>c</code>
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</code>
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</code>
502 * doesn't specify a class or interface that implements
503 * <code>java.util.EventListener</code>
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</code>,
533 * this method invokes the <code>processItemEvent</code> method.
534 * Otherwise, it calls its superclass's <code>processEvent</code> method.
535 * <p>Note that if the event parameter is <code>null</code>
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</code> 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</code> object is registered
562 * via <code>addItemListener</code>.
563 * <li>Item events are enabled via <code>enableEvents</code>.
564 * </ul>
565 * <p>Note that if the event parameter is <code>null</code>
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</code>.
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</code>.
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</code>
614 * as optional data. The non-serializable
615 * <code>ItemListeners</code> are detected and
616 * no attempt is made to serialize them.
617 *
618 * @param s the <code>ObjectOutputStream</code> to write
619 * @serialData <code>null</code> terminated sequence of 0
620 * or more pairs; the pair consists of a <code>String</code>
621 * and an <code>Object</code>; the <code>String</code> indicates
622 * the type of object and is one of the following:
623 * <code>itemListenerK</code> indicating an
624 * <code>ItemListener</code> 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</code> and if it
641 * isn't <code>null</code> adds a listener to receive
642 * item events fired by the <code>Checkbox</code>.
643 * Unrecognized keys or values will be ignored.
644 *
645 * @param s the <code>ObjectInputStream</code> to read
646 * @exception HeadlessException if
647 * <code>GraphicsEnvironment.isHeadless</code> returns
648 * <code>true</code>
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
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</code> 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 /**
|
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 graphic."
56 * style="float:center; 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;
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;
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
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 /**
|