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    */
AccessibleAWTCheckbox()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    */
itemStateChanged(ItemEvent event)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    */
getAccessibleAction()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    */
getAccessibleValue()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    */
getAccessibleActionCount()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    */
getAccessibleActionDescription(int i)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    */
doAccessibleAction(int i)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    */
getCurrentAccessibleValue()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    */
setCurrentAccessibleValue(Number number)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    */
getMinimumAccessibleValue()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    */
getMaximumAccessibleValue()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    */
getAccessibleRole()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    */
getAccessibleStateSet()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
Checkbox()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
Checkbox(String label)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
Checkbox(String label, boolean state)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
Checkbox(String label, CheckboxGroup group, boolean state)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
Checkbox(String label, boolean state, CheckboxGroup group)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
getLabel()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
setLabel(String label)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
getState()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
setState(boolean state)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[]
getSelectedObjects()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
getCheckboxGroup()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
setCheckboxGroup(CheckboxGroup group)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
addNotify()533 addNotify()
534 {
535   if (peer == null)
536     peer = getToolkit ().createCheckbox (this);
537   super.addNotify ();
538 }
539 
getItemListeners()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
addItemListener(ItemListener listener)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
removeItemListener(ItemListener listener)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
processEvent(AWTEvent event)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
processItemEvent(ItemEvent event)596 processItemEvent(ItemEvent event)
597 {
598   if (item_listeners != null)
599     item_listeners.itemStateChanged(event);
600 }
601 
602 void
dispatchEventImpl(AWTEvent e)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
paramString()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  */
getAccessibleContext()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    */
generateName()656   String generateName()
657   {
658     return "checkbox" + getUniqueLong();
659   }
660 
getUniqueLong()661   private static synchronized long getUniqueLong()
662   {
663     return next_checkbox_number++;
664   }
665 }
666