1 /* 2 * Copyright (c) 1997, 2006, 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.awt.*; 28 import java.awt.event.*; 29 30 import javax.swing.event.*; 31 import javax.swing.plaf.*; 32 import javax.accessibility.*; 33 34 import java.io.ObjectOutputStream; 35 import java.io.ObjectInputStream; 36 import java.io.IOException; 37 38 39 /** 40 * An implementation of a two-state button. 41 * The <code>JRadioButton</code> and <code>JCheckBox</code> classes 42 * are subclasses of this class. 43 * For information on using them see 44 * <a 45 href="http://docs.oracle.com/javase/tutorial/uiswing/components/button.html">How to Use Buttons, Check Boxes, and Radio Buttons</a>, 46 * a section in <em>The Java Tutorial</em>. 47 * <p> 48 * Buttons can be configured, and to some degree controlled, by 49 * <code><a href="Action.html">Action</a></code>s. Using an 50 * <code>Action</code> with a button has many benefits beyond directly 51 * configuring a button. Refer to <a href="Action.html#buttonActions"> 52 * Swing Components Supporting <code>Action</code></a> for more 53 * details, and you can find more information in <a 54 * href="http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html">How 55 * to Use Actions</a>, a section in <em>The Java Tutorial</em>. 56 * <p> 57 * <strong>Warning:</strong> Swing is not thread safe. For more 58 * information see <a 59 * href="package-summary.html#threading">Swing's Threading 60 * Policy</a>. 61 * <p> 62 * <strong>Warning:</strong> 63 * Serialized objects of this class will not be compatible with 64 * future Swing releases. The current serialization support is 65 * appropriate for short term storage or RMI between applications running 66 * the same version of Swing. As of 1.4, support for long term storage 67 * of all JavaBeans<sup><font size="-2">TM</font></sup> 68 * has been added to the <code>java.beans</code> package. 69 * Please see {@link java.beans.XMLEncoder}. 70 * 71 * @beaninfo 72 * attribute: isContainer false 73 * description: An implementation of a two-state button. 74 * 75 * @see JRadioButton 76 * @see JCheckBox 77 * @author Jeff Dinkins 78 */ 79 public class JToggleButton extends AbstractButton implements Accessible { 80 81 /** 82 * @see #getUIClassID 83 * @see #readObject 84 */ 85 private static final String uiClassID = "ToggleButtonUI"; 86 87 /** 88 * Creates an initially unselected toggle button 89 * without setting the text or image. 90 */ 91 public JToggleButton () { 92 this(null, null, false); 93 } 94 95 /** 96 * Creates an initially unselected toggle button 97 * with the specified image but no text. 98 * 99 * @param icon the image that the button should display 100 */ 101 public JToggleButton(Icon icon) { 102 this(null, icon, false); 103 } 104 105 /** 106 * Creates a toggle button with the specified image 107 * and selection state, but no text. 108 * 109 * @param icon the image that the button should display 110 * @param selected if true, the button is initially selected; 111 * otherwise, the button is initially unselected 112 */ 113 public JToggleButton(Icon icon, boolean selected) { 114 this(null, icon, selected); 115 } 116 117 /** 118 * Creates an unselected toggle button with the specified text. 119 * 120 * @param text the string displayed on the toggle button 121 */ 122 public JToggleButton (String text) { 123 this(text, null, false); 124 } 125 126 /** 127 * Creates a toggle button with the specified text 128 * and selection state. 129 * 130 * @param text the string displayed on the toggle button 131 * @param selected if true, the button is initially selected; 132 * otherwise, the button is initially unselected 133 */ 134 public JToggleButton (String text, boolean selected) { 135 this(text, null, selected); 136 } 137 138 /** 139 * Creates a toggle button where properties are taken from the 140 * Action supplied. 141 * 142 * @since 1.3 143 */ 144 public JToggleButton(Action a) { 145 this(); 146 setAction(a); 147 } 148 149 /** 150 * Creates a toggle button that has the specified text and image, 151 * and that is initially unselected. 152 * 153 * @param text the string displayed on the button 154 * @param icon the image that the button should display 155 */ 156 public JToggleButton(String text, Icon icon) { 157 this(text, icon, false); 158 } 159 160 /** 161 * Creates a toggle button with the specified text, image, and 162 * selection state. 163 * 164 * @param text the text of the toggle button 165 * @param icon the image that the button should display 166 * @param selected if true, the button is initially selected; 167 * otherwise, the button is initially unselected 168 */ 169 public JToggleButton (String text, Icon icon, boolean selected) { 170 // Create the model 171 setModel(new ToggleButtonModel()); 172 173 model.setSelected(selected); 174 175 // initialize 176 init(text, icon); 177 } 178 179 /** 180 * Resets the UI property to a value from the current look and feel. 181 * 182 * @see JComponent#updateUI 183 */ 184 public void updateUI() { 185 setUI((ButtonUI)UIManager.getUI(this)); 186 } 187 188 /** 189 * Returns a string that specifies the name of the l&f class 190 * that renders this component. 191 * 192 * @return String "ToggleButtonUI" 193 * @see JComponent#getUIClassID 194 * @see UIDefaults#getUI 195 * @beaninfo 196 * description: A string that specifies the name of the L&F class 197 */ 198 public String getUIClassID() { 199 return uiClassID; 200 } 201 202 203 /** 204 * Overriden to return true, JToggleButton supports 205 * the selected state. 206 */ 207 boolean shouldUpdateSelectedStateFromAction() { 208 return true; 209 } 210 211 // ********************************************************************* 212 213 /** 214 * The ToggleButton model 215 * <p> 216 * <strong>Warning:</strong> 217 * Serialized objects of this class will not be compatible with 218 * future Swing releases. The current serialization support is 219 * appropriate for short term storage or RMI between applications running 220 * the same version of Swing. As of 1.4, support for long term storage 221 * of all JavaBeans<sup><font size="-2">TM</font></sup> 222 * has been added to the <code>java.beans</code> package. 223 * Please see {@link java.beans.XMLEncoder}. 224 */ 225 public static class ToggleButtonModel extends DefaultButtonModel { 226 227 /** 228 * Creates a new ToggleButton Model 229 */ 230 public ToggleButtonModel () { 231 } 232 233 /** 234 * Checks if the button is selected. 235 */ 236 public boolean isSelected() { 237 // if(getGroup() != null) { 238 // return getGroup().isSelected(this); 239 // } else { 240 return (stateMask & SELECTED) != 0; 241 // } 242 } 243 244 245 /** 246 * Sets the selected state of the button. 247 * @param b true selects the toggle button, 248 * false deselects the toggle button. 249 */ 250 public void setSelected(boolean b) { 251 ButtonGroup group = getGroup(); 252 if (group != null) { 253 // use the group model instead 254 group.setSelected(this, b); 255 b = group.isSelected(this); 256 } 257 258 if (isSelected() == b) { 259 return; 260 } 261 262 if (b) { 263 stateMask |= SELECTED; 264 } else { 265 stateMask &= ~SELECTED; 266 } 267 268 // Send ChangeEvent 269 fireStateChanged(); 270 271 // Send ItemEvent 272 fireItemStateChanged( 273 new ItemEvent(this, 274 ItemEvent.ITEM_STATE_CHANGED, 275 this, 276 this.isSelected() ? ItemEvent.SELECTED : ItemEvent.DESELECTED)); 277 278 } 279 280 /** 281 * Sets the pressed state of the toggle button. 282 */ 283 public void setPressed(boolean b) { 284 if ((isPressed() == b) || !isEnabled()) { 285 return; 286 } 287 288 if (b == false && isArmed()) { 289 setSelected(!this.isSelected()); 290 } 291 292 if (b) { 293 stateMask |= PRESSED; 294 } else { 295 stateMask &= ~PRESSED; 296 } 297 298 fireStateChanged(); 299 300 if(!isPressed() && isArmed()) { 301 int modifiers = 0; 302 AWTEvent currentEvent = EventQueue.getCurrentEvent(); 303 if (currentEvent instanceof InputEvent) { 304 modifiers = ((InputEvent)currentEvent).getModifiers(); 305 } else if (currentEvent instanceof ActionEvent) { 306 modifiers = ((ActionEvent)currentEvent).getModifiers(); 307 } 308 fireActionPerformed( 309 new ActionEvent(this, ActionEvent.ACTION_PERFORMED, 310 getActionCommand(), 311 EventQueue.getMostRecentEventTime(), 312 modifiers)); 313 } 314 315 } 316 } 317 318 319 /** 320 * See readObject() and writeObject() in JComponent for more 321 * information about serialization in Swing. 322 */ 323 private void writeObject(ObjectOutputStream s) throws IOException { 324 s.defaultWriteObject(); 325 if (getUIClassID().equals(uiClassID)) { 326 byte count = JComponent.getWriteObjCounter(this); 327 JComponent.setWriteObjCounter(this, --count); 328 if (count == 0 && ui != null) { 329 ui.installUI(this); 330 } 331 } 332 } 333 334 335 /** 336 * Returns a string representation of this JToggleButton. This method 337 * is intended to be used only for debugging purposes, and the 338 * content and format of the returned string may vary between 339 * implementations. The returned string may be empty but may not 340 * be <code>null</code>. 341 * 342 * @return a string representation of this JToggleButton. 343 */ 344 protected String paramString() { 345 return super.paramString(); 346 } 347 348 349 ///////////////// 350 // Accessibility support 351 //////////////// 352 353 /** 354 * Gets the AccessibleContext associated with this JToggleButton. 355 * For toggle buttons, the AccessibleContext takes the form of an 356 * AccessibleJToggleButton. 357 * A new AccessibleJToggleButton instance is created if necessary. 358 * 359 * @return an AccessibleJToggleButton that serves as the 360 * AccessibleContext of this JToggleButton 361 * @beaninfo 362 * expert: true 363 * description: The AccessibleContext associated with this ToggleButton. 364 */ 365 public AccessibleContext getAccessibleContext() { 366 if (accessibleContext == null) { 367 accessibleContext = new AccessibleJToggleButton(); 368 } 369 return accessibleContext; 370 } 371 372 /** 373 * This class implements accessibility support for the 374 * <code>JToggleButton</code> class. It provides an implementation of the 375 * Java Accessibility API appropriate to toggle button user-interface 376 * elements. 377 * <p> 378 * <strong>Warning:</strong> 379 * Serialized objects of this class will not be compatible with 380 * future Swing releases. The current serialization support is 381 * appropriate for short term storage or RMI between applications running 382 * the same version of Swing. As of 1.4, support for long term storage 383 * of all JavaBeans<sup><font size="-2">TM</font></sup> 384 * has been added to the <code>java.beans</code> package. 385 * Please see {@link java.beans.XMLEncoder}. 386 */ 387 protected class AccessibleJToggleButton extends AccessibleAbstractButton 388 implements ItemListener { 389 390 public AccessibleJToggleButton() { 391 super(); 392 JToggleButton.this.addItemListener(this); 393 } 394 395 /** 396 * Fire accessible property change events when the state of the 397 * toggle button changes. 398 */ 399 public void itemStateChanged(ItemEvent e) { 400 JToggleButton tb = (JToggleButton) e.getSource(); 401 if (JToggleButton.this.accessibleContext != null) { 402 if (tb.isSelected()) { 403 JToggleButton.this.accessibleContext.firePropertyChange( 404 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 405 null, AccessibleState.CHECKED); 406 } else { 407 JToggleButton.this.accessibleContext.firePropertyChange( 408 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 409 AccessibleState.CHECKED, null); 410 } 411 } 412 } 413 414 /** 415 * Get the role of this object. 416 * 417 * @return an instance of AccessibleRole describing the role of the 418 * object 419 */ 420 public AccessibleRole getAccessibleRole() { 421 return AccessibleRole.TOGGLE_BUTTON; 422 } 423 } // inner class AccessibleJToggleButton 424 }