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