Path: blob/master/src/java.desktop/share/classes/java/awt/Button.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.ActionEvent;28import java.awt.event.ActionListener;29import java.awt.peer.ButtonPeer;30import java.beans.BeanProperty;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;4243/**44* This class creates a labeled button. The application can cause45* some action to happen when the button is pushed. This image46* depicts three views of a "{@code Quit}" button as it appears47* under the Solaris operating system:48* <p>49* <img src="doc-files/Button-1.gif" alt="The following context describes the50* graphic" style="margin: 7px 10px;">51* <p>52* The first view shows the button as it appears normally.53* The second view shows the button54* when it has input focus. Its outline is darkened to let the55* user know that it is an active object. The third view shows the56* button when the user clicks the mouse over the button, and thus57* requests that an action be performed.58* <p>59* The gesture of clicking on a button with the mouse60* is associated with one instance of {@code ActionEvent},61* which is sent out when the mouse is both pressed and released62* over the button. If an application is interested in knowing63* when the button has been pressed but not released, as a separate64* gesture, it can specialize {@code processMouseEvent},65* or it can register itself as a listener for mouse events by66* calling {@code addMouseListener}. Both of these methods are67* defined by {@code Component}, the abstract superclass of68* all components.69* <p>70* When a button is pressed and released, AWT sends an instance71* of {@code ActionEvent} to the button, by calling72* {@code processEvent} on the button. The button's73* {@code processEvent} method receives all events74* for the button; it passes an action event along by75* calling its own {@code processActionEvent} method.76* The latter method passes the action event on to any action77* listeners that have registered an interest in action78* events generated by this button.79* <p>80* If an application wants to perform some action based on81* a button being pressed and released, it should implement82* {@code ActionListener} and register the new listener83* to receive events from this button, by calling the button's84* {@code addActionListener} method. The application can85* make use of the button's action command as a messaging protocol.86*87* @author Sami Shaio88* @see java.awt.event.ActionEvent89* @see java.awt.event.ActionListener90* @see java.awt.Component#processMouseEvent91* @see java.awt.Component#addMouseListener92* @since 1.093*/94public class Button extends Component implements Accessible {9596/**97* The button's label. This value may be null.98* @serial99* @see #getLabel()100* @see #setLabel(String)101*/102String label;103104/**105* The action to be performed once a button has been106* pressed. This value may be null.107* @serial108* @see #getActionCommand()109* @see #setActionCommand(String)110*/111String actionCommand;112113transient ActionListener actionListener;114115private static final String base = "button";116private static int nameCounter = 0;117118/**119* Use serialVersionUID from JDK 1.1 for interoperability.120*/121@Serial122private static final long serialVersionUID = -8774683716313001058L;123124125static {126/* ensure that the necessary native libraries are loaded */127Toolkit.loadLibraries();128if (!GraphicsEnvironment.isHeadless()) {129initIDs();130}131}132133/**134* Initialize JNI field and method IDs for fields that may be135* accessed from C.136*/137private static native void initIDs();138139/**140* Constructs a button with an empty string for its label.141*142* @exception HeadlessException if GraphicsEnvironment.isHeadless()143* returns true144* @see java.awt.GraphicsEnvironment#isHeadless145*/146public Button() throws HeadlessException {147this("");148}149150/**151* Constructs a button with the specified label.152*153* @param label a string label for the button, or154* {@code null} for no label155* @exception HeadlessException if GraphicsEnvironment.isHeadless()156* returns true157* @see java.awt.GraphicsEnvironment#isHeadless158*/159public Button(String label) throws HeadlessException {160GraphicsEnvironment.checkHeadless();161this.label = label;162}163164/**165* Construct a name for this component. Called by getName() when the166* name is null.167*/168String constructComponentName() {169synchronized (Button.class) {170return base + nameCounter++;171}172}173174/**175* Creates the peer of the button. The button's peer allows the176* application to change the look of the button without changing177* its functionality.178*179* @see java.awt.Component#getToolkit()180*/181public void addNotify() {182synchronized(getTreeLock()) {183if (peer == null)184peer = getComponentFactory().createButton(this);185super.addNotify();186}187}188189/**190* Gets the label of this button.191*192* @return the button's label, or {@code null}193* if the button has no label.194* @see java.awt.Button#setLabel195*/196public String getLabel() {197return label;198}199200/**201* Sets the button's label to be the specified string.202*203* @param label the new label, or {@code null}204* if the button has no label.205* @see java.awt.Button#getLabel206*/207public void setLabel(String label) {208boolean testvalid = false;209210synchronized (this) {211if (label != this.label && (this.label == null ||212!this.label.equals(label))) {213this.label = label;214ButtonPeer peer = (ButtonPeer)this.peer;215if (peer != null) {216peer.setLabel(label);217}218testvalid = true;219}220}221222// This could change the preferred size of the Component.223if (testvalid) {224invalidateIfValid();225}226}227228/**229* Sets the command name for the action event fired230* by this button. By default this action command is231* set to match the label of the button.232*233* @param command a string used to set the button's234* action command.235* If the string is {@code null} then the action command236* is set to match the label of the button.237* @see java.awt.event.ActionEvent238* @since 1.1239*/240public void setActionCommand(String command) {241actionCommand = command;242}243244/**245* Returns the command name of the action event fired by this button.246* If the command name is {@code null} (default) then this method247* returns the label of the button.248*249* @return the action command name (or label) for this button250*/251public String getActionCommand() {252return (actionCommand == null? label : actionCommand);253}254255/**256* Adds the specified action listener to receive action events from257* this button. Action events occur when a user presses or releases258* the mouse over this button.259* If l is null, no exception is thrown and no action is performed.260* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"261* >AWT Threading Issues</a> for details on AWT's threading model.262*263* @param l the action listener264* @see #removeActionListener265* @see #getActionListeners266* @see java.awt.event.ActionListener267* @since 1.1268*/269public synchronized void addActionListener(ActionListener l) {270if (l == null) {271return;272}273actionListener = AWTEventMulticaster.add(actionListener, l);274newEventsOnly = true;275}276277/**278* Removes the specified action listener so that it no longer279* receives action events from this button. Action events occur280* when a user presses or releases the mouse over this button.281* If l is null, no exception is thrown and no action is performed.282* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"283* >AWT Threading Issues</a> for details on AWT's threading model.284*285* @param l the action listener286* @see #addActionListener287* @see #getActionListeners288* @see java.awt.event.ActionListener289* @since 1.1290*/291public synchronized void removeActionListener(ActionListener l) {292if (l == null) {293return;294}295actionListener = AWTEventMulticaster.remove(actionListener, l);296}297298/**299* Returns an array of all the action listeners300* registered on this button.301*302* @return all of this button's {@code ActionListener}s303* or an empty array if no action304* listeners are currently registered305*306* @see #addActionListener307* @see #removeActionListener308* @see java.awt.event.ActionListener309* @since 1.4310*/311public synchronized ActionListener[] getActionListeners() {312return getListeners(ActionListener.class);313}314315/**316* Returns an array of all the objects currently registered317* as <code><em>Foo</em>Listener</code>s318* upon this {@code Button}.319* <code><em>Foo</em>Listener</code>s are registered using the320* <code>add<em>Foo</em>Listener</code> method.321*322* <p>323* You can specify the {@code listenerType} argument324* with a class literal, such as325* <code><em>Foo</em>Listener.class</code>.326* For example, you can query a327* {@code Button b}328* for its action listeners with the following code:329*330* <pre>ActionListener[] als = (ActionListener[])(b.getListeners(ActionListener.class));</pre>331*332* If no such listeners exist, this method returns an empty array.333*334* @param listenerType the type of listeners requested; this parameter335* should specify an interface that descends from336* {@code java.util.EventListener}337* @return an array of all objects registered as338* <code><em>Foo</em>Listener</code>s on this button,339* or an empty array if no such340* listeners have been added341* @exception ClassCastException if {@code listenerType}342* doesn't specify a class or interface that implements343* {@code java.util.EventListener}344*345* @see #getActionListeners346* @since 1.3347*/348public <T extends EventListener> T[] getListeners(Class<T> listenerType) {349EventListener l = null;350if (listenerType == ActionListener.class) {351l = actionListener;352} else {353return super.getListeners(listenerType);354}355return AWTEventMulticaster.getListeners(l, listenerType);356}357358// REMIND: remove when filtering is done at lower level359boolean eventEnabled(AWTEvent e) {360if (e.id == ActionEvent.ACTION_PERFORMED) {361if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||362actionListener != null) {363return true;364}365return false;366}367return super.eventEnabled(e);368}369370/**371* Processes events on this button. If an event is372* an instance of {@code ActionEvent}, this method invokes373* the {@code processActionEvent} method. Otherwise,374* it invokes {@code processEvent} on the superclass.375* <p>Note that if the event parameter is {@code null}376* the behavior is unspecified and may result in an377* exception.378*379* @param e the event380* @see java.awt.event.ActionEvent381* @see java.awt.Button#processActionEvent382* @since 1.1383*/384protected void processEvent(AWTEvent e) {385if (e instanceof ActionEvent) {386processActionEvent((ActionEvent)e);387return;388}389super.processEvent(e);390}391392/**393* Processes action events occurring on this button394* by dispatching them to any registered395* {@code ActionListener} objects.396* <p>397* This method is not called unless action events are398* enabled for this button. Action events are enabled399* when one of the following occurs:400* <ul>401* <li>An {@code ActionListener} object is registered402* via {@code addActionListener}.403* <li>Action events are enabled via {@code enableEvents}.404* </ul>405* <p>Note that if the event parameter is {@code null}406* the behavior is unspecified and may result in an407* exception.408*409* @param e the action event410* @see java.awt.event.ActionListener411* @see java.awt.Button#addActionListener412* @see java.awt.Component#enableEvents413* @since 1.1414*/415protected void processActionEvent(ActionEvent e) {416ActionListener listener = actionListener;417if (listener != null) {418listener.actionPerformed(e);419}420}421422/**423* Returns a string representing the state of this {@code Button}.424* This method is intended to be used only for debugging purposes, and the425* content and format of the returned string may vary between426* implementations. The returned string may be empty but may not be427* {@code null}.428*429* @return the parameter string of this button430*/431protected String paramString() {432return super.paramString() + ",label=" + label;433}434435436/* Serialization support.437*/438/**439* Serialized data version.440* @serial441*/442private int buttonSerializedDataVersion = 1;443444/**445* Writes default serializable fields to stream. Writes446* a list of serializable {@code ActionListeners}447* as optional data. The non-serializable448* {@code ActionListeners} are detected and449* no attempt is made to serialize them.450*451* @serialData {@code null} terminated sequence of 0 or452* more pairs: the pair consists of a {@code String}453* and an {@code Object}; the {@code String}454* indicates the type of object and is one of the following:455* {@code actionListenerK} indicating an456* {@code ActionListener} object457*458* @param s the {@code ObjectOutputStream} to write459* @throws IOException if an I/O error occurs460* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)461* @see java.awt.Component#actionListenerK462* @see #readObject(ObjectInputStream)463*/464@Serial465private void writeObject(ObjectOutputStream s)466throws IOException467{468s.defaultWriteObject();469470AWTEventMulticaster.save(s, actionListenerK, actionListener);471s.writeObject(null);472}473474/**475* Reads the {@code ObjectInputStream} and if476* it isn't {@code null} adds a listener to477* receive action events fired by the button.478* Unrecognized keys or values will be ignored.479*480* @param s the {@code ObjectInputStream} to read481* @throws ClassNotFoundException if the class of a serialized object could482* not be found483* @throws IOException if an I/O error occurs484* @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}485* returns {@code true}486* @serial487* @see #removeActionListener(ActionListener)488* @see #addActionListener(ActionListener)489* @see java.awt.GraphicsEnvironment#isHeadless490* @see #writeObject(ObjectOutputStream)491*/492@Serial493private void readObject(ObjectInputStream s)494throws ClassNotFoundException, IOException, HeadlessException495{496GraphicsEnvironment.checkHeadless();497s.defaultReadObject();498499Object keyOrNull;500while(null != (keyOrNull = s.readObject())) {501String key = ((String)keyOrNull).intern();502503if (actionListenerK == key)504addActionListener((ActionListener)(s.readObject()));505506else // skip value for unrecognized key507s.readObject();508}509}510511512/////////////////513// Accessibility support514////////////////515516/**517* Gets the {@code AccessibleContext} associated with518* this {@code Button}. For buttons, the519* {@code AccessibleContext} takes the form of an520* {@code AccessibleAWTButton}.521* A new {@code AccessibleAWTButton} instance is522* created if necessary.523*524* @return an {@code AccessibleAWTButton} that serves as the525* {@code AccessibleContext} of this {@code Button}526* @since 1.3527*/528@BeanProperty(expert = true, description529= "The AccessibleContext associated with this Button.")530public AccessibleContext getAccessibleContext() {531if (accessibleContext == null) {532accessibleContext = new AccessibleAWTButton();533}534return accessibleContext;535}536537/**538* This class implements accessibility support for the539* {@code Button} class. It provides an implementation of the540* Java Accessibility API appropriate to button user-interface elements.541* @since 1.3542*/543protected class AccessibleAWTButton extends AccessibleAWTComponent544implements AccessibleAction, AccessibleValue545{546/**547* Use serialVersionUID from JDK 1.3 for interoperability.548*/549@Serial550private static final long serialVersionUID = -5932203980244017102L;551552/**553* Constructs an {@code AccessibleAWTButton}.554*/555protected AccessibleAWTButton() {}556557/**558* Get the accessible name of this object.559*560* @return the localized name of the object -- can be null if this561* object does not have a name562*/563public String getAccessibleName() {564if (accessibleName != null) {565return accessibleName;566} else {567if (getLabel() == null) {568return super.getAccessibleName();569} else {570return getLabel();571}572}573}574575/**576* Get the AccessibleAction associated with this object. In the577* implementation of the Java Accessibility API for this class,578* return this object, which is responsible for implementing the579* AccessibleAction interface on behalf of itself.580*581* @return this object582*/583public AccessibleAction getAccessibleAction() {584return this;585}586587/**588* Get the AccessibleValue associated with this object. In the589* implementation of the Java Accessibility API for this class,590* return this object, which is responsible for implementing the591* AccessibleValue interface on behalf of itself.592*593* @return this object594*/595public AccessibleValue getAccessibleValue() {596return this;597}598599/**600* Returns the number of Actions available in this object. The601* default behavior of a button is to have one action - toggle602* the button.603*604* @return 1, the number of Actions in this object605*/606public int getAccessibleActionCount() {607return 1;608}609610/**611* Return a description of the specified action of the object.612*613* @param i zero-based index of the actions614*/615public String getAccessibleActionDescription(int i) {616if (i == 0) {617// [[[PENDING: WDW -- need to provide a localized string]]]618return "click";619} else {620return null;621}622}623624/**625* Perform the specified Action on the object626*627* @param i zero-based index of actions628* @return true if the action was performed; else false.629*/630public boolean doAccessibleAction(int i) {631if (i == 0) {632// Simulate a button click633Toolkit.getEventQueue().postEvent(634new ActionEvent(Button.this,635ActionEvent.ACTION_PERFORMED,636Button.this.getActionCommand()));637return true;638} else {639return false;640}641}642643/**644* Get the value of this object as a Number.645*646* @return An Integer of 0 if this isn't selected or an Integer of 1 if647* this is selected.648* @see javax.swing.AbstractButton#isSelected()649*/650public Number getCurrentAccessibleValue() {651return Integer.valueOf(0);652}653654/**655* Set the value of this object as a Number.656*657* @return True if the value was set.658*/659public boolean setCurrentAccessibleValue(Number n) {660return false;661}662663/**664* Get the minimum value of this object as a Number.665*666* @return An Integer of 0.667*/668public Number getMinimumAccessibleValue() {669return Integer.valueOf(0);670}671672/**673* Get the maximum value of this object as a Number.674*675* @return An Integer of 0.676*/677public Number getMaximumAccessibleValue() {678return Integer.valueOf(0);679}680681/**682* Get the role of this object.683*684* @return an instance of AccessibleRole describing the role of the685* object686* @see AccessibleRole687*/688public AccessibleRole getAccessibleRole() {689return AccessibleRole.PUSH_BUTTON;690}691} // inner class AccessibleAWTButton692693}694695696