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