1. /*
  2. * @(#)Button.java 1.51 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 java.awt;
  8. import java.awt.peer.ButtonPeer;
  9. import java.awt.event.*;
  10. import java.io.ObjectOutputStream;
  11. import java.io.ObjectInputStream;
  12. import java.io.IOException;
  13. /**
  14. * This class creates a labeled button. The application can cause
  15. * some action to happen when the button is pushed. This image
  16. * depicts three views of a "<code>Quit</code>" button as it appears
  17. * under the Solaris operating system:
  18. * <p>
  19. * <img src="doc-files/Button-1.gif"
  20. * ALIGN=center HSPACE=10 VSPACE=7>
  21. * <p>
  22. * The first view shows the button as it appears normally.
  23. * The second view shows the button
  24. * when it has input focus. Its outline is darkened to let the
  25. * user know that it is an active object. The third view shows the
  26. * button when the user clicks the mouse over the button, and thus
  27. * requests that an action be performed.
  28. * <p>
  29. * The gesture of clicking on a button with the mouse
  30. * is associated with one instance of <code>ActionEvent</code>,
  31. * which is sent out when the mouse is both pressed and released
  32. * over the button. If an application is interested in knowing
  33. * when the button has been pressed but not released, as a separate
  34. * gesture, it can specialize <code>processMouseEvent</code>,
  35. * or it can register itself as a listener for mouse events by
  36. * calling <code>addMouseListener</code>. Both of these methods are
  37. * defined by <code>Component</code>, the abstract superclass of
  38. * all components.
  39. * <p>
  40. * When a button is pressed and released, AWT sends an instance
  41. * of <code>ActionEvent</code> to the button, by calling
  42. * <code>processEvent</code> on the button. The button's
  43. * <code>processEvent</code> method receives all events
  44. * for the button; it passes an action event along by
  45. * calling its own <code>processActionEvent</code> method.
  46. * The latter method passes the action event on to any action
  47. * listeners that have registered an interest in action
  48. * events generated by this button.
  49. * <p>
  50. * If an application wants to perform some action based on
  51. * a button being pressed and released, it should implement
  52. * <code>ActionListener</code> and register the new listener
  53. * to receive events from this button, by calling the button's
  54. * <code>addActionListener</code> method. The application can
  55. * make use of the button's action command as a messaging protocol.
  56. *
  57. * @version 1.51 11/29/01
  58. * @author Sami Shaio
  59. * @see java.awt.event.ActionEvent
  60. * @see java.awt.event.ActionListener
  61. * @see java.awt.Component#processMouseEvent
  62. * @see java.awt.Component#addMouseListener
  63. * @since JDK1.0
  64. */
  65. public class Button extends Component {
  66. /*
  67. * The button's Label.
  68. * If Label is not specified it will default to "".
  69. * @serial
  70. * @see getLabel()
  71. * @see setLabel()
  72. */
  73. String label;
  74. /*
  75. * The action to be performaed once a button has been
  76. * pressed.
  77. * actionCommand can be null.
  78. * @serial
  79. * @see getActionCommand()
  80. * @see setActionCommand()
  81. */
  82. String actionCommand;
  83. transient ActionListener actionListener;
  84. private static final String base = "button";
  85. private static int nameCounter = 0;
  86. /*
  87. * JDK 1.1 serialVersionUID
  88. */
  89. private static final long serialVersionUID = -8774683716313001058L;
  90. static {
  91. /* ensure that the necessary native libraries are loaded */
  92. Toolkit.loadLibraries();
  93. initIDs();
  94. }
  95. /**
  96. * Initialize JNI field and method IDs for fields that may be
  97. accessed from C.
  98. */
  99. private static native void initIDs();
  100. /**
  101. * Constructs a Button with no label.
  102. */
  103. public Button() {
  104. this("");
  105. }
  106. /**
  107. * Constructs a Button with the specified label.
  108. * @param label A string label for the button.
  109. */
  110. public Button(String label) {
  111. this.label = label;
  112. }
  113. /**
  114. * Construct a name for this component. Called by getName() when the
  115. * name is null.
  116. */
  117. String constructComponentName() {
  118. synchronized (getClass()) {
  119. return base + nameCounter++;
  120. }
  121. }
  122. /**
  123. * Creates the peer of the button. The button's peer allows the
  124. * application to change the look of the button without changing
  125. * its functionality.
  126. * @see java.awt.Toolkit#createButton(java.awt.Button)
  127. * @see java.awt.Component#getToolkit()
  128. */
  129. public void addNotify() {
  130. synchronized(getTreeLock()) {
  131. if (peer == null)
  132. peer = getToolkit().createButton(this);
  133. super.addNotify();
  134. }
  135. }
  136. /**
  137. * Gets the label of this button.
  138. * @return the button's label, or <code>null</code>
  139. * if the button has no label.
  140. * @see java.awt.Button#setLabel
  141. */
  142. public String getLabel() {
  143. return label;
  144. }
  145. /**
  146. * Sets the button's label to be the specified string.
  147. * @param label the new label, or <code>null</code>
  148. * if the button has no label.
  149. * @see java.awt.Button#getLabel
  150. */
  151. public void setLabel(String label) {
  152. boolean testvalid = false;
  153. synchronized (this) {
  154. if (label != this.label && (this.label == null ||
  155. !this.label.equals(label))) {
  156. this.label = label;
  157. ButtonPeer peer = (ButtonPeer)this.peer;
  158. if (peer != null) {
  159. peer.setLabel(label);
  160. }
  161. testvalid = true;
  162. }
  163. }
  164. // This could change the preferred size of the Component.
  165. if (testvalid && valid) {
  166. invalidate();
  167. }
  168. }
  169. /**
  170. * Sets the command name for the action event fired
  171. * by this button. By default this action command is
  172. * set to match the label of the button.
  173. * @param command A string used to set the button's
  174. * action command.
  175. * If the string is <code>null</code> then the action command
  176. * is set to match the label of the button.
  177. * @see java.awt.event.ActionEvent
  178. * @since JDK1.1
  179. */
  180. public void setActionCommand(String command) {
  181. actionCommand = command;
  182. }
  183. /**
  184. * Returns the command name of the action event fired by this button.
  185. * If the command name is <code>null</code> (default) then this method
  186. * returns the label of the button.
  187. */
  188. public String getActionCommand() {
  189. return (actionCommand == null? label : actionCommand);
  190. }
  191. /**
  192. * Adds the specified action listener to receive action events from
  193. * this button. Action events occur when a user presses or releases
  194. * the mouse over this button.
  195. * If l is null, no exception is thrown and no action is performed.
  196. *
  197. * @param l the action listener
  198. * @see java.awt.event.ActionListener
  199. * @see java.awt.Button#removeActionListener
  200. * @since JDK1.1
  201. */
  202. public synchronized void addActionListener(ActionListener l) {
  203. if (l == null) {
  204. return;
  205. }
  206. actionListener = AWTEventMulticaster.add(actionListener, l);
  207. newEventsOnly = true;
  208. }
  209. /**
  210. * Removes the specified action listener so that it no longer
  211. * receives action events from this button. Action events occur
  212. * when a user presses or releases the mouse over this button.
  213. * If l is null, no exception is thrown and no action is performed.
  214. *
  215. * @param l the action listener
  216. * @see java.awt.event.ActionListener
  217. * @see java.awt.Button#addActionListener
  218. * @since JDK1.1
  219. */
  220. public synchronized void removeActionListener(ActionListener l) {
  221. if (l == null) {
  222. return;
  223. }
  224. actionListener = AWTEventMulticaster.remove(actionListener, l);
  225. }
  226. // REMIND: remove when filtering is done at lower level
  227. boolean eventEnabled(AWTEvent e) {
  228. if (e.id == ActionEvent.ACTION_PERFORMED) {
  229. if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
  230. actionListener != null) {
  231. return true;
  232. }
  233. return false;
  234. }
  235. return super.eventEnabled(e);
  236. }
  237. /**
  238. * Processes events on this button. If an event is
  239. * an instance of <code>ActionEvent</code>, this method invokes
  240. * the <code>processActionEvent</code> method. Otherwise,
  241. * it invokes <code>processEvent</code> on the superclass.
  242. * @param e the event.
  243. * @see java.awt.event.ActionEvent
  244. * @see java.awt.Button#processActionEvent
  245. * @since JDK1.1
  246. */
  247. protected void processEvent(AWTEvent e) {
  248. if (e instanceof ActionEvent) {
  249. processActionEvent((ActionEvent)e);
  250. return;
  251. }
  252. super.processEvent(e);
  253. }
  254. /**
  255. * Processes action events occurring on this button
  256. * by dispatching them to any registered
  257. * <code>ActionListener</code> objects.
  258. * <p>
  259. * This method is not called unless action events are
  260. * enabled for this button. Action events are enabled
  261. * when one of the following occurs:
  262. * <p><ul>
  263. * <li>An <code>ActionListener</code> object is registered
  264. * via <code>addActionListener</code>.
  265. * <li>Action events are enabled via <code>enableEvents</code>.
  266. * </ul>
  267. * @param e the action event.
  268. * @see java.awt.event.ActionListener
  269. * @see java.awt.Button#addActionListener
  270. * @see java.awt.Component#enableEvents
  271. * @since JDK1.1
  272. */
  273. protected void processActionEvent(ActionEvent e) {
  274. if (actionListener != null) {
  275. actionListener.actionPerformed(e);
  276. }
  277. }
  278. /**
  279. * Returns the parameter string representing the state of this
  280. * button. This string is useful for debugging.
  281. * @return the parameter string of this button.
  282. */
  283. protected String paramString() {
  284. return super.paramString() + ",label=" + label;
  285. }
  286. /* Serialization support.
  287. */
  288. /*
  289. * Button Serial Data Version.
  290. * @serial
  291. */
  292. private int buttonSerializedDataVersion = 1;
  293. /**
  294. * Writes default serializable fields to stream. Writes
  295. * a list of serializable ItemListener(s) as optional data.
  296. * The non-serializable ItemListner(s) are detected and
  297. * no attempt is made to serialize them.
  298. *
  299. * @serialData Null terminated sequence of 0 or more pairs.
  300. * The pair consists of a String and Object.
  301. * The String indicates the type of object and
  302. * is one of the following :
  303. * itemListenerK indicating and ItemListener object.
  304. *
  305. * @see AWTEventMulticaster.save(ObjectOutputStream, String, EventListener)
  306. * @see java.awt.Component.itemListenerK
  307. */
  308. private void writeObject(ObjectOutputStream s)
  309. throws IOException
  310. {
  311. s.defaultWriteObject();
  312. AWTEventMulticaster.save(s, actionListenerK, actionListener);
  313. s.writeObject(null);
  314. }
  315. /*
  316. * Read the ObjectInputStream and if it isnt null
  317. * add a listener to receive item events fired
  318. * by the button.
  319. * Unrecognised keys or values will be Ignored.
  320. * @serial
  321. * @see removeActionListener()
  322. * @see addActionListener()
  323. */
  324. private void readObject(ObjectInputStream s)
  325. throws ClassNotFoundException, IOException
  326. {
  327. s.defaultReadObject();
  328. Object keyOrNull;
  329. while(null != (keyOrNull = s.readObject())) {
  330. String key = ((String)keyOrNull).intern();
  331. if (actionListenerK == key)
  332. addActionListener((ActionListener)(s.readObject()));
  333. else // skip value for unrecognized key
  334. s.readObject();
  335. }
  336. }
  337. }