1 /*
   2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.swing;
  26 
  27 import java.beans.JavaBean;
  28 import java.beans.BeanProperty;
  29 import java.beans.ConstructorProperties;
  30 
  31 import javax.swing.plaf.*;
  32 import javax.accessibility.*;
  33 
  34 import java.io.ObjectOutputStream;
  35 import java.io.IOException;
  36 
  37 /**
  38  * An implementation of a "push" button.
  39   * <p>
  40  * Buttons can be configured, and to some degree controlled, by
  41  * <code><a href="Action.html">Action</a></code>s.  Using an
  42  * <code>Action</code> with a button has many benefits beyond directly
  43  * configuring a button.  Refer to <a href="Action.html#buttonActions">
  44  * Swing Components Supporting <code>Action</code></a> for more
  45  * details, and you can find more information in <a
  46  * href="http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html">How
  47  * to Use Actions</a>, a section in <em>The Java Tutorial</em>.
  48  * <p>
  49  * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/button.html">How to Use Buttons, Check Boxes, and Radio Buttons</a>
  50  * in <em>The Java Tutorial</em>
  51  * for information and examples of using buttons.
  52  * <p>
  53  * <strong>Warning:</strong> Swing is not thread safe. For more
  54  * information see <a
  55  * href="package-summary.html#threading">Swing's Threading
  56  * Policy</a>.
  57  * <p>
  58  * <strong>Warning:</strong>
  59  * Serialized objects of this class will not be compatible with
  60  * future Swing releases. The current serialization support is
  61  * appropriate for short term storage or RMI between applications running
  62  * the same version of Swing.  As of 1.4, support for long term storage
  63  * of all JavaBeans&trade;
  64  * has been added to the <code>java.beans</code> package.
  65  * Please see {@link java.beans.XMLEncoder}.
  66  *
  67  * @author Jeff Dinkins
  68  * @since 1.2
  69  */
  70 @JavaBean(defaultProperty = "UIClassID", description = "An implementation of a \"push\" button.")
  71 @SwingContainer(false)
  72 @SuppressWarnings("serial")
  73 public class JButton extends AbstractButton implements Accessible {
  74 
  75     /**
  76      * @see #getUIClassID
  77      * @see #readObject
  78      */
  79     private static final String uiClassID = "ButtonUI";
  80 
  81     /**
  82      * Creates a button with no set text or icon.
  83      */
  84     public JButton() {
  85         this(null, null);
  86     }
  87 
  88     /**
  89      * Creates a button with an icon.
  90      *
  91      * @param icon  the Icon image to display on the button
  92      */
  93     public JButton(Icon icon) {
  94         this(null, icon);
  95     }
  96 
  97     /**
  98      * Creates a button with text.
  99      *
 100      * @param text  the text of the button
 101      */
 102     @ConstructorProperties({"text"})
 103     public JButton(String text) {
 104         this(text, null);
 105     }
 106 
 107     /**
 108      * Creates a button where properties are taken from the
 109      * <code>Action</code> supplied.
 110      *
 111      * @param a the <code>Action</code> used to specify the new button
 112      *
 113      * @since 1.3
 114      */
 115     public JButton(Action a) {
 116         this();
 117         setAction(a);
 118     }
 119 
 120     /**
 121      * Creates a button with initial text and an icon.
 122      *
 123      * @param text  the text of the button
 124      * @param icon  the Icon image to display on the button
 125      */
 126     public JButton(String text, Icon icon) {
 127         // Create the model
 128         setModel(new DefaultButtonModel());
 129 
 130         // initialize
 131         init(text, icon);
 132     }
 133 
 134     /**
 135      * Resets the UI property to a value from the current look and
 136      * feel.
 137      *
 138      * @see JComponent#updateUI
 139      */
 140     public void updateUI() {
 141         setUI((ButtonUI)UIManager.getUI(this));
 142     }
 143 
 144 
 145     /**
 146      * Returns a string that specifies the name of the L&amp;F class
 147      * that renders this component.
 148      *
 149      * @return the string "ButtonUI"
 150      * @see JComponent#getUIClassID
 151      * @see UIDefaults#getUI
 152      */
 153     @BeanProperty(bound = false, expert = true, description
 154             = "A string that specifies the name of the L&amp;F class.")
 155     public String getUIClassID() {
 156         return uiClassID;
 157     }
 158 
 159 
 160     /**
 161      * Gets the value of the <code>defaultButton</code> property,
 162      * which if <code>true</code> means that this button is the current
 163      * default button for its <code>JRootPane</code>.
 164      * Most look and feels render the default button
 165      * differently, and may potentially provide bindings
 166      * to access the default button.
 167      *
 168      * @return the value of the <code>defaultButton</code> property
 169      * @see JRootPane#setDefaultButton
 170      * @see #isDefaultCapable
 171      */
 172     @BeanProperty(bound = false, description
 173             = "Whether or not this button is the default button")
 174     public boolean isDefaultButton() {
 175         JRootPane root = SwingUtilities.getRootPane(this);
 176         if (root != null) {
 177             return root.getDefaultButton() == this;
 178         }
 179         return false;
 180     }
 181 
 182     /**
 183      * Gets the value of the <code>defaultCapable</code> property.
 184      *
 185      * @return the value of the <code>defaultCapable</code> property
 186      * @see #setDefaultCapable
 187      * @see #isDefaultButton
 188      * @see JRootPane#setDefaultButton
 189      */
 190     public boolean isDefaultCapable() {
 191         return defaultCapable;
 192     }
 193 
 194     /**
 195      * Sets the <code>defaultCapable</code> property,
 196      * which determines whether this button can be
 197      * made the default button for its root pane.
 198      * The default value of the <code>defaultCapable</code>
 199      * property is <code>true</code> unless otherwise
 200      * specified by the look and feel.
 201      *
 202      * @param defaultCapable <code>true</code> if this button will be
 203      *        capable of being the default button on the
 204      *        <code>RootPane</code>; otherwise <code>false</code>
 205      * @see #isDefaultCapable
 206      */
 207     @BeanProperty(visualUpdate = true, description
 208             = "Whether or not this button can be the default button")
 209     public void setDefaultCapable(boolean defaultCapable) {
 210         boolean oldDefaultCapable = this.defaultCapable;
 211         this.defaultCapable = defaultCapable;
 212         firePropertyChange("defaultCapable", oldDefaultCapable, defaultCapable);
 213     }
 214 
 215     /**
 216      * Overrides <code>JComponent.removeNotify</code> to check if
 217      * this button is currently set as the default button on the
 218      * <code>RootPane</code>, and if so, sets the <code>RootPane</code>'s
 219      * default button to <code>null</code> to ensure the
 220      * <code>RootPane</code> doesn't hold onto an invalid button reference.
 221      */
 222     public void removeNotify() {
 223         JRootPane root = SwingUtilities.getRootPane(this);
 224         if (root != null && root.getDefaultButton() == this) {
 225             root.setDefaultButton(null);
 226         }
 227         super.removeNotify();
 228     }
 229 
 230     /**
 231      * See readObject() and writeObject() in JComponent for more
 232      * information about serialization in Swing.
 233      */
 234     private void writeObject(ObjectOutputStream s) throws IOException {
 235         s.defaultWriteObject();
 236         if (getUIClassID().equals(uiClassID)) {
 237             byte count = JComponent.getWriteObjCounter(this);
 238             JComponent.setWriteObjCounter(this, --count);
 239             if (count == 0 && ui != null) {
 240                 ui.installUI(this);
 241             }
 242         }
 243     }
 244 
 245 
 246     /**
 247      * Returns a string representation of this <code>JButton</code>.
 248      * This method is intended to be used only for debugging purposes, and the
 249      * content and format of the returned string may vary between
 250      * implementations. The returned string may be empty but may not
 251      * be <code>null</code>.
 252      *
 253      * @return  a string representation of this <code>JButton</code>
 254      */
 255     protected String paramString() {
 256         String defaultCapableString = (defaultCapable ? "true" : "false");
 257 
 258         return super.paramString() +
 259             ",defaultCapable=" + defaultCapableString;
 260     }
 261 
 262 
 263 /////////////////
 264 // Accessibility support
 265 ////////////////
 266 
 267     /**
 268      * Gets the <code>AccessibleContext</code> associated with this
 269      * <code>JButton</code>. For <code>JButton</code>s,
 270      * the <code>AccessibleContext</code> takes the form of an
 271      * <code>AccessibleJButton</code>.
 272      * A new <code>AccessibleJButton</code> instance is created if necessary.
 273      *
 274      * @return an <code>AccessibleJButton</code> that serves as the
 275      *         <code>AccessibleContext</code> of this <code>JButton</code>
 276      */
 277     @BeanProperty(bound = false, expert = true, description
 278             = "The AccessibleContext associated with this Button.")
 279     public AccessibleContext getAccessibleContext() {
 280         if (accessibleContext == null) {
 281             accessibleContext = new AccessibleJButton();
 282         }
 283         return accessibleContext;
 284     }
 285 
 286     /**
 287      * This class implements accessibility support for the
 288      * <code>JButton</code> class.  It provides an implementation of the
 289      * Java Accessibility API appropriate to button user-interface
 290      * elements.
 291      * <p>
 292      * <strong>Warning:</strong>
 293      * Serialized objects of this class will not be compatible with
 294      * future Swing releases. The current serialization support is
 295      * appropriate for short term storage or RMI between applications running
 296      * the same version of Swing.  As of 1.4, support for long term storage
 297      * of all JavaBeans&trade;
 298      * has been added to the <code>java.beans</code> package.
 299      * Please see {@link java.beans.XMLEncoder}.
 300      */
 301     @SuppressWarnings("serial")
 302     protected class AccessibleJButton extends AccessibleAbstractButton {
 303 
 304         /**
 305          * Get the role of this object.
 306          *
 307          * @return an instance of AccessibleRole describing the role of the
 308          * object
 309          * @see AccessibleRole
 310          */
 311         public AccessibleRole getAccessibleRole() {
 312             return AccessibleRole.PUSH_BUTTON;
 313         }
 314     } // inner class AccessibleJButton
 315 }