1 /* 2 * Copyright (c) 2010, 2014, 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 com.sun.javafx.scene.control.behavior; 27 28 import javafx.geometry.NodeOrientation; 29 import javafx.scene.control.ScrollPane; 30 import javafx.scene.input.KeyEvent; 31 import javafx.scene.input.MouseEvent; 32 import java.util.ArrayList; 33 import java.util.List; 34 import com.sun.javafx.scene.control.skin.ScrollPaneSkin; 35 import static javafx.scene.input.KeyCode.DOWN; 36 import static javafx.scene.input.KeyCode.F4; 37 import static javafx.scene.input.KeyCode.LEFT; 38 import static javafx.scene.input.KeyCode.PAGE_DOWN; 39 import static javafx.scene.input.KeyCode.PAGE_UP; 40 import static javafx.scene.input.KeyCode.RIGHT; 41 import static javafx.scene.input.KeyCode.SPACE; 42 import static javafx.scene.input.KeyCode.UP; 43 import static javafx.scene.input.KeyCode.HOME; 44 import static javafx.scene.input.KeyCode.END; 45 46 47 /** 48 * Behavior for ScrollPane. 49 * 50 * TODO: the function variables are a poor way to couple to the rest of 51 * the system. This technique avoids a direct dependency on the skin class. 52 * However, this should really be coupled through the control itself instead 53 * of directly to the skin. 54 */ 55 public class ScrollPaneBehavior extends BehaviorBase<ScrollPane> { 56 57 /*************************************************************************** 58 * * 59 * Constructors * 60 * * 61 **************************************************************************/ 62 63 public ScrollPaneBehavior(ScrollPane scrollPane) { 64 super(scrollPane, SCROLL_PANE_BINDINGS); 65 } 66 67 /*************************************************************************** 68 * * 69 * Functions * 70 * * 71 **************************************************************************/ 72 73 public void horizontalUnitIncrement() { 74 ((ScrollPaneSkin)getControl().getSkin()).hsbIncrement(); 75 } 76 public void horizontalUnitDecrement() { 77 ((ScrollPaneSkin)getControl().getSkin()).hsbDecrement(); 78 } 79 public void verticalUnitIncrement() { 80 ((ScrollPaneSkin)getControl().getSkin()).vsbIncrement(); 81 } 82 void verticalUnitDecrement() { 83 ((ScrollPaneSkin)getControl().getSkin()).vsbDecrement(); 84 } 85 void horizontalPageIncrement() { 86 ((ScrollPaneSkin)getControl().getSkin()).hsbPageIncrement(); 87 } 88 void horizontalPageDecrement() { 89 ((ScrollPaneSkin)getControl().getSkin()).hsbPageDecrement(); 90 } 91 void verticalPageIncrement() { 92 ((ScrollPaneSkin)getControl().getSkin()).vsbPageIncrement(); 93 } 94 void verticalPageDecrement() { 95 ((ScrollPaneSkin)getControl().getSkin()).vsbPageDecrement(); 96 } 97 void verticalHome() { 98 ScrollPane sp = getControl(); 99 sp.setHvalue(sp.getHmin()); 100 sp.setVvalue(sp.getVmin()); 101 } 102 void verticalEnd() { 103 ScrollPane sp = getControl(); 104 sp.setHvalue(sp.getHmax()); 105 sp.setVvalue(sp.getVmax()); 106 } 107 108 109 public void contentDragged(double deltaX, double deltaY) { 110 // negative when dragged to the right/bottom 111 ScrollPane scroll = getControl(); 112 if (!scroll.isPannable()) return; 113 if (deltaX < 0 && scroll.getHvalue() != 0 || deltaX > 0 && scroll.getHvalue() != scroll.getHmax()) { 114 scroll.setHvalue(scroll.getHvalue() + deltaX); 115 } 116 if (deltaY < 0 && scroll.getVvalue() != 0 || deltaY > 0 && scroll.getVvalue() != scroll.getVmax()) { 117 scroll.setVvalue(scroll.getVvalue() + deltaY); 118 } 119 } 120 121 /*************************************************************************** 122 * * 123 * Key event handling * 124 * * 125 **************************************************************************/ 126 127 static final String TRAVERSE_DEBUG = "TraverseDebug"; 128 static final String HORIZONTAL_UNITDECREMENT = "HorizontalUnitDecrement"; 129 static final String HORIZONTAL_UNITINCREMENT = "HorizontalUnitIncrement"; 130 static final String VERTICAL_UNITDECREMENT = "VerticalUnitDecrement"; 131 static final String VERTICAL_UNITINCREMENT = "VerticalUnitIncrement"; 132 static final String VERTICAL_PAGEDECREMENT = "VerticalPageDecrement"; 133 static final String VERTICAL_PAGEINCREMENT = "VerticalPageIncrement"; 134 static final String VERTICAL_HOME = "VerticalHome"; 135 static final String VERTICAL_END = "VerticalEnd"; 136 137 /** 138 * We manually handle focus traversal keys due to the ScrollPane binding 139 * the left/right/up/down keys specially. 140 */ 141 protected static final List<KeyBinding> SCROLL_PANE_BINDINGS = new ArrayList<>(); 142 static { 143 // TODO XXX DEBUGGING ONLY 144 SCROLL_PANE_BINDINGS.add(new KeyBinding(F4, TRAVERSE_DEBUG).alt().ctrl().shift()); 145 146 SCROLL_PANE_BINDINGS.add(new KeyBinding(LEFT, HORIZONTAL_UNITDECREMENT)); 147 SCROLL_PANE_BINDINGS.add(new KeyBinding(RIGHT, HORIZONTAL_UNITINCREMENT)); 148 149 SCROLL_PANE_BINDINGS.add(new KeyBinding(UP, VERTICAL_UNITDECREMENT)); 150 SCROLL_PANE_BINDINGS.add(new KeyBinding(DOWN, VERTICAL_UNITINCREMENT)); 151 152 SCROLL_PANE_BINDINGS.add(new KeyBinding(PAGE_UP, VERTICAL_PAGEDECREMENT)); 153 SCROLL_PANE_BINDINGS.add(new KeyBinding(PAGE_DOWN, VERTICAL_PAGEINCREMENT)); 154 SCROLL_PANE_BINDINGS.add(new KeyBinding(SPACE, VERTICAL_PAGEINCREMENT)); 155 156 SCROLL_PANE_BINDINGS.add(new KeyBinding(HOME, VERTICAL_HOME)); 157 SCROLL_PANE_BINDINGS.add(new KeyBinding(END, VERTICAL_END)); 158 } 159 160 protected /*final*/ String matchActionForEvent(KeyEvent e) { 161 //TODO - untested code doesn't seem to get triggered (key eaten?) 162 String action = super.matchActionForEvent(e); 163 if (action != null) { 164 if (e.getCode() == LEFT) { 165 if (getControl().getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) { 166 action = "HorizontalUnitIncrement"; 167 } 168 } else if (e.getCode() == RIGHT) { 169 if (getControl().getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) { 170 action = "HorizontalUnitDecrement"; 171 } 172 } 173 } 174 return action; 175 } 176 177 @Override protected void callAction(String name) { 178 switch (name) { 179 case HORIZONTAL_UNITDECREMENT: 180 horizontalUnitDecrement(); 181 break; 182 case HORIZONTAL_UNITINCREMENT: 183 horizontalUnitIncrement(); 184 break; 185 case VERTICAL_UNITDECREMENT: 186 verticalUnitDecrement(); 187 break; 188 case VERTICAL_UNITINCREMENT: 189 verticalUnitIncrement(); 190 break; 191 case VERTICAL_PAGEDECREMENT: 192 verticalPageDecrement(); 193 break; 194 case VERTICAL_PAGEINCREMENT: 195 verticalPageIncrement(); 196 break; 197 case VERTICAL_HOME: 198 verticalHome(); 199 break; 200 case VERTICAL_END: 201 verticalEnd(); 202 break; 203 default : 204 super.callAction(name); 205 break; 206 } 207 } 208 209 /*************************************************************************** 210 * * 211 * Mouse event handling * 212 * * 213 **************************************************************************/ 214 215 public void mouseClicked() { 216 getControl().requestFocus(); 217 } 218 219 @Override public void mousePressed(MouseEvent e) { 220 super.mousePressed(e); 221 getControl().requestFocus(); 222 } 223 }