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