001 /*
002 * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package java.awt;
026
027 import java.awt.peer.CheckboxMenuItemPeer;
028 import java.awt.event.*;
029 import java.util.EventListener;
030 import java.io.ObjectOutputStream;
031 import java.io.ObjectInputStream;
032 import java.io.IOException;
033 import javax.accessibility.*;
034
035 /**
036 * This class represents a check box that can be included in a menu.
037 * Selecting the check box in the menu changes its state from
038 * "on" to "off" or from "off" to "on."
039 * <p>
040 * The following picture depicts a menu which contains an instance
041 * of <code>CheckBoxMenuItem</code>:
042 * <p>
043 * <img src="doc-files/MenuBar-1.gif"
044 * alt="Menu labeled Examples, containing items Basic, Simple, Check, and More Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
045 * ALIGN=center HSPACE=10 VSPACE=7>
046 * <p>
047 * The item labeled <code>Check</code> shows a check box menu item
048 * in its "off" state.
049 * <p>
050 * When a check box menu item is selected, AWT sends an item event to
051 * the item. Since the event is an instance of <code>ItemEvent</code>,
052 * the <code>processEvent</code> method examines the event and passes
053 * it along to <code>processItemEvent</code>. The latter method redirects
054 * the event to any <code>ItemListener</code> objects that have
055 * registered an interest in item events generated by this menu item.
056 *
057 * @version 1.79, 05/05/07
058 * @author Sami Shaio
059 * @see java.awt.event.ItemEvent
060 * @see java.awt.event.ItemListener
061 * @since JDK1.0
062 */
063 public class CheckboxMenuItem extends MenuItem implements
064 ItemSelectable, Accessible {
065
066 static {
067 /* ensure that the necessary native libraries are loaded */
068 Toolkit.loadLibraries();
069 if (!GraphicsEnvironment.isHeadless()) {
070 initIDs();
071 }
072 }
073
074 /**
075 * The state of a checkbox menu item
076 * @serial
077 * @see #getState()
078 * @see #setState(boolean)
079 */
080 boolean state = false;
081
082 transient ItemListener itemListener;
083
084 private static final String base = "chkmenuitem";
085 private static int nameCounter = 0;
086
087 /*
088 * JDK 1.1 serialVersionUID
089 */
090 private static final long serialVersionUID = 6190621106981774043L;
091
092 /**
093 * Create a check box menu item with an empty label.
094 * The item's state is initially set to "off."
095 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
096 * returns true
097 * @see java.awt.GraphicsEnvironment#isHeadless
098 * @since JDK1.1
099 */
100 public CheckboxMenuItem() throws HeadlessException {
101 this ("", false);
102 }
103
104 /**
105 * Create a check box menu item with the specified label.
106 * The item's state is initially set to "off."
107
108 * @param label a string label for the check box menu item,
109 * or <code>null</code> for an unlabeled menu item.
110 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
111 * returns true
112 * @see java.awt.GraphicsEnvironment#isHeadless
113 */
114 public CheckboxMenuItem(String label) throws HeadlessException {
115 this (label, false);
116 }
117
118 /**
119 * Create a check box menu item with the specified label and state.
120 * @param label a string label for the check box menu item,
121 * or <code>null</code> for an unlabeled menu item.
122 * @param state the initial state of the menu item, where
123 * <code>true</code> indicates "on" and
124 * <code>false</code> indicates "off."
125 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
126 * returns true
127 * @see java.awt.GraphicsEnvironment#isHeadless
128 * @since JDK1.1
129 */
130 public CheckboxMenuItem(String label, boolean state)
131 throws HeadlessException {
132 super (label);
133 this .state = state;
134 }
135
136 /**
137 * Construct a name for this MenuComponent. Called by getName() when
138 * the name is null.
139 */
140 String constructComponentName() {
141 synchronized (CheckboxMenuItem.class) {
142 return base + nameCounter++;
143 }
144 }
145
146 /**
147 * Creates the peer of the checkbox item. This peer allows us to
148 * change the look of the checkbox item without changing its
149 * functionality.
150 * Most applications do not call this method directly.
151 * @see java.awt.Toolkit#createCheckboxMenuItem(java.awt.CheckboxMenuItem)
152 * @see java.awt.Component#getToolkit()
153 */
154 public void addNotify() {
155 synchronized (getTreeLock()) {
156 if (peer == null)
157 peer = Toolkit.getDefaultToolkit()
158 .createCheckboxMenuItem(this );
159 super .addNotify();
160 }
161 }
162
163 /**
164 * Determines whether the state of this check box menu item
165 * is "on" or "off."
166 *
167 * @return the state of this check box menu item, where
168 * <code>true</code> indicates "on" and
169 * <code>false</code> indicates "off"
170 * @see #setState
171 */
172 public boolean getState() {
173 return state;
174 }
175
176 /**
177 * Sets this check box menu item to the specifed state.
178 * The boolean value <code>true</code> indicates "on" while
179 * <code>false</code> indicates "off."
180 *
181 * <p>Note that this method should be primarily used to
182 * initialize the state of the check box menu item.
183 * Programmatically setting the state of the check box
184 * menu item will <i>not</i> trigger
185 * an <code>ItemEvent</code>. The only way to trigger an
186 * <code>ItemEvent</code> is by user interaction.
187 *
188 * @param b <code>true</code> if the check box
189 * menu item is on, otherwise <code>false</code>
190 * @see #getState
191 */
192 public synchronized void setState(boolean b) {
193 state = b;
194 CheckboxMenuItemPeer peer = (CheckboxMenuItemPeer) this .peer;
195 if (peer != null) {
196 peer.setState(b);
197 }
198 }
199
200 /**
201 * Returns the an array (length 1) containing the checkbox menu item
202 * label or null if the checkbox is not selected.
203 * @see ItemSelectable
204 */
205 public synchronized Object[] getSelectedObjects() {
206 if (state) {
207 Object[] items = new Object[1];
208 items[0] = label;
209 return items;
210 }
211 return null;
212 }
213
214 /**
215 * Adds the specified item listener to receive item events from
216 * this check box menu item. Item events are sent in response to user
217 * actions, but not in response to calls to setState().
218 * If l is null, no exception is thrown and no action is performed.
219 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
220 * >AWT Threading Issues</a> for details on AWT's threading model.
221 *
222 * @param l the item listener
223 * @see #removeItemListener
224 * @see #getItemListeners
225 * @see #setState
226 * @see java.awt.event.ItemEvent
227 * @see java.awt.event.ItemListener
228 * @since JDK1.1
229 */
230 public synchronized void addItemListener(ItemListener l) {
231 if (l == null) {
232 return;
233 }
234 itemListener = AWTEventMulticaster.add(itemListener, l);
235 newEventsOnly = true;
236 }
237
238 /**
239 * Removes the specified item listener so that it no longer receives
240 * item events from this check box menu item.
241 * If l is null, no exception is thrown and no action is performed.
242 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
243 * >AWT Threading Issues</a> for details on AWT's threading model.
244 *
245 * @param l the item listener
246 * @see #addItemListener
247 * @see #getItemListeners
248 * @see java.awt.event.ItemEvent
249 * @see java.awt.event.ItemListener
250 * @since JDK1.1
251 */
252 public synchronized void removeItemListener(ItemListener l) {
253 if (l == null) {
254 return;
255 }
256 itemListener = AWTEventMulticaster.remove(itemListener, l);
257 }
258
259 /**
260 * Returns an array of all the item listeners
261 * registered on this checkbox menuitem.
262 *
263 * @return all of this checkbox menuitem's <code>ItemListener</code>s
264 * or an empty array if no item
265 * listeners are currently registered
266 *
267 * @see #addItemListener
268 * @see #removeItemListener
269 * @see java.awt.event.ItemEvent
270 * @see java.awt.event.ItemListener
271 * @since 1.4
272 */
273 public synchronized ItemListener[] getItemListeners() {
274 return (ItemListener[]) (getListeners(ItemListener.class));
275 }
276
277 /**
278 * Returns an array of all the objects currently registered
279 * as <code><em>Foo</em>Listener</code>s
280 * upon this <code>CheckboxMenuItem</code>.
281 * <code><em>Foo</em>Listener</code>s are registered using the
282 * <code>add<em>Foo</em>Listener</code> method.
283 *
284 * <p>
285 * You can specify the <code>listenerType</code> argument
286 * with a class literal, such as
287 * <code><em>Foo</em>Listener.class</code>.
288 * For example, you can query a
289 * <code>CheckboxMenuItem</code> <code>c</code>
290 * for its item listeners with the following code:
291 *
292 * <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre>
293 *
294 * If no such listeners exist, this method returns an empty array.
295 *
296 * @param listenerType the type of listeners requested; this parameter
297 * should specify an interface that descends from
298 * <code>java.util.EventListener</code>
299 * @return an array of all objects registered as
300 * <code><em>Foo</em>Listener</code>s on this checkbox menuitem,
301 * or an empty array if no such
302 * listeners have been added
303 * @exception ClassCastException if <code>listenerType</code>
304 * doesn't specify a class or interface that implements
305 * <code>java.util.EventListener</code>
306 *
307 * @see #getItemListeners
308 * @since 1.3
309 */
310 public <T extends EventListener> T[] getListeners(
311 Class<T> listenerType) {
312 EventListener l = null;
313 if (listenerType == ItemListener.class) {
314 l = itemListener;
315 } else {
316 return super .getListeners(listenerType);
317 }
318 return AWTEventMulticaster.getListeners(l, listenerType);
319 }
320
321 // REMIND: remove when filtering is done at lower level
322 boolean eventEnabled(AWTEvent e) {
323 if (e.id == ItemEvent.ITEM_STATE_CHANGED) {
324 if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0
325 || itemListener != null) {
326 return true;
327 }
328 return false;
329 }
330 return super .eventEnabled(e);
331 }
332
333 /**
334 * Processes events on this check box menu item.
335 * If the event is an instance of <code>ItemEvent</code>,
336 * this method invokes the <code>processItemEvent</code> method.
337 * If the event is not an item event,
338 * it invokes <code>processEvent</code> on the superclass.
339 * <p>
340 * Check box menu items currently support only item events.
341 * <p>Note that if the event parameter is <code>null</code>
342 * the behavior is unspecified and may result in an
343 * exception.
344 *
345 * @param e the event
346 * @see java.awt.event.ItemEvent
347 * @see #processItemEvent
348 * @since JDK1.1
349 */
350 protected void processEvent(AWTEvent e) {
351 if (e instanceof ItemEvent) {
352 processItemEvent((ItemEvent) e);
353 return;
354 }
355 super .processEvent(e);
356 }
357
358 /**
359 * Processes item events occurring on this check box menu item by
360 * dispatching them to any registered <code>ItemListener</code> objects.
361 * <p>
362 * This method is not called unless item events are
363 * enabled for this menu item. Item events are enabled
364 * when one of the following occurs:
365 * <p><ul>
366 * <li>An <code>ItemListener</code> object is registered
367 * via <code>addItemListener</code>.
368 * <li>Item events are enabled via <code>enableEvents</code>.
369 * </ul>
370 * <p>Note that if the event parameter is <code>null</code>
371 * the behavior is unspecified and may result in an
372 * exception.
373 *
374 * @param e the item event
375 * @see java.awt.event.ItemEvent
376 * @see java.awt.event.ItemListener
377 * @see #addItemListener
378 * @see java.awt.MenuItem#enableEvents
379 * @since JDK1.1
380 */
381 protected void processItemEvent(ItemEvent e) {
382 ItemListener listener = itemListener;
383 if (listener != null) {
384 listener.itemStateChanged(e);
385 }
386 }
387
388 /*
389 * Post an ItemEvent and toggle state.
390 */
391 void doMenuEvent(long when, int modifiers) {
392 setState(!state);
393 Toolkit.getEventQueue().postEvent(
394 new ItemEvent(this , ItemEvent.ITEM_STATE_CHANGED,
395 getLabel(), state ? ItemEvent.SELECTED
396 : ItemEvent.DESELECTED));
397 }
398
399 /**
400 * Returns a string representing the state of this
401 * <code>CheckBoxMenuItem</code>. This
402 * method is intended to be used only for debugging purposes, and the
403 * content and format of the returned string may vary between
404 * implementations. The returned string may be empty but may not be
405 * <code>null</code>.
406 *
407 * @return the parameter string of this check box menu item
408 */
409 public String paramString() {
410 return super .paramString() + ",state=" + state;
411 }
412
413 /* Serialization support.
414 */
415
416 /*
417 * Serial Data Version
418 * @serial
419 */
420 private int checkboxMenuItemSerializedDataVersion = 1;
421
422 /**
423 * Writes default serializable fields to stream. Writes
424 * a list of serializable <code>ItemListeners</code>
425 * as optional data. The non-serializable
426 * <code>ItemListeners</code> are detected and
427 * no attempt is made to serialize them.
428 *
429 * @param s the <code>ObjectOutputStream</code> to write
430 * @serialData <code>null</code> terminated sequence of
431 * 0 or more pairs; the pair consists of a <code>String</code>
432 * and an <code>Object</code>; the <code>String</code> indicates
433 * the type of object and is one of the following:
434 * <code>itemListenerK</code> indicating an
435 * <code>ItemListener</code> object
436 *
437 * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
438 * @see java.awt.Component#itemListenerK
439 * @see #readObject(ObjectInputStream)
440 */
441 private void writeObject(ObjectOutputStream s)
442 throws java.io.IOException {
443 s.defaultWriteObject();
444
445 AWTEventMulticaster.save(s, itemListenerK, itemListener);
446 s.writeObject(null);
447 }
448
449 /*
450 * Reads the <code>ObjectInputStream</code> and if it
451 * isn't <code>null</code> adds a listener to receive
452 * item events fired by the <code>Checkbox</code> menu item.
453 * Unrecognized keys or values will be ignored.
454 *
455 * @param s the <code>ObjectInputStream</code> to read
456 * @serial
457 * @see removeActionListener()
458 * @see addActionListener()
459 * @see #writeObject
460 */
461 private void readObject(ObjectInputStream s)
462 throws ClassNotFoundException, IOException {
463 s.defaultReadObject();
464
465 Object keyOrNull;
466 while (null != (keyOrNull = s.readObject())) {
467 String key = ((String) keyOrNull).intern();
468
469 if (itemListenerK == key)
470 addItemListener((ItemListener) (s.readObject()));
471
472 else
473 // skip value for unrecognized key
474 s.readObject();
475 }
476 }
477
478 /**
479 * Initialize JNI field and method IDs
480 */
481 private static native void initIDs();
482
483 /////////////////
484 // Accessibility support
485 ////////////////
486
487 /**
488 * Gets the AccessibleContext associated with this CheckboxMenuItem.
489 * For checkbox menu items, the AccessibleContext takes the
490 * form of an AccessibleAWTCheckboxMenuItem.
491 * A new AccessibleAWTCheckboxMenuItem is created if necessary.
492 *
493 * @return an AccessibleAWTCheckboxMenuItem that serves as the
494 * AccessibleContext of this CheckboxMenuItem
495 * @since 1.3
496 */
497 public AccessibleContext getAccessibleContext() {
498 if (accessibleContext == null) {
499 accessibleContext = new AccessibleAWTCheckboxMenuItem();
500 }
501 return accessibleContext;
502 }
503
504 /**
505 * Inner class of CheckboxMenuItem used to provide default support for
506 * accessibility. This class is not meant to be used directly by
507 * application developers, but is instead meant only to be
508 * subclassed by menu component developers.
509 * <p>
510 * This class implements accessibility support for the
511 * <code>CheckboxMenuItem</code> class. It provides an implementation
512 * of the Java Accessibility API appropriate to checkbox menu item
513 * user-interface elements.
514 * @since 1.3
515 */
516 protected class AccessibleAWTCheckboxMenuItem extends
517 AccessibleAWTMenuItem implements AccessibleAction,
518 AccessibleValue {
519 /*
520 * JDK 1.3 serialVersionUID
521 */
522 private static final long serialVersionUID = -1122642964303476L;
523
524 /**
525 * Get the AccessibleAction associated with this object. In the
526 * implementation of the Java Accessibility API for this class,
527 * return this object, which is responsible for implementing the
528 * AccessibleAction interface on behalf of itself.
529 *
530 * @return this object
531 */
532 public AccessibleAction getAccessibleAction() {
533 return this ;
534 }
535
536 /**
537 * Get the AccessibleValue associated with this object. In the
538 * implementation of the Java Accessibility API for this class,
539 * return this object, which is responsible for implementing the
540 * AccessibleValue interface on behalf of itself.
541 *
542 * @return this object
543 */
544 public AccessibleValue getAccessibleValue() {
545 return this ;
546 }
547
548 /**
549 * Returns the number of Actions available in this object.
550 * If there is more than one, the first one is the "default"
551 * action.
552 *
553 * @return the number of Actions in this object
554 */
555 public int getAccessibleActionCount() {
556 return 0; // To be fully implemented in a future release
557 }
558
559 /**
560 * Return a description of the specified action of the object.
561 *
562 * @param i zero-based index of the actions
563 */
564 public String getAccessibleActionDescription(int i) {
565 return null; // To be fully implemented in a future release
566 }
567
568 /**
569 * Perform the specified Action on the object
570 *
571 * @param i zero-based index of actions
572 * @return true if the action was performed; otherwise false.
573 */
574 public boolean doAccessibleAction(int i) {
575 return false; // To be fully implemented in a future release
576 }
577
578 /**
579 * Get the value of this object as a Number. If the value has not been
580 * set, the return value will be null.
581 *
582 * @return value of the object
583 * @see #setCurrentAccessibleValue
584 */
585 public Number getCurrentAccessibleValue() {
586 return null; // To be fully implemented in a future release
587 }
588
589 /**
590 * Set the value of this object as a Number.
591 *
592 * @return true if the value was set; otherwise false
593 * @see #getCurrentAccessibleValue
594 */
595 public boolean setCurrentAccessibleValue(Number n) {
596 return false; // To be fully implemented in a future release
597 }
598
599 /**
600 * Get the minimum value of this object as a Number.
601 *
602 * @return Minimum value of the object; null if this object does not
603 * have a minimum value
604 * @see #getMaximumAccessibleValue
605 */
606 public Number getMinimumAccessibleValue() {
607 return null; // To be fully implemented in a future release
608 }
609
610 /**
611 * Get the maximum value of this object as a Number.
612 *
613 * @return Maximum value of the object; null if this object does not
614 * have a maximum value
615 * @see #getMinimumAccessibleValue
616 */
617 public Number getMaximumAccessibleValue() {
618 return null; // To be fully implemented in a future release
619 }
620
621 /**
622 * Get the role of this object.
623 *
624 * @return an instance of AccessibleRole describing the role of the
625 * object
626 */
627 public AccessibleRole getAccessibleRole() {
628 return AccessibleRole.CHECK_BOX;
629 }
630
631 } // class AccessibleAWTMenuItem
632
633 }
|