modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ButtonBehavior.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization

*** 1,7 **** /* ! * Copyright (c) 2010, 2013, 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 --- 1,7 ---- /* ! * Copyright (c) 2010, 2015, 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
*** 20,165 **** * * 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 com.sun.javafx.scene.control.behavior; import javafx.scene.control.ButtonBase; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; - import java.util.ArrayList; - import java.util.List; - import static javafx.scene.input.KeyCode.SPACE; - import static javafx.scene.input.KeyCode.TAB; - import static javafx.scene.input.KeyEvent.KEY_PRESSED; - import static javafx.scene.input.KeyEvent.KEY_RELEASED; /** * All of the "button" types (CheckBox, RadioButton, ToggleButton, and Button) * and also maybe some other types like hyperlinks operate on the "armed" * selection strategy, just like JButton. This behavior class encapsulates that * logic in a way that can be reused and extended by each of the individual * class behaviors. * */ public class ButtonBehavior<C extends ButtonBase> extends BehaviorBase<C> { /*************************************************************************** * * * Constructors * * * **************************************************************************/ ! public ButtonBehavior(final C button) { ! super(button, BUTTON_BINDINGS); } ! public ButtonBehavior(final C button, final List<KeyBinding> bindings) { ! super(button, bindings); } /*************************************************************************** * * * Focus change handling * * * **************************************************************************/ ! @Override protected void focusChanged() { // If we did have the key down, but are now not focused, then we must // disarm the button. ! final ButtonBase button = getControl(); if (keyDown && !button.isFocused()) { keyDown = false; button.disarm(); } } /*************************************************************************** * * * Key event handling * * * **************************************************************************/ /** - * Indicates that a keyboard key has been pressed which represents the - * event (this could be space bar for example). As long as keyDown is true, - * we are also armed, and will ignore mouse events related to arming. - * Note this is made package private solely for the sake of testing. - */ - private boolean keyDown; - - private static final String PRESS_ACTION = "Press"; - private static final String RELEASE_ACTION = "Release"; - - protected static final List<KeyBinding> BUTTON_BINDINGS = new ArrayList<KeyBinding>(); - static { - BUTTON_BINDINGS.add(new KeyBinding(TAB, "TraverseNext")); - BUTTON_BINDINGS.add(new KeyBinding(TAB, "TraversePrevious").shift()); - - BUTTON_BINDINGS.add(new KeyBinding(SPACE, KEY_PRESSED, PRESS_ACTION)); - BUTTON_BINDINGS.add(new KeyBinding(SPACE, KEY_RELEASED, RELEASE_ACTION)); - } - - @Override protected void callAction(String name) { - if (!getControl().isDisabled()) { - if (PRESS_ACTION.equals(name)) { - keyPressed(); - } else if (RELEASE_ACTION.equals(name)) { - keyReleased(); - } else { - super.callAction(name); - } - } - } - - /** * This function is invoked when an appropriate keystroke occurs which * causes this button to be armed if it is not already armed by a mouse * press. */ ! private void keyPressed() { ! final ButtonBase button = getControl(); ! if (! button.isPressed() && ! button.isArmed()) { keyDown = true; ! button.arm(); } } /** * Invoked when a valid keystroke release occurs which causes the button * to fire if it was armed by a keyPress. */ ! private void keyReleased() { ! final ButtonBase button = getControl(); if (keyDown) { keyDown = false; ! if (button.isArmed()) { ! button.disarm(); ! button.fire(); } } } /*************************************************************************** * * * Mouse event handling * * * **************************************************************************/ /** * Invoked when a mouse press has occurred over the button. In addition to * potentially arming the Button, this will transfer focus to the button */ ! @Override public void mousePressed(MouseEvent e) { ! final ButtonBase button = getControl(); ! super.mousePressed(e); // if the button is not already focused, then request the focus ! if (! button.isFocused() && button.isFocusTraversable()) { ! button.requestFocus(); } // arm the button if it is a valid mouse event // Note there appears to be a bug where if I press and hold and release // then there is a clickCount of 0 on the release, whereas a quick click --- 20,179 ---- * * 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 com.sun.javafx.scene.control.behavior; + import javafx.beans.Observable; import javafx.scene.control.ButtonBase; + import com.sun.javafx.scene.control.inputmap.InputMap; + import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; + import static com.sun.javafx.scene.control.inputmap.InputMap.*; + import static javafx.scene.input.KeyCode.SPACE; /** * All of the "button" types (CheckBox, RadioButton, ToggleButton, and Button) * and also maybe some other types like hyperlinks operate on the "armed" * selection strategy, just like JButton. This behavior class encapsulates that * logic in a way that can be reused and extended by each of the individual * class behaviors. * */ public class ButtonBehavior<C extends ButtonBase> extends BehaviorBase<C> { + private final InputMap<C> buttonInputMap; + + /** + * Indicates that a keyboard key has been pressed which represents the + * event (this could be space bar for example). As long as keyDown is true, + * we are also armed, and will ignore mouse events related to arming. + * Note this is made package private solely for the sake of testing. + */ + private boolean keyDown; + + /*************************************************************************** * * * Constructors * * * **************************************************************************/ ! public ButtonBehavior(C control) { ! super(control); ! ! // create a map for button-specific mappings (this reuses the default ! // InputMap installed on the control, if it is non-null, allowing us to pick up any user-specified mappings) ! buttonInputMap = createInputMap(); ! ! // add focus traversal mappings ! addDefaultMapping(buttonInputMap, FocusTraversalInputMap.getFocusTraversalMappings()); ! ! // then button-specific mappings for key and mouse input ! addDefaultMapping(buttonInputMap, ! new KeyMapping(SPACE, KeyEvent.KEY_PRESSED, this::keyPressed), ! new KeyMapping(SPACE, KeyEvent.KEY_RELEASED, this::keyReleased), ! new MouseMapping(MouseEvent.MOUSE_PRESSED, this::mousePressed), ! new MouseMapping(MouseEvent.MOUSE_RELEASED, this::mouseReleased), ! new MouseMapping(MouseEvent.MOUSE_ENTERED, this::mouseEntered), ! new MouseMapping(MouseEvent.MOUSE_EXITED, this::mouseExited) ! ); ! ! // Button also cares about focus ! control.focusedProperty().addListener(this::focusChanged); } ! ! ! /*************************************************************************** ! * * ! * Implementation of BehaviorBase API * ! * * ! **************************************************************************/ ! ! @Override public InputMap<C> getInputMap() { ! return buttonInputMap; } + @Override public void dispose() { + super.dispose(); + + // TODO + getNode().focusedProperty().removeListener(this::focusChanged); + } + + + /*************************************************************************** * * * Focus change handling * * * **************************************************************************/ ! private void focusChanged(Observable o) { // If we did have the key down, but are now not focused, then we must // disarm the button. ! final ButtonBase button = getNode(); if (keyDown && !button.isFocused()) { keyDown = false; button.disarm(); } } + + /*************************************************************************** * * * Key event handling * * * **************************************************************************/ /** * This function is invoked when an appropriate keystroke occurs which * causes this button to be armed if it is not already armed by a mouse * press. */ ! protected void keyPressed(KeyEvent e) { ! if (! getNode().isPressed() && ! getNode().isArmed()) { keyDown = true; ! getNode().arm(); } } /** * Invoked when a valid keystroke release occurs which causes the button * to fire if it was armed by a keyPress. */ ! protected void keyReleased(KeyEvent e) { if (keyDown) { keyDown = false; ! if (getNode().isArmed()) { ! getNode().disarm(); ! getNode().fire(); } } } + + /*************************************************************************** * * * Mouse event handling * * * **************************************************************************/ /** * Invoked when a mouse press has occurred over the button. In addition to * potentially arming the Button, this will transfer focus to the button */ ! protected void mousePressed(MouseEvent e) { // if the button is not already focused, then request the focus ! if (! getNode().isFocused() && getNode().isFocusTraversable()) { ! getNode().requestFocus(); } // arm the button if it is a valid mouse event // Note there appears to be a bug where if I press and hold and release // then there is a clickCount of 0 on the release, whereas a quick click
*** 167,218 **** // though it should really be == 1 I think. boolean valid = (e.getButton() == MouseButton.PRIMARY && ! (e.isMiddleButtonDown() || e.isSecondaryButtonDown() || e.isShiftDown() || e.isControlDown() || e.isAltDown() || e.isMetaDown())); ! if (! button.isArmed() && valid) { ! button.arm(); } } /** * Invoked when a mouse release has occurred. We determine whether this * was done in a manner that would fire the button's action. This happens * only if the button was armed by a corresponding mouse press. */ ! @Override public void mouseReleased(MouseEvent e) { // if armed by a mouse press instead of key press, then fire! ! final ButtonBase button = getControl(); ! if (! keyDown && button.isArmed()) { ! button.fire(); ! button.disarm(); } } /** * Invoked when the mouse enters the Button. If the Button had been armed * by a mouse press and the mouse is still pressed, then this will cause * the button to be rearmed. */ ! @Override public void mouseEntered(MouseEvent e) { // rearm if necessary ! final ButtonBase button = getControl(); ! super.mouseEntered(e); ! if (! keyDown && button.isPressed()) { ! button.arm(); } } /** * Invoked when the mouse exits the Button. If the Button is armed due to * a mouse press, then this function will disarm the button upon the mouse * exiting it. */ ! @Override public void mouseExited(MouseEvent e) { // Disarm if necessary ! final ButtonBase button = getControl(); ! super.mouseExited(e); ! if (! keyDown && button.isArmed()) { ! button.disarm(); } } } --- 181,227 ---- // though it should really be == 1 I think. boolean valid = (e.getButton() == MouseButton.PRIMARY && ! (e.isMiddleButtonDown() || e.isSecondaryButtonDown() || e.isShiftDown() || e.isControlDown() || e.isAltDown() || e.isMetaDown())); ! if (! getNode().isArmed() && valid) { ! getNode().arm(); } } /** * Invoked when a mouse release has occurred. We determine whether this * was done in a manner that would fire the button's action. This happens * only if the button was armed by a corresponding mouse press. */ ! protected void mouseReleased(MouseEvent e) { // if armed by a mouse press instead of key press, then fire! ! if (! keyDown && getNode().isArmed()) { ! getNode().fire(); ! getNode().disarm(); } } /** * Invoked when the mouse enters the Button. If the Button had been armed * by a mouse press and the mouse is still pressed, then this will cause * the button to be rearmed. */ ! protected void mouseEntered(MouseEvent e) { // rearm if necessary ! if (! keyDown && getNode().isPressed()) { ! getNode().arm(); } } /** * Invoked when the mouse exits the Button. If the Button is armed due to * a mouse press, then this function will disarm the button upon the mouse * exiting it. */ ! protected void mouseExited(MouseEvent e) { // Disarm if necessary ! if (! keyDown && getNode().isArmed()) { ! getNode().disarm(); } } }