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: }
|