1 /* 2 * Copyright (c) 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 package com.sun.javafx.scene.control.behavior; 26 27 import com.sun.javafx.scene.traversal.Direction; 28 import javafx.event.EventTarget; 29 import javafx.scene.Node; 30 import com.sun.javafx.scene.control.inputmap.InputMap; 31 import com.sun.javafx.scene.control.inputmap.KeyBinding; 32 import javafx.scene.input.KeyEvent; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 37 import static com.sun.javafx.scene.control.inputmap.InputMap.*; 38 import static javafx.scene.input.KeyCode.DOWN; 39 import static javafx.scene.input.KeyCode.LEFT; 40 import static javafx.scene.input.KeyCode.RIGHT; 41 import static javafx.scene.input.KeyCode.TAB; 42 import static javafx.scene.input.KeyCode.UP; 43 44 public class FocusTraversalInputMap<N extends Node> { 45 46 private static final List<InputMap.Mapping<?>> mappings = new ArrayList<>(); 47 static { 48 mappings.add(new KeyMapping(UP, e -> traverseUp(e))); 49 mappings.add(new KeyMapping(DOWN, e -> traverseDown(e))); 50 mappings.add(new KeyMapping(LEFT, e -> traverseLeft(e))); 51 mappings.add(new KeyMapping(RIGHT, e -> traverseRight(e))); 52 mappings.add(new KeyMapping(TAB, e -> traverseNext(e))); 53 mappings.add(new KeyMapping(new KeyBinding(TAB).shift(), e -> traversePrevious(e))); 54 55 mappings.add(new KeyMapping(new KeyBinding(UP).shift().alt().ctrl(), e -> traverseUp(e))); 56 mappings.add(new KeyMapping(new KeyBinding(DOWN).shift().alt().ctrl(), e -> traverseDown(e))); 57 mappings.add(new KeyMapping(new KeyBinding(LEFT).shift().alt().ctrl(), e -> traverseLeft(e))); 58 mappings.add(new KeyMapping(new KeyBinding(RIGHT).shift().alt().ctrl(), e -> traverseRight(e))); 59 mappings.add(new KeyMapping(new KeyBinding(TAB).shift().alt().ctrl(), e -> traverseNext(e))); 60 mappings.add(new KeyMapping(new KeyBinding(TAB).alt().ctrl(), e -> traversePrevious(e))); 61 } 62 63 private FocusTraversalInputMap() { 64 // no-op, just forcing use of static method 65 } 66 67 public static InputMap.Mapping<?>[] getFocusTraversalMappings() { 68 return mappings.toArray(new InputMap.Mapping[mappings.size()]); 69 } 70 71 public static <N extends Node> InputMap<N> createInputMap(N node) { 72 InputMap<N> inputMap = new InputMap<>(node); 73 inputMap.getMappings().addAll(getFocusTraversalMappings()); 74 return inputMap; 75 } 76 77 78 79 /*************************************************************************** 80 * Focus Traversal methods * 81 **************************************************************************/ 82 83 /** 84 * Called by any of the BehaviorBase traverse methods to actually effect a 85 * traversal of the focus. The default behavior of this method is to simply 86 * call impl_traverse on the given node, passing the given direction. A 87 * subclass may override this method. 88 * 89 * @param node The node to call impl_traverse on 90 * @param dir The direction to traverse 91 */ 92 public static void traverse(final Node node, final Direction dir) { 93 if (node == null) { 94 throw new IllegalArgumentException("Attempting to traverse on a null Node. " + 95 "Most probably a KeyEvent has been fired with a null target specified."); 96 } 97 node.impl_traverse(dir); 98 } 99 100 /** 101 * Calls the focus traversal engine and indicates that traversal should 102 * go the next focusTraversable Node above the current one. 103 */ 104 public static final void traverseUp(KeyEvent e) { 105 traverse(getNode(e), com.sun.javafx.scene.traversal.Direction.UP); 106 } 107 108 /** 109 * Calls the focus traversal engine and indicates that traversal should 110 * go the next focusTraversable Node below the current one. 111 */ 112 public static final void traverseDown(KeyEvent e) { 113 traverse(getNode(e), com.sun.javafx.scene.traversal.Direction.DOWN); 114 } 115 116 /** 117 * Calls the focus traversal engine and indicates that traversal should 118 * go the next focusTraversable Node left of the current one. 119 */ 120 public static final void traverseLeft(KeyEvent e) { 121 traverse(getNode(e), com.sun.javafx.scene.traversal.Direction.LEFT); 122 } 123 124 /** 125 * Calls the focus traversal engine and indicates that traversal should 126 * go the next focusTraversable Node right of the current one. 127 */ 128 public static final void traverseRight(KeyEvent e) { 129 traverse(getNode(e), com.sun.javafx.scene.traversal.Direction.RIGHT); 130 } 131 132 /** 133 * Calls the focus traversal engine and indicates that traversal should 134 * go the next focusTraversable Node in the focus traversal cycle. 135 */ 136 public static final void traverseNext(KeyEvent e) { 137 traverse(getNode(e), com.sun.javafx.scene.traversal.Direction.NEXT); 138 } 139 140 /** 141 * Calls the focus traversal engine and indicates that traversal should 142 * go the previous focusTraversable Node in the focus traversal cycle. 143 */ 144 public static final void traversePrevious(KeyEvent e) { 145 traverse(getNode(e), com.sun.javafx.scene.traversal.Direction.PREVIOUS); 146 } 147 148 private static Node getNode(KeyEvent e) { 149 EventTarget target = e.getTarget(); 150 if (target instanceof Node) { 151 return (Node) target; 152 } 153 return null; 154 } 155 }