blob: 05e35cc72ecd6ca3987a8b5a6ede8c8e5abffaae [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.swing.plaf.basic;
27
28import sun.swing.DefaultLookup;
29import sun.swing.UIAction;
30import java.awt.*;
31import java.awt.event.*;
32import java.beans.*;
33import javax.swing.*;
34import javax.swing.event.*;
35import javax.swing.plaf.ActionMapUIResource;
36import javax.swing.plaf.ButtonUI;
37import javax.swing.plaf.ComponentInputMapUIResource;
38
39/**
40 * Button Listener
41 *
42 * @author Jeff Dinkins
43 * @author Arnaud Weber (keyboard UI support)
44 */
45
46public class BasicButtonListener implements MouseListener, MouseMotionListener,
47 FocusListener, ChangeListener, PropertyChangeListener
48{
49 private long lastPressedTimestamp = -1;
50 private boolean shouldDiscardRelease = false;
51
52 /**
53 * Populates Buttons actions.
54 */
55 static void loadActionMap(LazyActionMap map) {
56 map.put(new Actions(Actions.PRESS));
57 map.put(new Actions(Actions.RELEASE));
58 }
59
60
61 public BasicButtonListener(AbstractButton b) {
62 }
63
64 public void propertyChange(PropertyChangeEvent e) {
65 String prop = e.getPropertyName();
66 if(prop == AbstractButton.MNEMONIC_CHANGED_PROPERTY) {
67 updateMnemonicBinding((AbstractButton)e.getSource());
68 }
69 else if(prop == AbstractButton.CONTENT_AREA_FILLED_CHANGED_PROPERTY) {
70 checkOpacity((AbstractButton) e.getSource() );
71 }
72 else if(prop == AbstractButton.TEXT_CHANGED_PROPERTY ||
73 "font" == prop || "foreground" == prop) {
74 AbstractButton b = (AbstractButton) e.getSource();
75 BasicHTML.updateRenderer(b, b.getText());
76 }
77 }
78
79 protected void checkOpacity(AbstractButton b) {
80 b.setOpaque( b.isContentAreaFilled() );
81 }
82
83 /**
84 * Register default key actions: pressing space to "click" a
85 * button and registring the keyboard mnemonic (if any).
86 */
87 public void installKeyboardActions(JComponent c) {
88 AbstractButton b = (AbstractButton)c;
89 // Update the mnemonic binding.
90 updateMnemonicBinding(b);
91
92 LazyActionMap.installLazyActionMap(c, BasicButtonListener.class,
93 "Button.actionMap");
94
95 InputMap km = getInputMap(JComponent.WHEN_FOCUSED, c);
96
97 SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, km);
98 }
99
100 /**
101 * Unregister's default key actions
102 */
103 public void uninstallKeyboardActions(JComponent c) {
104 SwingUtilities.replaceUIInputMap(c, JComponent.
105 WHEN_IN_FOCUSED_WINDOW, null);
106 SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, null);
107 SwingUtilities.replaceUIActionMap(c, null);
108 }
109
110 /**
111 * Returns the InputMap for condition <code>condition</code>. Called as
112 * part of <code>installKeyboardActions</code>.
113 */
114 InputMap getInputMap(int condition, JComponent c) {
115 if (condition == JComponent.WHEN_FOCUSED) {
116 BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
117 ((AbstractButton)c).getUI(), BasicButtonUI.class);
118 if (ui != null) {
119 return (InputMap)DefaultLookup.get(
120 c, ui, ui.getPropertyPrefix() + "focusInputMap");
121 }
122 }
123 return null;
124 }
125
126 /**
127 * Resets the binding for the mnemonic in the WHEN_IN_FOCUSED_WINDOW
128 * UI InputMap.
129 */
130 void updateMnemonicBinding(AbstractButton b) {
131 int m = b.getMnemonic();
132 if(m != 0) {
133 InputMap map = SwingUtilities.getUIInputMap(
134 b, JComponent.WHEN_IN_FOCUSED_WINDOW);
135
136 if (map == null) {
137 map = new ComponentInputMapUIResource(b);
138 SwingUtilities.replaceUIInputMap(b,
139 JComponent.WHEN_IN_FOCUSED_WINDOW, map);
140 }
141 map.clear();
142 map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, false),
143 "pressed");
144 map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, true),
145 "released");
146 map.put(KeyStroke.getKeyStroke(m, 0, true), "released");
147 }
148 else {
149 InputMap map = SwingUtilities.getUIInputMap(b, JComponent.
150 WHEN_IN_FOCUSED_WINDOW);
151 if (map != null) {
152 map.clear();
153 }
154 }
155 }
156
157 public void stateChanged(ChangeEvent e) {
158 AbstractButton b = (AbstractButton) e.getSource();
159 b.repaint();
160 }
161
162 public void focusGained(FocusEvent e) {
163 AbstractButton b = (AbstractButton) e.getSource();
164 if (b instanceof JButton && ((JButton)b).isDefaultCapable()) {
165 JRootPane root = b.getRootPane();
166 if (root != null) {
167 BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
168 ((AbstractButton)b).getUI(), BasicButtonUI.class);
169 if (ui != null && DefaultLookup.getBoolean(b, ui,
170 ui.getPropertyPrefix() +
171 "defaultButtonFollowsFocus", true)) {
172 root.putClientProperty("temporaryDefaultButton", b);
173 root.setDefaultButton((JButton)b);
174 root.putClientProperty("temporaryDefaultButton", null);
175 }
176 }
177 }
178 b.repaint();
179 }
180
181 public void focusLost(FocusEvent e) {
182 AbstractButton b = (AbstractButton) e.getSource();
183 JRootPane root = b.getRootPane();
184 if (root != null) {
185 JButton initialDefault = (JButton)root.getClientProperty("initialDefaultButton");
186 if (b != initialDefault) {
187 BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
188 ((AbstractButton)b).getUI(), BasicButtonUI.class);
189 if (ui != null && DefaultLookup.getBoolean(b, ui,
190 ui.getPropertyPrefix() +
191 "defaultButtonFollowsFocus", true)) {
192 root.setDefaultButton(initialDefault);
193 }
194 }
195 }
196
197 ButtonModel model = b.getModel();
198 model.setArmed(false);
199 model.setPressed(false);
200
201 b.repaint();
202 }
203
204 public void mouseMoved(MouseEvent e) {
205 }
206
207
208 public void mouseDragged(MouseEvent e) {
209 }
210
211 public void mouseClicked(MouseEvent e) {
212 }
213
214 public void mousePressed(MouseEvent e) {
215 if (SwingUtilities.isLeftMouseButton(e) ) {
216 AbstractButton b = (AbstractButton) e.getSource();
217
218 if(b.contains(e.getX(), e.getY())) {
219 long multiClickThreshhold = b.getMultiClickThreshhold();
220 long lastTime = lastPressedTimestamp;
221 long currentTime = lastPressedTimestamp = e.getWhen();
222 if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) {
223 shouldDiscardRelease = true;
224 return;
225 }
226
227 ButtonModel model = b.getModel();
228 if (!model.isEnabled()) {
229 // Disabled buttons ignore all input...
230 return;
231 }
232 if (!model.isArmed()) {
233 // button not armed, should be
234 model.setArmed(true);
235 }
236 model.setPressed(true);
237 if(!b.hasFocus() && b.isRequestFocusEnabled()) {
238 b.requestFocus();
239 }
240 }
241 }
242 };
243
244 public void mouseReleased(MouseEvent e) {
245 if (SwingUtilities.isLeftMouseButton(e)) {
246 // Support for multiClickThreshhold
247 if (shouldDiscardRelease) {
248 shouldDiscardRelease = false;
249 return;
250 }
251 AbstractButton b = (AbstractButton) e.getSource();
252 ButtonModel model = b.getModel();
253 model.setPressed(false);
254 model.setArmed(false);
255 }
256 };
257
258 public void mouseEntered(MouseEvent e) {
259 AbstractButton b = (AbstractButton) e.getSource();
260 ButtonModel model = b.getModel();
261 if (b.isRolloverEnabled() && !SwingUtilities.isLeftMouseButton(e)) {
262 model.setRollover(true);
263 }
264 if (model.isPressed())
265 model.setArmed(true);
266 };
267
268 public void mouseExited(MouseEvent e) {
269 AbstractButton b = (AbstractButton) e.getSource();
270 ButtonModel model = b.getModel();
271 if(b.isRolloverEnabled()) {
272 model.setRollover(false);
273 }
274 model.setArmed(false);
275 };
276
277
278 /**
279 * Actions for Buttons. Two types of action are supported:
280 * pressed: Moves the button to a pressed state
281 * released: Disarms the button.
282 */
283 private static class Actions extends UIAction {
284 private static final String PRESS = "pressed";
285 private static final String RELEASE = "released";
286
287 Actions(String name) {
288 super(name);
289 }
290
291 public void actionPerformed(ActionEvent e) {
292 AbstractButton b = (AbstractButton)e.getSource();
293 String key = getName();
294 if (key == PRESS) {
295 ButtonModel model = b.getModel();
296 model.setArmed(true);
297 model.setPressed(true);
298 if(!b.hasFocus()) {
299 b.requestFocus();
300 }
301 }
302 else if (key == RELEASE) {
303 ButtonModel model = b.getModel();
304 model.setPressed(false);
305 model.setArmed(false);
306 }
307 }
308
309 public boolean isEnabled(Object sender) {
310 if(sender != null && (sender instanceof AbstractButton) &&
311 !((AbstractButton)sender).getModel().isEnabled()) {
312 return false;
313 } else {
314 return true;
315 }
316 }
317 }
318}