1 /* 2 * Copyright (c) 2010, 2015, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.scene.control.skin; 27 28 import com.sun.javafx.scene.control.behavior.BehaviorBase; 29 import com.sun.javafx.scene.control.skin.Utils; 30 import javafx.scene.Node; 31 import javafx.scene.Scene; 32 import javafx.scene.control.Button; 33 import javafx.scene.control.ContextMenu; 34 import com.sun.javafx.scene.control.behavior.ButtonBehavior; 35 import javafx.scene.control.Control; 36 import javafx.scene.input.KeyCode; 37 import javafx.scene.input.KeyCodeCombination; 38 39 /** 40 * Default skin implementation for the {@link Button} control. 41 * 42 * @see Button 43 * @since 9 44 */ 45 public class ButtonSkin extends LabeledSkinBase<Button> { 46 47 /*************************************************************************** 48 * * 49 * Private fields * 50 * * 51 **************************************************************************/ 52 53 private KeyCodeCombination defaultAcceleratorKeyCodeCombination; 54 private KeyCodeCombination cancelAcceleratorKeyCodeCombination; 55 private final BehaviorBase<Button> behavior; 56 57 58 59 /*************************************************************************** 60 * * 61 * Listeners * 62 * * 63 **************************************************************************/ 64 65 Runnable defaultButtonRunnable = () -> { 66 if (getSkinnable().getScene() != null && getSkinnable().impl_isTreeVisible() && !getSkinnable().isDisabled()) { 67 getSkinnable().fire(); 68 } 69 }; 70 71 Runnable cancelButtonRunnable = () -> { 72 if (getSkinnable().getScene() != null && getSkinnable().impl_isTreeVisible() && !getSkinnable().isDisabled()) { 73 getSkinnable().fire(); 74 } 75 }; 76 77 78 79 /*************************************************************************** 80 * * 81 * Constructors * 82 * * 83 **************************************************************************/ 84 85 /** 86 * Creates a new ButtonSkin instance, installing the necessary child 87 * nodes into the Control {@link Control#getChildren() children} list, as 88 * well as the necessary input mappings for handling key, mouse, etc events. 89 * 90 * @param control The control that this skin should be installed onto. 91 */ 92 public ButtonSkin(Button control) { 93 super(control); 94 95 // install default input map for the Button control 96 behavior = new ButtonBehavior<>(control); 97 // control.setInputMap(behavior.getInputMap()); 98 99 // Register listeners 100 registerChangeListener(control.defaultButtonProperty(), o -> setDefaultButton(getSkinnable().isDefaultButton())); 101 registerChangeListener(control.cancelButtonProperty(), o -> setCancelButton(getSkinnable().isCancelButton())); 102 registerChangeListener(control.focusedProperty(), o -> { 103 if (!getSkinnable().isFocused()) { 104 ContextMenu cm = getSkinnable().getContextMenu(); 105 if (cm != null) { 106 if (cm.isShowing()) { 107 cm.hide(); 108 Utils.removeMnemonics(cm, getSkinnable().getScene()); 109 } 110 } 111 } 112 }); 113 registerChangeListener(control.parentProperty(), o -> { 114 if (getSkinnable().getParent() == null && getSkinnable().getScene() != null) { 115 if (getSkinnable().isDefaultButton()) { 116 getSkinnable().getScene().getAccelerators().remove(defaultAcceleratorKeyCodeCombination); 117 } 118 if (getSkinnable().isCancelButton()) { 119 getSkinnable().getScene().getAccelerators().remove(cancelAcceleratorKeyCodeCombination); 120 } 121 } 122 }); 123 124 // set visuals 125 if (getSkinnable().isDefaultButton()) { 126 /* 127 ** were we already the defaultButton, before the listener was added? 128 ** don't laugh, it can happen.... 129 */ 130 setDefaultButton(true); 131 } 132 133 if (getSkinnable().isCancelButton()) { 134 /* 135 ** were we already the defaultButton, before the listener was added? 136 ** don't laugh, it can happen.... 137 */ 138 setCancelButton(true); 139 } 140 } 141 142 143 144 /*************************************************************************** 145 * * 146 * Public API * 147 * * 148 **************************************************************************/ 149 150 /** {@inheritDoc} */ 151 @Override public void dispose() { 152 super.dispose(); 153 154 if (behavior != null) { 155 behavior.dispose(); 156 } 157 } 158 159 160 161 /*************************************************************************** 162 * * 163 * Private implementation * 164 * * 165 **************************************************************************/ 166 167 private void setDefaultButton(boolean value) { 168 Scene scene = getSkinnable().getScene(); 169 if (scene != null) { 170 KeyCode acceleratorCode = KeyCode.ENTER; 171 defaultAcceleratorKeyCodeCombination = new KeyCodeCombination(acceleratorCode); 172 173 Runnable oldDefault = scene.getAccelerators().get(defaultAcceleratorKeyCodeCombination); 174 if (!value) { 175 /** 176 * first check of there's a default button already 177 */ 178 if (defaultButtonRunnable.equals(oldDefault)) { 179 /** 180 * is it us? 181 */ 182 scene.getAccelerators().remove(defaultAcceleratorKeyCodeCombination); 183 } 184 } 185 else { 186 if (!defaultButtonRunnable.equals(oldDefault)) { 187 scene.getAccelerators().remove(defaultAcceleratorKeyCodeCombination); 188 scene.getAccelerators().put(defaultAcceleratorKeyCodeCombination, defaultButtonRunnable); 189 } 190 } 191 } 192 } 193 194 private void setCancelButton(boolean value) { 195 Scene scene = getSkinnable().getScene(); 196 if (scene != null) { 197 KeyCode acceleratorCode = KeyCode.ESCAPE; 198 cancelAcceleratorKeyCodeCombination = new KeyCodeCombination(acceleratorCode); 199 200 Runnable oldCancel = scene.getAccelerators().get(cancelAcceleratorKeyCodeCombination); 201 if (!value) { 202 /** 203 * first check of there's a cancel button already 204 */ 205 if (cancelButtonRunnable.equals(oldCancel)) { 206 /** 207 * is it us? 208 */ 209 scene.getAccelerators().remove(cancelAcceleratorKeyCodeCombination); 210 } 211 } 212 else { 213 if (!cancelButtonRunnable.equals(oldCancel)) { 214 scene.getAccelerators().remove(cancelAcceleratorKeyCodeCombination); 215 scene.getAccelerators().put(cancelAcceleratorKeyCodeCombination, cancelButtonRunnable); 216 } 217 } 218 } 219 } 220 }