1. /*
  2. * @(#)BasicButtonListener.java 1.63 04/01/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.plaf.basic;
  8. import sun.swing.DefaultLookup;
  9. import sun.swing.UIAction;
  10. import java.awt.*;
  11. import java.awt.event.*;
  12. import java.beans.*;
  13. import javax.swing.*;
  14. import javax.swing.event.*;
  15. import javax.swing.plaf.ActionMapUIResource;
  16. import javax.swing.plaf.ButtonUI;
  17. import javax.swing.plaf.ComponentInputMapUIResource;
  18. /**
  19. * Button Listener
  20. *
  21. * @version 1.63 01/19/04
  22. * @author Jeff Dinkins
  23. * @author Arnaud Weber (keyboard UI support)
  24. */
  25. public class BasicButtonListener implements MouseListener, MouseMotionListener,
  26. FocusListener, ChangeListener, PropertyChangeListener
  27. {
  28. private long lastPressedTimestamp = -1;
  29. private boolean shouldDiscardRelease = false;
  30. /**
  31. * Populates Buttons actions.
  32. */
  33. static void loadActionMap(LazyActionMap map) {
  34. map.put(new Actions(Actions.PRESS));
  35. map.put(new Actions(Actions.RELEASE));
  36. }
  37. public BasicButtonListener(AbstractButton b) {
  38. }
  39. public void propertyChange(PropertyChangeEvent e) {
  40. String prop = e.getPropertyName();
  41. if(prop == AbstractButton.MNEMONIC_CHANGED_PROPERTY) {
  42. updateMnemonicBinding((AbstractButton)e.getSource());
  43. }
  44. else if(prop == AbstractButton.CONTENT_AREA_FILLED_CHANGED_PROPERTY) {
  45. checkOpacity((AbstractButton) e.getSource() );
  46. }
  47. else if(prop == AbstractButton.TEXT_CHANGED_PROPERTY ||
  48. "font" == prop || "foreground" == prop) {
  49. AbstractButton b = (AbstractButton) e.getSource();
  50. BasicHTML.updateRenderer(b, b.getText());
  51. }
  52. }
  53. protected void checkOpacity(AbstractButton b) {
  54. b.setOpaque( b.isContentAreaFilled() );
  55. }
  56. /**
  57. * Register default key actions: pressing space to "click" a
  58. * button and registring the keyboard mnemonic (if any).
  59. */
  60. public void installKeyboardActions(JComponent c) {
  61. AbstractButton b = (AbstractButton)c;
  62. // Update the mnemonic binding.
  63. updateMnemonicBinding(b);
  64. LazyActionMap.installLazyActionMap(c, BasicButtonListener.class,
  65. "Button.actionMap");
  66. InputMap km = getInputMap(JComponent.WHEN_FOCUSED, c);
  67. SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, km);
  68. }
  69. /**
  70. * Unregister's default key actions
  71. */
  72. public void uninstallKeyboardActions(JComponent c) {
  73. SwingUtilities.replaceUIInputMap(c, JComponent.
  74. WHEN_IN_FOCUSED_WINDOW, null);
  75. SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, null);
  76. SwingUtilities.replaceUIActionMap(c, null);
  77. }
  78. /**
  79. * Returns the InputMap for condition <code>condition</code>. Called as
  80. * part of <code>installKeyboardActions</code>.
  81. */
  82. InputMap getInputMap(int condition, JComponent c) {
  83. if (condition == JComponent.WHEN_FOCUSED) {
  84. BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
  85. ((AbstractButton)c).getUI(), BasicButtonUI.class);
  86. if (ui != null) {
  87. return (InputMap)DefaultLookup.get(
  88. c, ui, ui.getPropertyPrefix() + "focusInputMap");
  89. }
  90. }
  91. return null;
  92. }
  93. /**
  94. * Resets the binding for the mnemonic in the WHEN_IN_FOCUSED_WINDOW
  95. * UI InputMap.
  96. */
  97. void updateMnemonicBinding(AbstractButton b) {
  98. int m = b.getMnemonic();
  99. if(m != 0) {
  100. InputMap map = SwingUtilities.getUIInputMap(
  101. b, JComponent.WHEN_IN_FOCUSED_WINDOW);
  102. if (map == null) {
  103. map = new ComponentInputMapUIResource(b);
  104. SwingUtilities.replaceUIInputMap(b,
  105. JComponent.WHEN_IN_FOCUSED_WINDOW, map);
  106. }
  107. map.clear();
  108. map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, false),
  109. "pressed");
  110. map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, true),
  111. "released");
  112. map.put(KeyStroke.getKeyStroke(m, 0, true), "released");
  113. }
  114. else {
  115. InputMap map = SwingUtilities.getUIInputMap(b, JComponent.
  116. WHEN_IN_FOCUSED_WINDOW);
  117. if (map != null) {
  118. map.clear();
  119. }
  120. }
  121. }
  122. public void stateChanged(ChangeEvent e) {
  123. AbstractButton b = (AbstractButton) e.getSource();
  124. b.repaint();
  125. }
  126. public void focusGained(FocusEvent e) {
  127. AbstractButton b = (AbstractButton) e.getSource();
  128. if (b instanceof JButton && ((JButton)b).isDefaultCapable()) {
  129. JRootPane root = b.getRootPane();
  130. if (root != null) {
  131. BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
  132. ((AbstractButton)b).getUI(), BasicButtonUI.class);
  133. if (ui != null && DefaultLookup.getBoolean(b, ui,
  134. ui.getPropertyPrefix() +
  135. "defaultButtonFollowsFocus", true)) {
  136. root.putClientProperty("temporaryDefaultButton", b);
  137. root.setDefaultButton((JButton)b);
  138. root.putClientProperty("temporaryDefaultButton", null);
  139. }
  140. }
  141. }
  142. b.repaint();
  143. }
  144. public void focusLost(FocusEvent e) {
  145. AbstractButton b = (AbstractButton) e.getSource();
  146. JRootPane root = b.getRootPane();
  147. if (root != null) {
  148. JButton initialDefault = (JButton)root.getClientProperty("initialDefaultButton");
  149. if (b != initialDefault) {
  150. BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
  151. ((AbstractButton)b).getUI(), BasicButtonUI.class);
  152. if (ui != null && DefaultLookup.getBoolean(b, ui,
  153. ui.getPropertyPrefix() +
  154. "defaultButtonFollowsFocus", true)) {
  155. root.setDefaultButton(initialDefault);
  156. }
  157. }
  158. }
  159. b.getModel().setArmed(false);
  160. b.repaint();
  161. }
  162. public void mouseMoved(MouseEvent e) {
  163. }
  164. public void mouseDragged(MouseEvent e) {
  165. }
  166. public void mouseClicked(MouseEvent e) {
  167. }
  168. public void mousePressed(MouseEvent e) {
  169. if (SwingUtilities.isLeftMouseButton(e) ) {
  170. AbstractButton b = (AbstractButton) e.getSource();
  171. if(b.contains(e.getX(), e.getY())) {
  172. long multiClickThreshhold = b.getMultiClickThreshhold();
  173. long lastTime = lastPressedTimestamp;
  174. long currentTime = lastPressedTimestamp = e.getWhen();
  175. if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) {
  176. shouldDiscardRelease = true;
  177. return;
  178. }
  179. ButtonModel model = b.getModel();
  180. if (!model.isEnabled()) {
  181. // Disabled buttons ignore all input...
  182. return;
  183. }
  184. if (!model.isArmed()) {
  185. // button not armed, should be
  186. model.setArmed(true);
  187. }
  188. model.setPressed(true);
  189. if(!b.hasFocus() && b.isRequestFocusEnabled()) {
  190. b.requestFocus();
  191. }
  192. }
  193. }
  194. };
  195. public void mouseReleased(MouseEvent e) {
  196. if (SwingUtilities.isLeftMouseButton(e)) {
  197. // Support for multiClickThreshhold
  198. if (shouldDiscardRelease) {
  199. shouldDiscardRelease = false;
  200. return;
  201. }
  202. AbstractButton b = (AbstractButton) e.getSource();
  203. ButtonModel model = b.getModel();
  204. model.setPressed(false);
  205. model.setArmed(false);
  206. }
  207. };
  208. public void mouseEntered(MouseEvent e) {
  209. AbstractButton b = (AbstractButton) e.getSource();
  210. ButtonModel model = b.getModel();
  211. if (b.isRolloverEnabled() && !SwingUtilities.isLeftMouseButton(e)) {
  212. model.setRollover(true);
  213. }
  214. if (model.isPressed())
  215. model.setArmed(true);
  216. };
  217. public void mouseExited(MouseEvent e) {
  218. AbstractButton b = (AbstractButton) e.getSource();
  219. ButtonModel model = b.getModel();
  220. if(b.isRolloverEnabled()) {
  221. model.setRollover(false);
  222. }
  223. model.setArmed(false);
  224. };
  225. /**
  226. * Actions for Buttons. Two type of action are supported:
  227. * pressed: Moves the button to a pressed state
  228. * released: Disarms the button.
  229. */
  230. private static class Actions extends UIAction {
  231. private static final String PRESS = "pressed";
  232. private static final String RELEASE = "released";
  233. Actions(String name) {
  234. super(name);
  235. }
  236. public void actionPerformed(ActionEvent e) {
  237. AbstractButton b = (AbstractButton)e.getSource();
  238. String key = getName();
  239. if (key == PRESS) {
  240. ButtonModel model = b.getModel();
  241. model.setArmed(true);
  242. model.setPressed(true);
  243. if(!b.hasFocus()) {
  244. b.requestFocus();
  245. }
  246. }
  247. else if (key == RELEASE) {
  248. ButtonModel model = b.getModel();
  249. model.setPressed(false);
  250. model.setArmed(false);
  251. }
  252. }
  253. public boolean isEnabled(Object sender) {
  254. if(sender != null && (sender instanceof AbstractButton) &&
  255. !((AbstractButton)sender).getModel().isEnabled()) {
  256. return false;
  257. } else {
  258. return true;
  259. }
  260. }
  261. }
  262. }