1. /*
  2. * @(#)DefaultButtonModel.java 1.27 01/11/29
  3. *
  4. * Copyright 2002 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 java.awt.image.*;
  11. import java.io.Serializable;
  12. import java.util.EventListener;
  13. import javax.swing.event.*;
  14. /**
  15. * The default implementation of a Button component's data model.
  16. * <p>
  17. * <strong>Warning:</strong>
  18. * Serialized objects of this class will not be compatible with
  19. * future Swing releases. The current serialization support is appropriate
  20. * for short term storage or RMI between applications running the same
  21. * version of Swing. A future release of Swing will provide support for
  22. * long term persistence.
  23. *
  24. * @version 1.27 11/29/01
  25. * @author Jeff Dinkins
  26. */
  27. public class DefaultButtonModel implements ButtonModel, Serializable {
  28. protected int stateMask = 0;
  29. protected String actionCommand = null;
  30. protected ButtonGroup group = null;
  31. protected int mnemonic = 0;
  32. /**
  33. * Only one ChangeEvent is needed per button model instance since the
  34. * event's only state is the source property. The source of events
  35. * generated is always "this".
  36. */
  37. protected transient ChangeEvent changeEvent = null;
  38. protected EventListenerList listenerList = new EventListenerList();
  39. /**
  40. * Constructs a JButtonModel
  41. *
  42. */
  43. public DefaultButtonModel() {
  44. stateMask = 0;
  45. setEnabled(true);
  46. }
  47. /**
  48. * Indicates partial commitment towards choosing the
  49. * button.
  50. */
  51. public final static int ARMED = 1 << 0;
  52. /**
  53. * Indicates that the button has been selected. Only needed for
  54. * certain types of buttons - such as RadioButton or Checkbox.
  55. */
  56. public final static int SELECTED = 1 << 1;
  57. /**
  58. * Indicates that the button has been "pressed"
  59. * (typically, when the mouse is released).
  60. */
  61. public final static int PRESSED = 1 << 2;
  62. /**
  63. * Indicates that the button can be selected by
  64. * an input device (such as a mouse pointer).
  65. */
  66. public final static int ENABLED = 1 << 3;
  67. /**
  68. * Indicates that the mouse is over the button.
  69. */
  70. public final static int ROLLOVER = 1 << 4;
  71. /**
  72. * Sets the actionCommand string that gets sent as part of the
  73. * event when the button is pressed.
  74. *
  75. * @param s the String that identifies the generated event
  76. */
  77. public void setActionCommand(String actionCommand) {
  78. this.actionCommand = actionCommand;
  79. }
  80. /**
  81. * Returns the action command for this button.
  82. *
  83. * @return the String that identifies the generated event
  84. * @see #setActionCommand
  85. */
  86. public String getActionCommand() {
  87. return actionCommand;
  88. }
  89. /**
  90. * Indicates partial commitment towards pressing the
  91. * button.
  92. *
  93. * @return true if the button is armed, and ready to be pressed
  94. * @see #setArmed
  95. */
  96. public boolean isArmed() {
  97. return (stateMask & ARMED) != 0;
  98. }
  99. /**
  100. * Indicates if the button has been selected. Only needed for
  101. * certain types of buttons - such as RadioButton or Checkbox.
  102. *
  103. * @return true if the button is selected
  104. */
  105. public boolean isSelected() {
  106. return (stateMask & SELECTED) != 0;
  107. }
  108. /**
  109. * Indicates if the button can be selected or pressed by
  110. * an input device (such as a mouse pointer). (Checkbox-buttons
  111. * are selected, regular buttons are "pressed".)
  112. *
  113. * @return true if the button is enabled, and therefore
  114. * selectable (or pressable)
  115. */
  116. public boolean isEnabled() {
  117. return (stateMask & ENABLED) != 0;
  118. }
  119. /**
  120. * Indicates if button has been pressed.
  121. *
  122. * @return true if the button has been pressed
  123. */
  124. public boolean isPressed() {
  125. return (stateMask & PRESSED) != 0;
  126. }
  127. /**
  128. * Indicates that the mouse is over the button.
  129. *
  130. * @return true if the mouse is over the button
  131. */
  132. public boolean isRollover() {
  133. return (stateMask & ROLLOVER) != 0;
  134. }
  135. /**
  136. * Marks the button as "armed". If the mouse button is
  137. * released while it is over this item, the button's action event
  138. * fires. If the mouse button is released elsewhere, the
  139. * event does not fire and the button is disarmed.
  140. *
  141. * @param b true to arm the button so it can be selected
  142. */
  143. public void setArmed(boolean b) {
  144. if((isArmed() == b) || !isEnabled()) {
  145. return;
  146. }
  147. if (b) {
  148. stateMask |= ARMED;
  149. } else {
  150. stateMask &= ~ARMED;
  151. }
  152. fireStateChanged();
  153. }
  154. /**
  155. * Enables or disables the button.
  156. *
  157. * @param b true to enable the button
  158. * @see #isEnabled
  159. */
  160. public void setEnabled(boolean b) {
  161. if(isEnabled() == b) {
  162. return;
  163. }
  164. if (b) {
  165. stateMask |= ENABLED;
  166. } else {
  167. stateMask &= ~ENABLED;
  168. }
  169. fireStateChanged();
  170. }
  171. /**
  172. * Selects or deselects the button.
  173. *
  174. * @param b true selects the button,
  175. * false deselects the button.
  176. */
  177. public void setSelected(boolean b) {
  178. if (this.isSelected() == b) {
  179. return;
  180. }
  181. if (b) {
  182. stateMask |= SELECTED;
  183. } else {
  184. stateMask &= ~SELECTED;
  185. }
  186. fireItemStateChanged(
  187. new ItemEvent(this,
  188. ItemEvent.ITEM_STATE_CHANGED,
  189. this,
  190. b ? ItemEvent.SELECTED : ItemEvent.DESELECTED));
  191. fireStateChanged();
  192. }
  193. /**
  194. * Sets the button to pressed or unpressed.
  195. *
  196. * @param b true to set the button to "pressed"
  197. * @see #isPressed
  198. */
  199. public void setPressed(boolean b) {
  200. if((isPressed() == b) || !isEnabled()) {
  201. return;
  202. }
  203. if (b) {
  204. stateMask |= PRESSED;
  205. } else {
  206. stateMask &= ~PRESSED;
  207. }
  208. if(!isPressed() && isArmed()) {
  209. fireActionPerformed(
  210. new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
  211. getActionCommand())
  212. );
  213. }
  214. fireStateChanged();
  215. }
  216. /**
  217. * Sets or clears the button's rollover state
  218. *
  219. * @param b true to turn on rollover
  220. * @see #isRollover
  221. */
  222. public void setRollover(boolean b) {
  223. if((isRollover() == b) || !isEnabled()) {
  224. return;
  225. }
  226. if (b) {
  227. stateMask |= ROLLOVER;
  228. } else {
  229. stateMask &= ~ROLLOVER;
  230. }
  231. fireStateChanged();
  232. }
  233. /**
  234. * Sets the keyboard mnemonic (shortcut key or
  235. * accelerator key) for this button.
  236. *
  237. * @param key an int specifying the accelerator key
  238. */
  239. public void setMnemonic(int key) {
  240. mnemonic = key;
  241. fireStateChanged();
  242. }
  243. /**
  244. * Gets the keyboard mnemonic for this model
  245. *
  246. * @return an int specifying the accelerator key
  247. * @see #setMnemonic
  248. */
  249. public int getMnemonic() {
  250. return mnemonic;
  251. }
  252. /**
  253. * Adds a ChangeListener to the button.
  254. *
  255. * @param l the listener to add
  256. */
  257. public void addChangeListener(ChangeListener l) {
  258. listenerList.add(ChangeListener.class, l);
  259. }
  260. /**
  261. * Removes a ChangeListener from the button.
  262. *
  263. * @param l the listener to remove
  264. */
  265. public void removeChangeListener(ChangeListener l) {
  266. listenerList.remove(ChangeListener.class, l);
  267. }
  268. /*
  269. * Notify all listeners that have registered interest for
  270. * notification on this event type. The event instance
  271. * is lazily created using the parameters passed into
  272. * the fire method.
  273. *
  274. * @see EventListenerList
  275. */
  276. protected void fireStateChanged() {
  277. // Guaranteed to return a non-null array
  278. Object[] listeners = listenerList.getListenerList();
  279. // Process the listeners last to first, notifying
  280. // those that are interested in this event
  281. for (int i = listeners.length-2; i>=0; i-=2) {
  282. if (listeners[i]==ChangeListener.class) {
  283. // Lazily create the event:
  284. if (changeEvent == null)
  285. changeEvent = new ChangeEvent(this);
  286. ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
  287. }
  288. }
  289. }
  290. /**
  291. * Adds an ActionListener to the button.
  292. *
  293. * @param l the listener to add
  294. */
  295. public void addActionListener(ActionListener l) {
  296. listenerList.add(ActionListener.class, l);
  297. }
  298. /**
  299. * Removes an ActionListener from the button.
  300. *
  301. * @param l the listener to remove
  302. */
  303. public void removeActionListener(ActionListener l) {
  304. listenerList.remove(ActionListener.class, l);
  305. }
  306. /*
  307. * Notify all listeners that have registered interest for
  308. * notification on this event type. The event instance
  309. * is lazily created using the parameters passed into
  310. * the fire method.
  311. *
  312. * @param e the ActionEvent to deliver to listeners
  313. * @see EventListenerList
  314. */
  315. protected void fireActionPerformed(ActionEvent e) {
  316. // Guaranteed to return a non-null array
  317. Object[] listeners = listenerList.getListenerList();
  318. // Process the listeners last to first, notifying
  319. // those that are interested in this event
  320. for (int i = listeners.length-2; i>=0; i-=2) {
  321. if (listeners[i]==ActionListener.class) {
  322. // Lazily create the event:
  323. // if (changeEvent == null)
  324. // changeEvent = new ChangeEvent(this);
  325. ((ActionListener)listeners[i+1]).actionPerformed(e);
  326. }
  327. }
  328. }
  329. /**
  330. * Adds an ItemListener to the button.
  331. *
  332. * @param l the listener to add
  333. */
  334. public void addItemListener(ItemListener l) {
  335. listenerList.add(ItemListener.class, l);
  336. }
  337. /**
  338. * Removes an ItemListener from the button.
  339. *
  340. * @param l the listener to remove
  341. */
  342. public void removeItemListener(ItemListener l) {
  343. listenerList.remove(ItemListener.class, l);
  344. }
  345. /*
  346. * Notify all listeners that have registered interest for
  347. * notification on this event type. The event instance
  348. * is lazily created using the parameters passed into
  349. * the fire method.
  350. *
  351. * @param e the ItemEvent to deliver to listeners
  352. * @see EventListenerList
  353. */
  354. protected void fireItemStateChanged(ItemEvent e) {
  355. // Guaranteed to return a non-null array
  356. Object[] listeners = listenerList.getListenerList();
  357. // Process the listeners last to first, notifying
  358. // those that are interested in this event
  359. for (int i = listeners.length-2; i>=0; i-=2) {
  360. if (listeners[i]==ItemListener.class) {
  361. // Lazily create the event:
  362. // if (changeEvent == null)
  363. // changeEvent = new ChangeEvent(this);
  364. ((ItemListener)listeners[i+1]).itemStateChanged(e);
  365. }
  366. }
  367. }
  368. /** Overriden to return null */
  369. public Object[] getSelectedObjects() {
  370. return null;
  371. }
  372. /**
  373. * Identifies the group this button belongs to --
  374. * needed for radio buttons, which are mutually
  375. * exclusive within their group.
  376. *
  377. * @param group the ButtonGroup this button belongs to
  378. */
  379. public void setGroup(ButtonGroup group) {
  380. this.group = group;
  381. }
  382. }