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