Path: blob/master/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java
41152 views
/*1* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.awt;2627import java.awt.event.ActionListener;28import java.awt.event.ItemEvent;29import java.awt.event.ItemListener;30import java.awt.peer.CheckboxMenuItemPeer;31import java.io.IOException;32import java.io.ObjectInputStream;33import java.io.ObjectOutputStream;34import java.io.Serial;35import java.util.EventListener;3637import javax.accessibility.Accessible;38import javax.accessibility.AccessibleAction;39import javax.accessibility.AccessibleContext;40import javax.accessibility.AccessibleRole;41import javax.accessibility.AccessibleValue;4243import sun.awt.AWTAccessor;4445/**46* This class represents a check box that can be included in a menu.47* Selecting the check box in the menu changes its state from48* "on" to "off" or from "off" to "on."49* <p>50* The following picture depicts a menu which contains an instance51* of {@code CheckBoxMenuItem}:52* <p>53* <img src="doc-files/MenuBar-1.gif"54* alt="Menu labeled Examples, containing items Basic, Simple, Check, and More55* Examples. The Check item is a CheckBoxMenuItem instance, in the off state."56* style="margin: 7px 10px;">57* <p>58* The item labeled {@code Check} shows a check box menu item59* in its "off" state.60* <p>61* When a check box menu item is selected, AWT sends an item event to62* the item. Since the event is an instance of {@code ItemEvent},63* the {@code processEvent} method examines the event and passes64* it along to {@code processItemEvent}. The latter method redirects65* the event to any {@code ItemListener} objects that have66* registered an interest in item events generated by this menu item.67*68* @author Sami Shaio69* @see java.awt.event.ItemEvent70* @see java.awt.event.ItemListener71* @since 1.072*/73public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Accessible {7475static {76/* ensure that the necessary native libraries are loaded */77Toolkit.loadLibraries();78if (!GraphicsEnvironment.isHeadless()) {79initIDs();80}8182AWTAccessor.setCheckboxMenuItemAccessor(83new AWTAccessor.CheckboxMenuItemAccessor() {84public boolean getState(CheckboxMenuItem cmi) {85return cmi.state;86}87});88}8990/**91* The state of a checkbox menu item92* @serial93* @see #getState()94* @see #setState(boolean)95*/96private volatile boolean state;9798private transient volatile ItemListener itemListener;99100private static final String base = "chkmenuitem";101private static int nameCounter = 0;102103/**104* Use serialVersionUID from JDK 1.1 for interoperability.105*/106@Serial107private static final long serialVersionUID = 6190621106981774043L;108109/**110* Create a check box menu item with an empty label.111* The item's state is initially set to "off."112* @exception HeadlessException if GraphicsEnvironment.isHeadless()113* returns true114* @see java.awt.GraphicsEnvironment#isHeadless115* @since 1.1116*/117public CheckboxMenuItem() throws HeadlessException {118this("", false);119}120121/**122* Create a check box menu item with the specified label.123* The item's state is initially set to "off."124125* @param label a string label for the check box menu item,126* or {@code null} for an unlabeled menu item.127* @exception HeadlessException if GraphicsEnvironment.isHeadless()128* returns true129* @see java.awt.GraphicsEnvironment#isHeadless130*/131public CheckboxMenuItem(String label) throws HeadlessException {132this(label, false);133}134135/**136* Create a check box menu item with the specified label and state.137* @param label a string label for the check box menu item,138* or {@code null} for an unlabeled menu item.139* @param state the initial state of the menu item, where140* {@code true} indicates "on" and141* {@code false} indicates "off."142* @exception HeadlessException if GraphicsEnvironment.isHeadless()143* returns true144* @see java.awt.GraphicsEnvironment#isHeadless145* @since 1.1146*/147public CheckboxMenuItem(String label, boolean state)148throws HeadlessException {149super(label);150this.state = state;151}152153/**154* Construct a name for this MenuComponent. Called by getName() when155* the name is null.156*/157String constructComponentName() {158synchronized (CheckboxMenuItem.class) {159return base + nameCounter++;160}161}162163/**164* Creates the peer of the checkbox item. This peer allows us to165* change the look of the checkbox item without changing its166* functionality.167* Most applications do not call this method directly.168* @see java.awt.Component#getToolkit()169*/170public void addNotify() {171synchronized (getTreeLock()) {172if (peer == null)173peer = getComponentFactory().createCheckboxMenuItem(this);174super.addNotify();175}176}177178/**179* Determines whether the state of this check box menu item180* is "on" or "off."181*182* @return the state of this check box menu item, where183* {@code true} indicates "on" and184* {@code false} indicates "off"185* @see #setState186*/187public boolean getState() {188return state;189}190191/**192* Sets this check box menu item to the specified state.193* The boolean value {@code true} indicates "on" while194* {@code false} indicates "off."195*196* <p>Note that this method should be primarily used to197* initialize the state of the check box menu item.198* Programmatically setting the state of the check box199* menu item will <i>not</i> trigger200* an {@code ItemEvent}. The only way to trigger an201* {@code ItemEvent} is by user interaction.202*203* @param b {@code true} if the check box204* menu item is on, otherwise {@code false}205* @see #getState206*/207public synchronized void setState(boolean b) {208state = b;209CheckboxMenuItemPeer peer = (CheckboxMenuItemPeer)this.peer;210if (peer != null) {211peer.setState(b);212}213}214215/**216* Returns the an array (length 1) containing the checkbox menu item217* label or null if the checkbox is not selected.218* @see ItemSelectable219*/220public synchronized Object[] getSelectedObjects() {221if (state) {222Object[] items = new Object[1];223items[0] = label;224return items;225}226return null;227}228229/**230* Adds the specified item listener to receive item events from231* this check box menu item. Item events are sent in response to user232* actions, but not in response to calls to setState().233* If l is null, no exception is thrown and no action is performed.234* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"235* >AWT Threading Issues</a> for details on AWT's threading model.236*237* @param l the item listener238* @see #removeItemListener239* @see #getItemListeners240* @see #setState241* @see java.awt.event.ItemEvent242* @see java.awt.event.ItemListener243* @since 1.1244*/245public synchronized void addItemListener(ItemListener l) {246if (l == null) {247return;248}249itemListener = AWTEventMulticaster.add(itemListener, l);250newEventsOnly = true;251}252253/**254* Removes the specified item listener so that it no longer receives255* item events from this check box menu item.256* If l is null, no exception is thrown and no action is performed.257* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"258* >AWT Threading Issues</a> for details on AWT's threading model.259*260* @param l the item listener261* @see #addItemListener262* @see #getItemListeners263* @see java.awt.event.ItemEvent264* @see java.awt.event.ItemListener265* @since 1.1266*/267public synchronized void removeItemListener(ItemListener l) {268if (l == null) {269return;270}271itemListener = AWTEventMulticaster.remove(itemListener, l);272}273274/**275* Returns an array of all the item listeners276* registered on this checkbox menuitem.277*278* @return all of this checkbox menuitem's {@code ItemListener}s279* or an empty array if no item280* listeners are currently registered281*282* @see #addItemListener283* @see #removeItemListener284* @see java.awt.event.ItemEvent285* @see java.awt.event.ItemListener286* @since 1.4287*/288public synchronized ItemListener[] getItemListeners() {289return getListeners(ItemListener.class);290}291292/**293* Returns an array of all the objects currently registered294* as <code><em>Foo</em>Listener</code>s295* upon this {@code CheckboxMenuItem}.296* <code><em>Foo</em>Listener</code>s are registered using the297* <code>add<em>Foo</em>Listener</code> method.298*299* <p>300* You can specify the {@code listenerType} argument301* with a class literal, such as302* <code><em>Foo</em>Listener.class</code>.303* For example, you can query a304* {@code CheckboxMenuItem c}305* for its item listeners with the following code:306*307* <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre>308*309* If no such listeners exist, this method returns an empty array.310*311* @param listenerType the type of listeners requested; this parameter312* should specify an interface that descends from313* {@code java.util.EventListener}314* @return an array of all objects registered as315* <code><em>Foo</em>Listener</code>s on this checkbox menuitem,316* or an empty array if no such317* listeners have been added318* @exception ClassCastException if {@code listenerType}319* doesn't specify a class or interface that implements320* {@code java.util.EventListener}321*322* @see #getItemListeners323* @since 1.3324*/325public <T extends EventListener> T[] getListeners(Class<T> listenerType) {326EventListener l = null;327if (listenerType == ItemListener.class) {328l = itemListener;329} else {330return super.getListeners(listenerType);331}332return AWTEventMulticaster.getListeners(l, listenerType);333}334335// REMIND: remove when filtering is done at lower level336boolean eventEnabled(AWTEvent e) {337if (e.id == ItemEvent.ITEM_STATE_CHANGED) {338if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 ||339itemListener != null) {340return true;341}342return false;343}344return super.eventEnabled(e);345}346347/**348* Processes events on this check box menu item.349* If the event is an instance of {@code ItemEvent},350* this method invokes the {@code processItemEvent} method.351* If the event is not an item event,352* it invokes {@code processEvent} on the superclass.353* <p>354* Check box menu items currently support only item events.355* <p>Note that if the event parameter is {@code null}356* the behavior is unspecified and may result in an357* exception.358*359* @param e the event360* @see java.awt.event.ItemEvent361* @see #processItemEvent362* @since 1.1363*/364protected void processEvent(AWTEvent e) {365if (e instanceof ItemEvent) {366processItemEvent((ItemEvent)e);367return;368}369super.processEvent(e);370}371372/**373* Processes item events occurring on this check box menu item by374* dispatching them to any registered {@code ItemListener} objects.375* <p>376* This method is not called unless item events are377* enabled for this menu item. Item events are enabled378* when one of the following occurs:379* <ul>380* <li>An {@code ItemListener} object is registered381* via {@code addItemListener}.382* <li>Item events are enabled via {@code enableEvents}.383* </ul>384* <p>Note that if the event parameter is {@code null}385* the behavior is unspecified and may result in an386* exception.387*388* @param e the item event389* @see java.awt.event.ItemEvent390* @see java.awt.event.ItemListener391* @see #addItemListener392* @see java.awt.MenuItem#enableEvents393* @since 1.1394*/395protected void processItemEvent(ItemEvent e) {396ItemListener listener = itemListener;397if (listener != null) {398listener.itemStateChanged(e);399}400}401402/*403* Post an ItemEvent and toggle state.404*/405void doMenuEvent(long when, int modifiers) {406setState(!state);407Toolkit.getEventQueue().postEvent(408new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,409getLabel(),410state ? ItemEvent.SELECTED :411ItemEvent.DESELECTED));412}413414/**415* Returns a string representing the state of this416* {@code CheckBoxMenuItem}. This417* method is intended to be used only for debugging purposes, and the418* content and format of the returned string may vary between419* implementations. The returned string may be empty but may not be420* {@code null}.421*422* @return the parameter string of this check box menu item423*/424public String paramString() {425return super.paramString() + ",state=" + state;426}427428/* Serialization support.429*/430431/**432* Serialized data version.433* @serial434*/435private int checkboxMenuItemSerializedDataVersion = 1;436437/**438* Writes default serializable fields to stream. Writes439* a list of serializable {@code ItemListeners}440* as optional data. The non-serializable441* {@code ItemListeners} are detected and442* no attempt is made to serialize them.443*444* @param s the {@code ObjectOutputStream} to write445* @throws IOException if an I/O error occurs446* @serialData {@code null} terminated sequence of447* 0 or more pairs; the pair consists of a {@code String}448* and an {@code Object}; the {@code String} indicates449* the type of object and is one of the following:450* {@code itemListenerK} indicating an451* {@code ItemListener} object452*453* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)454* @see java.awt.Component#itemListenerK455* @see #readObject(ObjectInputStream)456*/457@Serial458private void writeObject(ObjectOutputStream s)459throws java.io.IOException460{461s.defaultWriteObject();462463AWTEventMulticaster.save(s, itemListenerK, itemListener);464s.writeObject(null);465}466467/**468* Reads the {@code ObjectInputStream} and if it469* isn't {@code null} adds a listener to receive470* item events fired by the {@code Checkbox} menu item.471* Unrecognized keys or values will be ignored.472*473* @param s the {@code ObjectInputStream} to read474* @throws ClassNotFoundException if the class of a serialized object could475* not be found476* @throws IOException if an I/O error occurs477* @serial478* @see #removeActionListener(ActionListener)479* @see #addActionListener(ActionListener)480* @see #writeObject(ObjectOutputStream)481*/482@Serial483private void readObject(ObjectInputStream s)484throws ClassNotFoundException, IOException485{486s.defaultReadObject();487488Object keyOrNull;489while(null != (keyOrNull = s.readObject())) {490String key = ((String)keyOrNull).intern();491492if (itemListenerK == key)493addItemListener((ItemListener)(s.readObject()));494495else // skip value for unrecognized key496s.readObject();497}498}499500/**501* Initialize JNI field and method IDs502*/503private static native void initIDs();504505506/////////////////507// Accessibility support508////////////////509510/**511* Gets the AccessibleContext associated with this CheckboxMenuItem.512* For checkbox menu items, the AccessibleContext takes the513* form of an AccessibleAWTCheckboxMenuItem.514* A new AccessibleAWTCheckboxMenuItem is created if necessary.515*516* @return an AccessibleAWTCheckboxMenuItem that serves as the517* AccessibleContext of this CheckboxMenuItem518* @since 1.3519*/520public AccessibleContext getAccessibleContext() {521if (accessibleContext == null) {522accessibleContext = new AccessibleAWTCheckboxMenuItem();523}524return accessibleContext;525}526527/**528* Inner class of CheckboxMenuItem used to provide default support for529* accessibility. This class is not meant to be used directly by530* application developers, but is instead meant only to be531* subclassed by menu component developers.532* <p>533* This class implements accessibility support for the534* {@code CheckboxMenuItem} class. It provides an implementation535* of the Java Accessibility API appropriate to checkbox menu item536* user-interface elements.537* @since 1.3538*/539protected class AccessibleAWTCheckboxMenuItem extends AccessibleAWTMenuItem540implements AccessibleAction, AccessibleValue541{542/**543* Use serialVersionUID from JDK 1.3 for interoperability.544*/545@Serial546private static final long serialVersionUID = -1122642964303476L;547548/**549* Constructs an {@code AccessibleAWTCheckboxMenuItem}.550*/551protected AccessibleAWTCheckboxMenuItem() {}552553/**554* Get the AccessibleAction associated with this object. In the555* implementation of the Java Accessibility API for this class,556* return this object, which is responsible for implementing the557* AccessibleAction interface on behalf of itself.558*559* @return this object560*/561public AccessibleAction getAccessibleAction() {562return this;563}564565/**566* Get the AccessibleValue associated with this object. In the567* implementation of the Java Accessibility API for this class,568* return this object, which is responsible for implementing the569* AccessibleValue interface on behalf of itself.570*571* @return this object572*/573public AccessibleValue getAccessibleValue() {574return this;575}576577/**578* Returns the number of Actions available in this object.579* If there is more than one, the first one is the "default"580* action.581*582* @return the number of Actions in this object583*/584public int getAccessibleActionCount() {585return 0; // To be fully implemented in a future release586}587588/**589* Return a description of the specified action of the object.590*591* @param i zero-based index of the actions592*/593public String getAccessibleActionDescription(int i) {594return null; // To be fully implemented in a future release595}596597/**598* Perform the specified Action on the object599*600* @param i zero-based index of actions601* @return true if the action was performed; otherwise false.602*/603public boolean doAccessibleAction(int i) {604return false; // To be fully implemented in a future release605}606607/**608* Get the value of this object as a Number. If the value has not been609* set, the return value will be null.610*611* @return value of the object612* @see #setCurrentAccessibleValue613*/614public Number getCurrentAccessibleValue() {615return null; // To be fully implemented in a future release616}617618/**619* Set the value of this object as a Number.620*621* @return true if the value was set; otherwise false622* @see #getCurrentAccessibleValue623*/624public boolean setCurrentAccessibleValue(Number n) {625return false; // To be fully implemented in a future release626}627628/**629* Get the minimum value of this object as a Number.630*631* @return Minimum value of the object; null if this object does not632* have a minimum value633* @see #getMaximumAccessibleValue634*/635public Number getMinimumAccessibleValue() {636return null; // To be fully implemented in a future release637}638639/**640* Get the maximum value of this object as a Number.641*642* @return Maximum value of the object; null if this object does not643* have a maximum value644* @see #getMinimumAccessibleValue645*/646public Number getMaximumAccessibleValue() {647return null; // To be fully implemented in a future release648}649650/**651* Get the role of this object.652*653* @return an instance of AccessibleRole describing the role of the654* object655*/656public AccessibleRole getAccessibleRole() {657return AccessibleRole.CHECK_BOX;658}659660} // class AccessibleAWTMenuItem661662}663664665