1. /*
  2. * @(#)JToggleButton.java 1.57 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import javax.swing.event.*;
  11. import javax.swing.plaf.*;
  12. import javax.accessibility.*;
  13. import java.io.ObjectOutputStream;
  14. import java.io.ObjectInputStream;
  15. import java.io.IOException;
  16. /**
  17. * An implementation of a two-state button.
  18. * The <code>JRadioButton</code> and <code>JCheckBox</code> classes
  19. * are subclasses of this class.
  20. * For information on using them see
  21. * <a
  22. href="http://java.sun.com/docs/books/tutorial/uiswing/components/button.html">How to Use Buttons, Check Boxes, and Radio Buttons</a>,
  23. * a section in <em>The Java Tutorial</em>.
  24. * <p>
  25. * For the keyboard keys used by this component in the standard Look and
  26. * Feel (L&F) renditions, see the
  27. * <a href="doc-files/Key-Index.html#JToggleButton"><code>JToggleButton</code> key assignments</a>.
  28. * <p>
  29. * <strong>Warning:</strong>
  30. * Serialized objects of this class will not be compatible with
  31. * future Swing releases. The current serialization support is
  32. * appropriate for short term storage or RMI between applications running
  33. * the same version of Swing. As of 1.4, support for long term storage
  34. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  35. * has been added to the <code>java.beans</code> package.
  36. * Please see {@link java.beans.XMLEncoder}.
  37. *
  38. * @beaninfo
  39. * attribute: isContainer false
  40. * description: An implementation of a two-state button.
  41. *
  42. * @see JRadioButton
  43. * @see JCheckBox
  44. * @version 1.57 01/23/03
  45. * @author Jeff Dinkins
  46. */
  47. public class JToggleButton extends AbstractButton implements Accessible {
  48. /**
  49. * @see #getUIClassID
  50. * @see #readObject
  51. */
  52. private static final String uiClassID = "ToggleButtonUI";
  53. /**
  54. * Creates an initially unselected toggle button
  55. * without setting the text or image.
  56. */
  57. public JToggleButton () {
  58. this(null, null, false);
  59. }
  60. /**
  61. * Creates an initially unselected toggle button
  62. * with the specified image but no text.
  63. *
  64. * @param icon the image that the button should display
  65. */
  66. public JToggleButton(Icon icon) {
  67. this(null, icon, false);
  68. }
  69. /**
  70. * Creates a toggle button with the specified image
  71. * and selection state, but no text.
  72. *
  73. * @param icon the image that the button should display
  74. * @param selected if true, the button is initially selected;
  75. * otherwise, the button is initially unselected
  76. */
  77. public JToggleButton(Icon icon, boolean selected) {
  78. this(null, icon, selected);
  79. }
  80. /**
  81. * Creates an unselected toggle button with the specified text.
  82. *
  83. * @param text the string displayed on the toggle button
  84. */
  85. public JToggleButton (String text) {
  86. this(text, null, false);
  87. }
  88. /**
  89. * Creates a toggle button with the specified text
  90. * and selection state.
  91. *
  92. * @param text the string displayed on the toggle button
  93. * @param selected if true, the button is initially selected;
  94. * otherwise, the button is initially unselected
  95. */
  96. public JToggleButton (String text, boolean selected) {
  97. this(text, null, selected);
  98. }
  99. /**
  100. * Creates a toggle button where properties are taken from the
  101. * Action supplied.
  102. *
  103. * @since 1.3
  104. */
  105. public JToggleButton(Action a) {
  106. this();
  107. setAction(a);
  108. }
  109. /**
  110. * Creates a toggle button that has the specified text and image,
  111. * and that is initially unselected.
  112. *
  113. * @param text the string displayed on the button
  114. * @param icon the image that the button should display
  115. */
  116. public JToggleButton(String text, Icon icon) {
  117. this(text, icon, false);
  118. }
  119. /**
  120. * Creates a toggle button with the specified text, image, and
  121. * selection state.
  122. *
  123. * @param text the text of the toggle button
  124. * @param icon the image that the button should display
  125. * @param selected if true, the button is initially selected;
  126. * otherwise, the button is initially unselected
  127. */
  128. public JToggleButton (String text, Icon icon, boolean selected) {
  129. // Create the model
  130. setModel(new ToggleButtonModel());
  131. model.setSelected(selected);
  132. // initialize
  133. init(text, icon);
  134. }
  135. /**
  136. * Resets the UI property to a value from the current look and feel.
  137. *
  138. * @see JComponent#updateUI
  139. */
  140. public void updateUI() {
  141. setUI((ButtonUI)UIManager.getUI(this));
  142. }
  143. /**
  144. * Returns a string that specifies the name of the l&f class
  145. * that renders this component.
  146. *
  147. * @return String "ToggleButtonUI"
  148. * @see JComponent#getUIClassID
  149. * @see UIDefaults#getUI
  150. * @beaninfo
  151. * description: A string that specifies the name of the L&F class
  152. */
  153. public String getUIClassID() {
  154. return uiClassID;
  155. }
  156. // *********************************************************************
  157. /**
  158. * The ToggleButton model
  159. * <p>
  160. * <strong>Warning:</strong>
  161. * Serialized objects of this class will not be compatible with
  162. * future Swing releases. The current serialization support is
  163. * appropriate for short term storage or RMI between applications running
  164. * the same version of Swing. As of 1.4, support for long term storage
  165. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  166. * has been added to the <code>java.beans</code> package.
  167. * Please see {@link java.beans.XMLEncoder}.
  168. */
  169. public static class ToggleButtonModel extends DefaultButtonModel {
  170. /**
  171. * Creates a new ToggleButton Model
  172. */
  173. public ToggleButtonModel () {
  174. }
  175. /**
  176. * Checks if the button is selected.
  177. */
  178. public boolean isSelected() {
  179. // if(getGroup() != null) {
  180. // return getGroup().isSelected(this);
  181. // } else {
  182. return (stateMask & SELECTED) != 0;
  183. // }
  184. }
  185. /**
  186. * Sets the selected state of the button.
  187. * @param b true selects the toggle button,
  188. * false deselects the toggle button.
  189. */
  190. public void setSelected(boolean b) {
  191. ButtonGroup group = getGroup();
  192. if (group != null) {
  193. // use the group model instead
  194. group.setSelected(this, b);
  195. b = group.isSelected(this);
  196. }
  197. if (isSelected() == b) {
  198. return;
  199. }
  200. if (b) {
  201. stateMask |= SELECTED;
  202. } else {
  203. stateMask &= ~SELECTED;
  204. }
  205. // Send ChangeEvent
  206. fireStateChanged();
  207. // Send ItemEvent
  208. fireItemStateChanged(
  209. new ItemEvent(this,
  210. ItemEvent.ITEM_STATE_CHANGED,
  211. this,
  212. this.isSelected() ? ItemEvent.SELECTED : ItemEvent.DESELECTED));
  213. }
  214. /**
  215. * Sets the pressed state of the toggle button.
  216. */
  217. public void setPressed(boolean b) {
  218. if ((isPressed() == b) || !isEnabled()) {
  219. return;
  220. }
  221. if (b == false && isArmed()) {
  222. setSelected(!this.isSelected());
  223. }
  224. if (b) {
  225. stateMask |= PRESSED;
  226. } else {
  227. stateMask &= ~PRESSED;
  228. }
  229. fireStateChanged();
  230. if(!isPressed() && isArmed()) {
  231. int modifiers = 0;
  232. AWTEvent currentEvent = EventQueue.getCurrentEvent();
  233. if (currentEvent instanceof InputEvent) {
  234. modifiers = ((InputEvent)currentEvent).getModifiers();
  235. } else if (currentEvent instanceof ActionEvent) {
  236. modifiers = ((ActionEvent)currentEvent).getModifiers();
  237. }
  238. fireActionPerformed(
  239. new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
  240. getActionCommand(),
  241. EventQueue.getMostRecentEventTime(),
  242. modifiers));
  243. }
  244. }
  245. }
  246. /**
  247. * See readObject() and writeObject() in JComponent for more
  248. * information about serialization in Swing.
  249. */
  250. private void writeObject(ObjectOutputStream s) throws IOException {
  251. s.defaultWriteObject();
  252. if (getUIClassID().equals(uiClassID)) {
  253. byte count = JComponent.getWriteObjCounter(this);
  254. JComponent.setWriteObjCounter(this, --count);
  255. if (count == 0 && ui != null) {
  256. ui.installUI(this);
  257. }
  258. }
  259. }
  260. /**
  261. * Returns a string representation of this JToggleButton. This method
  262. * is intended to be used only for debugging purposes, and the
  263. * content and format of the returned string may vary between
  264. * implementations. The returned string may be empty but may not
  265. * be <code>null</code>.
  266. *
  267. * @return a string representation of this JToggleButton.
  268. */
  269. protected String paramString() {
  270. return super.paramString();
  271. }
  272. /////////////////
  273. // Accessibility support
  274. ////////////////
  275. /**
  276. * Gets the AccessibleContext associated with this JToggleButton.
  277. * For toggle buttons, the AccessibleContext takes the form of an
  278. * AccessibleJToggleButton.
  279. * A new AccessibleJToggleButton instance is created if necessary.
  280. *
  281. * @return an AccessibleJToggleButton that serves as the
  282. * AccessibleContext of this JToggleButton
  283. * @beaninfo
  284. * expert: true
  285. * description: The AccessibleContext associated with this ToggleButton.
  286. */
  287. public AccessibleContext getAccessibleContext() {
  288. if (accessibleContext == null) {
  289. accessibleContext = new AccessibleJToggleButton();
  290. }
  291. return accessibleContext;
  292. }
  293. /**
  294. * This class implements accessibility support for the
  295. * <code>JToggleButton</code> class. It provides an implementation of the
  296. * Java Accessibility API appropriate to toggle button user-interface
  297. * elements.
  298. * <p>
  299. * <strong>Warning:</strong>
  300. * Serialized objects of this class will not be compatible with
  301. * future Swing releases. The current serialization support is
  302. * appropriate for short term storage or RMI between applications running
  303. * the same version of Swing. As of 1.4, support for long term storage
  304. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  305. * has been added to the <code>java.beans</code> package.
  306. * Please see {@link java.beans.XMLEncoder}.
  307. */
  308. protected class AccessibleJToggleButton extends AccessibleAbstractButton
  309. implements ItemListener {
  310. public AccessibleJToggleButton() {
  311. super();
  312. JToggleButton.this.addItemListener(this);
  313. }
  314. /**
  315. * Fire accessible property change events when the state of the
  316. * toggle button changes.
  317. */
  318. public void itemStateChanged(ItemEvent e) {
  319. JToggleButton tb = (JToggleButton) e.getSource();
  320. if (JToggleButton.this.accessibleContext != null) {
  321. if (tb.isSelected()) {
  322. JToggleButton.this.accessibleContext.firePropertyChange(
  323. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  324. null, AccessibleState.CHECKED);
  325. } else {
  326. JToggleButton.this.accessibleContext.firePropertyChange(
  327. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  328. AccessibleState.CHECKED, null);
  329. }
  330. }
  331. }
  332. /**
  333. * Get the role of this object.
  334. *
  335. * @return an instance of AccessibleRole describing the role of the
  336. * object
  337. */
  338. public AccessibleRole getAccessibleRole() {
  339. return AccessibleRole.TOGGLE_BUTTON;
  340. }
  341. } // inner class AccessibleJToggleButton
  342. }