/* * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package swingjs.plaf; import jsjava.awt.event.ActionEvent; import jsjava.awt.event.FocusEvent; import jsjava.awt.event.FocusListener; import jsjava.awt.event.InputEvent; import jsjava.awt.event.MouseEvent; import jsjava.awt.event.MouseListener; import jsjava.awt.event.MouseMotionListener; import jsjava.beans.PropertyChangeEvent; import jsjava.beans.PropertyChangeListener; import jsjavax.swing.AbstractButton; import jsjavax.swing.ButtonModel; import jsjavax.swing.InputMap; import jsjavax.swing.JComponent; import jsjavax.swing.KeyStroke; import jsjavax.swing.SwingUtilities; import jsjavax.swing.event.ChangeEvent; import jsjavax.swing.event.ChangeListener; import jsjavax.swing.plaf.ComponentInputMapUIResource; import jsjavax.swing.plaf.ComponentUI; import jssun.swing.UIAction; /** * Button Listener * * @author Jeff Dinkins * @author Arnaud Weber (keyboard UI support) */ public class JSButtonListener implements MouseListener, MouseMotionListener, FocusListener, ChangeListener, PropertyChangeListener { private long lastPressedTimestamp = -1; private boolean shouldDiscardRelease = false; private AbstractButton btn; /** * Populates Buttons actions. */ static void loadActionMap(LazyActionMap map) { map.put(new Actions(Actions.PRESS)); map.put(new Actions(Actions.RELEASE)); } public JSButtonListener(AbstractButton b) { btn = b; } public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); //System.out.println("JSButtonListener property change: " + prop + " " + e.getSource()); if (prop == AbstractButton.MNEMONIC_CHANGED_PROPERTY) { updateMnemonicBinding((AbstractButton) e.getSource()); } else if (prop == AbstractButton.CONTENT_AREA_FILLED_CHANGED_PROPERTY) { checkOpacity((AbstractButton) e.getSource()); } else if (prop == AbstractButton.TEXT_CHANGED_PROPERTY || "font" == prop || "foreground" == prop) { AbstractButton b = (AbstractButton) e.getSource(); ((JSComponentUI) (Object) b.getUI()).notifyPropertyChanged(prop); } } protected void checkOpacity(AbstractButton b) { b.setOpaque( b.isContentAreaFilled() ); } /** * Register default key actions: pressing space to "click" a * button and registring the keyboard mnemonic (if any). */ public void installKeyboardActions(JComponent c) { AbstractButton b = (AbstractButton)c; // Update the mnemonic binding. updateMnemonicBinding(b); LazyActionMap.installLazyActionMap(c, JSButtonListener.class, "Button.actionMap"); InputMap km = getInputMap(JComponent.WHEN_FOCUSED, c); SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, km); } /** * Unregister's default key actions */ public void uninstallKeyboardActions(JComponent c) { SwingUtilities.replaceUIInputMap(c, JComponent. WHEN_IN_FOCUSED_WINDOW, null); SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, null); SwingUtilities.replaceUIActionMap(c, null); } /** * Returns the InputMap for condition condition. Called as * part of installKeyboardActions. */ InputMap getInputMap(int condition, JComponent c) { // if (condition == JComponent.WHEN_FOCUSED) { // BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType( // ((AbstractButton)c).getUI(), BasicButtonUI.class); // if (ui != null) { // return (InputMap)DefaultLookup.get( // c, ui, ui.getPropertyPrefix() + "focusInputMap"); // } // } return null; } /** * Resets the binding for the mnemonic in the WHEN_IN_FOCUSED_WINDOW * UI InputMap. */ void updateMnemonicBinding(AbstractButton b) { int m = b.getMnemonic(); if(m != 0) { InputMap map = SwingUtilities.getUIInputMap( b, JComponent.WHEN_IN_FOCUSED_WINDOW); if (map == null) { map = new ComponentInputMapUIResource(b); SwingUtilities.replaceUIInputMap(b, JComponent.WHEN_IN_FOCUSED_WINDOW, map); } map.clear(); map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, false), "pressed"); map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, true), "released"); map.put(KeyStroke.getKeyStroke(m, 0, true), "released"); } else { InputMap map = SwingUtilities.getUIInputMap(b, JComponent. WHEN_IN_FOCUSED_WINDOW); if (map != null) { map.clear(); } } } public void stateChanged(ChangeEvent e) { AbstractButton b = (AbstractButton) e.getSource(); b.repaint(); } public void focusGained(FocusEvent e) { // AbstractButton b = (AbstractButton) e.getSource(); // if (b instanceof JButton && ((JButton)b).isDefaultCapable()) { // JRootPane root = b.getRootPane(); // if (root != null) { // BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType( // ((AbstractButton)b).getUI(), BasicButtonUI.class); // if (ui != null && DefaultLookup.getBoolean(b, ui, // ui.getPropertyPrefix() + // "defaultButtonFollowsFocus", true)) { // root.putClientProperty("temporaryDefaultButton", b); // root.setDefaultButton((JButton)b); // root.putClientProperty("temporaryDefaultButton", null); // } // } // } // b.repaint(); } public void focusLost(FocusEvent e) { AbstractButton b = (AbstractButton) e.getSource(); // JRootPane root = b.getRootPane(); // if (root != null) { // JButton initialDefault = (JButton)root.getClientProperty("initialDefaultButton"); // if (b != initialDefault) { // BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType( // ((AbstractButton)b).getUI(), BasicButtonUI.class); // if (ui != null && DefaultLookup.getBoolean(b, ui, // ui.getPropertyPrefix() + // "defaultButtonFollowsFocus", true)) { // root.setDefaultButton(initialDefault); // } // } // } // ButtonModel model = b.getModel(); model.setArmed(false); model.setPressed(false); // // b.repaint(); } public void mouseMoved(MouseEvent e) { } public void mouseDragged(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { AbstractButton b = (AbstractButton) e.getSource(); if (!b.contains(e.getX(), e.getY())) return; // We need to check the state before and after the button click // for radio and checkboxes to make sure the DOM button actually got hit. // mousePress is an "arm"; mouseRelease is a "click" ((JSButtonUI) (ComponentUI) b.getUI()).verifyButtonClick(false); long multiClickThreshhold = b.getMultiClickThreshhold(); long lastTime = lastPressedTimestamp; long currentTime = lastPressedTimestamp = e.getWhen(); if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) { shouldDiscardRelease = true; return; } //System.out.println("JSButtonListener press " + b.getName() + " " + e); ButtonModel model = b.getModel(); if (!model.isEnabled()) { // Disabled buttons ignore all input... return; } if (!model.isArmed()) { // button not armed, should be model.setArmed(true); } model.setPressed(true); if (!b.hasFocus() && b.isRequestFocusEnabled()) { b.requestFocus(); } } }; public void mouseReleased(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { // Support for multiClickThreshhold if (shouldDiscardRelease) { shouldDiscardRelease = false; return; } AbstractButton b = (AbstractButton) e.getSource(); if (!((JSButtonUI) (ComponentUI) b.getUI()).verifyButtonClick(true)) return; //System.out.println("JSButtonListener released " + b.getName() + " " + e); ButtonModel model = b.getModel(); model.setPressed(false); model.setArmed(false); } }; public void mouseEntered(MouseEvent e) { AbstractButton b = (AbstractButton) e.getSource(); ButtonModel model = b.getModel(); if (b.isRolloverEnabled() && !SwingUtilities.isLeftMouseButton(e)) { model.setRollover(true); } if (model.isPressed()) model.setArmed(true); }; public void mouseExited(MouseEvent e) { AbstractButton b = (AbstractButton) e.getSource(); ButtonModel model = b.getModel(); if(b.isRolloverEnabled()) { model.setRollover(false); } model.setArmed(false); }; /** * Actions for Buttons. Two types of action are supported: * pressed: Moves the button to a pressed state * released: Disarms the button. */ private static class Actions extends UIAction { private static final String PRESS = "pressed"; private static final String RELEASE = "released"; Actions(String name) { super(name); } public void actionPerformed(ActionEvent e) { AbstractButton b = (AbstractButton)e.getSource(); String key = getName(); if (key == PRESS) { ButtonModel model = b.getModel(); model.setArmed(true); model.setPressed(true); if(!b.hasFocus()) { b.requestFocus(); } } else if (key == RELEASE) { ButtonModel model = b.getModel(); model.setPressed(false); model.setArmed(false); } } public boolean isEnabled(Object sender) { if(sender != null && (sender instanceof AbstractButton) && !((AbstractButton)sender).getModel().isEnabled()) { return false; } else { return true; } } } }