2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
\r
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
\r
5 * This code is free software; you can redistribute it and/or modify it
\r
6 * under the terms of the GNU General Public License version 2 only, as
\r
7 * published by the Free Software Foundation. Oracle designates this
\r
8 * particular file as subject to the "Classpath" exception as provided
\r
9 * by Oracle in the LICENSE file that accompanied this code.
\r
11 * This code is distributed in the hope that it will be useful, but WITHOUT
\r
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
\r
14 * version 2 for more details (a copy is included in the LICENSE file that
\r
15 * accompanied this code).
\r
17 * You should have received a copy of the GNU General Public License version
\r
18 * 2 along with this work; if not, write to the Free Software Foundation,
\r
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
\r
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
\r
22 * or visit www.oracle.com if you need additional information or have any
\r
26 package swingjs.plaf;
\r
28 import jsjava.awt.event.ActionEvent;
\r
29 import jsjava.awt.event.FocusEvent;
\r
30 import jsjava.awt.event.FocusListener;
\r
31 import jsjava.awt.event.InputEvent;
\r
32 import jsjava.awt.event.MouseEvent;
\r
33 import jsjava.awt.event.MouseListener;
\r
34 import jsjava.awt.event.MouseMotionListener;
\r
35 import jsjava.beans.PropertyChangeEvent;
\r
36 import jsjava.beans.PropertyChangeListener;
\r
37 import jsjavax.swing.AbstractButton;
\r
38 import jsjavax.swing.ButtonModel;
\r
39 import jsjavax.swing.InputMap;
\r
40 import jsjavax.swing.JComponent;
\r
41 import jsjavax.swing.KeyStroke;
\r
42 import jsjavax.swing.SwingUtilities;
\r
43 import jsjavax.swing.event.ChangeEvent;
\r
44 import jsjavax.swing.event.ChangeListener;
\r
45 import jsjavax.swing.plaf.ComponentInputMapUIResource;
\r
46 import jsjavax.swing.plaf.ComponentUI;
\r
47 import jssun.swing.UIAction;
\r
52 * @author Jeff Dinkins
\r
53 * @author Arnaud Weber (keyboard UI support)
\r
56 public class JSButtonListener implements MouseListener, MouseMotionListener,
\r
57 FocusListener, ChangeListener, PropertyChangeListener
\r
59 private long lastPressedTimestamp = -1;
\r
60 private boolean shouldDiscardRelease = false;
\r
61 private AbstractButton btn;
\r
64 * Populates Buttons actions.
\r
66 static void loadActionMap(LazyActionMap map) {
\r
67 map.put(new Actions(Actions.PRESS));
\r
68 map.put(new Actions(Actions.RELEASE));
\r
72 public JSButtonListener(AbstractButton b) {
\r
76 public void propertyChange(PropertyChangeEvent e) {
\r
77 String prop = e.getPropertyName();
\r
78 //System.out.println("JSButtonListener property change: " + prop + " " + e.getSource());
\r
79 if (prop == AbstractButton.MNEMONIC_CHANGED_PROPERTY) {
\r
80 updateMnemonicBinding((AbstractButton) e.getSource());
\r
81 } else if (prop == AbstractButton.CONTENT_AREA_FILLED_CHANGED_PROPERTY) {
\r
82 checkOpacity((AbstractButton) e.getSource());
\r
83 } else if (prop == AbstractButton.TEXT_CHANGED_PROPERTY || "font" == prop
\r
84 || "foreground" == prop) {
\r
85 AbstractButton b = (AbstractButton) e.getSource();
\r
86 ((JSComponentUI) (Object) b.getUI()).notifyPropertyChanged(prop);
\r
90 protected void checkOpacity(AbstractButton b) {
\r
91 b.setOpaque( b.isContentAreaFilled() );
\r
95 * Register default key actions: pressing space to "click" a
\r
96 * button and registring the keyboard mnemonic (if any).
\r
98 public void installKeyboardActions(JComponent c) {
\r
99 AbstractButton b = (AbstractButton)c;
\r
100 // Update the mnemonic binding.
\r
101 updateMnemonicBinding(b);
\r
103 LazyActionMap.installLazyActionMap(c, JSButtonListener.class,
\r
104 "Button.actionMap");
\r
106 InputMap km = getInputMap(JComponent.WHEN_FOCUSED, c);
\r
108 SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, km);
\r
112 * Unregister's default key actions
\r
114 public void uninstallKeyboardActions(JComponent c) {
\r
115 SwingUtilities.replaceUIInputMap(c, JComponent.
\r
116 WHEN_IN_FOCUSED_WINDOW, null);
\r
117 SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, null);
\r
118 SwingUtilities.replaceUIActionMap(c, null);
\r
122 * Returns the InputMap for condition <code>condition</code>. Called as
\r
123 * part of <code>installKeyboardActions</code>.
\r
125 InputMap getInputMap(int condition, JComponent c) {
\r
126 // if (condition == JComponent.WHEN_FOCUSED) {
\r
127 // BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
\r
128 // ((AbstractButton)c).getUI(), BasicButtonUI.class);
\r
129 // if (ui != null) {
\r
130 // return (InputMap)DefaultLookup.get(
\r
131 // c, ui, ui.getPropertyPrefix() + "focusInputMap");
\r
138 * Resets the binding for the mnemonic in the WHEN_IN_FOCUSED_WINDOW
\r
141 void updateMnemonicBinding(AbstractButton b) {
\r
142 int m = b.getMnemonic();
\r
144 InputMap map = SwingUtilities.getUIInputMap(
\r
145 b, JComponent.WHEN_IN_FOCUSED_WINDOW);
\r
148 map = new ComponentInputMapUIResource(b);
\r
149 SwingUtilities.replaceUIInputMap(b,
\r
150 JComponent.WHEN_IN_FOCUSED_WINDOW, map);
\r
153 map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, false),
\r
155 map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, true),
\r
157 map.put(KeyStroke.getKeyStroke(m, 0, true), "released");
\r
160 InputMap map = SwingUtilities.getUIInputMap(b, JComponent.
\r
161 WHEN_IN_FOCUSED_WINDOW);
\r
168 public void stateChanged(ChangeEvent e) {
\r
169 AbstractButton b = (AbstractButton) e.getSource();
\r
173 public void focusGained(FocusEvent e) {
\r
174 // AbstractButton b = (AbstractButton) e.getSource();
\r
175 // if (b instanceof JButton && ((JButton)b).isDefaultCapable()) {
\r
176 // JRootPane root = b.getRootPane();
\r
177 // if (root != null) {
\r
178 // BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
\r
179 // ((AbstractButton)b).getUI(), BasicButtonUI.class);
\r
180 // if (ui != null && DefaultLookup.getBoolean(b, ui,
\r
181 // ui.getPropertyPrefix() +
\r
182 // "defaultButtonFollowsFocus", true)) {
\r
183 // root.putClientProperty("temporaryDefaultButton", b);
\r
184 // root.setDefaultButton((JButton)b);
\r
185 // root.putClientProperty("temporaryDefaultButton", null);
\r
192 public void focusLost(FocusEvent e) {
\r
193 AbstractButton b = (AbstractButton) e.getSource();
\r
194 // JRootPane root = b.getRootPane();
\r
195 // if (root != null) {
\r
196 // JButton initialDefault = (JButton)root.getClientProperty("initialDefaultButton");
\r
197 // if (b != initialDefault) {
\r
198 // BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(
\r
199 // ((AbstractButton)b).getUI(), BasicButtonUI.class);
\r
200 // if (ui != null && DefaultLookup.getBoolean(b, ui,
\r
201 // ui.getPropertyPrefix() +
\r
202 // "defaultButtonFollowsFocus", true)) {
\r
203 // root.setDefaultButton(initialDefault);
\r
208 ButtonModel model = b.getModel();
\r
209 model.setArmed(false);
\r
210 model.setPressed(false);
\r
215 public void mouseMoved(MouseEvent e) {
\r
219 public void mouseDragged(MouseEvent e) {
\r
222 public void mouseClicked(MouseEvent e) {
\r
225 public void mousePressed(MouseEvent e) {
\r
226 if (SwingUtilities.isLeftMouseButton(e)) {
\r
227 AbstractButton b = (AbstractButton) e.getSource();
\r
228 if (!b.contains(e.getX(), e.getY()))
\r
230 // We need to check the state before and after the button click
\r
231 // for radio and checkboxes to make sure the DOM button actually got hit.
\r
232 // mousePress is an "arm"; mouseRelease is a "click"
\r
234 ((JSButtonUI) (ComponentUI) b.getUI()).verifyButtonClick(false);
\r
235 long multiClickThreshhold = b.getMultiClickThreshhold();
\r
236 long lastTime = lastPressedTimestamp;
\r
237 long currentTime = lastPressedTimestamp = e.getWhen();
\r
238 if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) {
\r
239 shouldDiscardRelease = true;
\r
243 //System.out.println("JSButtonListener press " + b.getName() + " " + e);
\r
245 ButtonModel model = b.getModel();
\r
246 if (!model.isEnabled()) {
\r
247 // Disabled buttons ignore all input...
\r
250 if (!model.isArmed()) {
\r
251 // button not armed, should be
\r
252 model.setArmed(true);
\r
254 model.setPressed(true);
\r
255 if (!b.hasFocus() && b.isRequestFocusEnabled()) {
\r
261 public void mouseReleased(MouseEvent e) {
\r
262 if (SwingUtilities.isLeftMouseButton(e)) {
\r
263 // Support for multiClickThreshhold
\r
264 if (shouldDiscardRelease) {
\r
265 shouldDiscardRelease = false;
\r
268 AbstractButton b = (AbstractButton) e.getSource();
\r
269 if (!((JSButtonUI) (ComponentUI) b.getUI()).verifyButtonClick(true))
\r
272 //System.out.println("JSButtonListener released " + b.getName() + " " + e);
\r
274 ButtonModel model = b.getModel();
\r
275 model.setPressed(false);
\r
276 model.setArmed(false);
\r
280 public void mouseEntered(MouseEvent e) {
\r
281 AbstractButton b = (AbstractButton) e.getSource();
\r
282 ButtonModel model = b.getModel();
\r
283 if (b.isRolloverEnabled() && !SwingUtilities.isLeftMouseButton(e)) {
\r
284 model.setRollover(true);
\r
286 if (model.isPressed())
\r
287 model.setArmed(true);
\r
290 public void mouseExited(MouseEvent e) {
\r
291 AbstractButton b = (AbstractButton) e.getSource();
\r
292 ButtonModel model = b.getModel();
\r
293 if(b.isRolloverEnabled()) {
\r
294 model.setRollover(false);
\r
296 model.setArmed(false);
\r
301 * Actions for Buttons. Two types of action are supported:
\r
302 * pressed: Moves the button to a pressed state
\r
303 * released: Disarms the button.
\r
305 private static class Actions extends UIAction {
\r
306 private static final String PRESS = "pressed";
\r
307 private static final String RELEASE = "released";
\r
309 Actions(String name) {
\r
313 public void actionPerformed(ActionEvent e) {
\r
314 AbstractButton b = (AbstractButton)e.getSource();
\r
315 String key = getName();
\r
316 if (key == PRESS) {
\r
317 ButtonModel model = b.getModel();
\r
318 model.setArmed(true);
\r
319 model.setPressed(true);
\r
320 if(!b.hasFocus()) {
\r
324 else if (key == RELEASE) {
\r
325 ButtonModel model = b.getModel();
\r
326 model.setPressed(false);
\r
327 model.setArmed(false);
\r
331 public boolean isEnabled(Object sender) {
\r
332 if(sender != null && (sender instanceof AbstractButton) &&
\r
333 !((AbstractButton)sender).getModel().isEnabled()) {
\r