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