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