changeset 7714:b87aff6ddefa

RT-38283: [Controls, Spinner] Add key binding to increment and decrement the Spinner
author jgiles
date Tue, 19 Aug 2014 15:31:37 +1200
parents 7c9dd9130dac
children b5b649ef6d8d
files modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/SpinnerBehavior.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/SpinnerSkin.java
diffstat 2 files changed, 91 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/SpinnerBehavior.java	Tue Aug 19 13:33:52 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/SpinnerBehavior.java	Tue Aug 19 15:31:37 2014 +1200
@@ -32,7 +32,11 @@
 import javafx.scene.control.SpinnerValueFactory;
 import javafx.util.Duration;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
+
+import static javafx.scene.input.KeyCode.*;
 
 public class SpinnerBehavior<T> extends BehaviorBase<Spinner<T>> {
 
@@ -62,10 +66,68 @@
     };
 
 
+
+    /***************************************************************************
+     *                                                                         *
+     * Constructors                                                            *
+     *                                                                         *
+     **************************************************************************/
+
     public SpinnerBehavior(Spinner<T> spinner) {
-        super(spinner, Collections.emptyList());
+        super(spinner, SPINNER_BINDINGS);
     }
 
+
+
+    /***************************************************************************
+     *                                                                         *
+     * 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;
+
+    protected static final List<KeyBinding> SPINNER_BINDINGS = new ArrayList<KeyBinding>();
+    static {
+        SPINNER_BINDINGS.add(new KeyBinding(UP, "increment-up"));
+        SPINNER_BINDINGS.add(new KeyBinding(RIGHT, "increment-right"));
+        SPINNER_BINDINGS.add(new KeyBinding(LEFT, "decrement-left"));
+        SPINNER_BINDINGS.add(new KeyBinding(DOWN, "decrement-down"));
+    }
+
+    @Override protected void callAction(String name) {
+        boolean vertical = arrowsAreVertical();
+
+        switch (name) {
+            case "increment-up": {
+                if (vertical) increment(1); else traverseUp(); break;
+            }
+            case "increment-right": {
+                if (! vertical) increment(1); else traverseRight(); break;
+            }
+            case "decrement-down": {
+                if (vertical) decrement(1); else traverseDown(); break;
+            }
+            case "decrement-left": {
+                if (! vertical) decrement(1); else traverseLeft(); break;
+            }
+            default: super.callAction(name); break;
+        }
+    }
+
+
+    /***************************************************************************
+     *                                                                         *
+     * API                                                                     *
+     *                                                                         *
+     **************************************************************************/
+
     public void increment(int steps) {
         getControl().increment(steps);
     }
@@ -94,4 +156,20 @@
             timeline.stop();
         }
     }
+
+
+
+    /***************************************************************************
+     *                                                                         *
+     * Implementation                                                          *
+     *                                                                         *
+     **************************************************************************/
+
+    private boolean arrowsAreVertical() {
+        final List<String> styleClass = getControl().getStyleClass();
+
+        return ! (styleClass.contains(Spinner.STYLE_CLASS_ARROWS_ON_LEFT_HORIZONTAL)  ||
+                  styleClass.contains(Spinner.STYLE_CLASS_ARROWS_ON_RIGHT_HORIZONTAL) ||
+                  styleClass.contains(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL));
+    }
 }
\ No newline at end of file
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/SpinnerSkin.java	Tue Aug 19 13:33:52 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/SpinnerSkin.java	Tue Aug 19 15:31:37 2014 +1200
@@ -144,6 +144,18 @@
             }
         });
 
+        // This event filter is to enable keyboard events being delivered to the
+        // spinner when the user has mouse clicked into the TextField area of the
+        // Spinner control. Without this the up/down/left/right arrow keys don't
+        // work when you click inside the TextField area (but they do in the case
+        // of tabbing in).
+        textField.addEventFilter(KeyEvent.ANY, ke -> {
+            if (! spinner.isEditable()) {
+                spinner.fireEvent(ke.copyFor(spinner, spinner));
+                ke.consume();
+            }
+        });
+
         textField.focusedProperty().addListener((ov, t, hasFocus) -> {
             // Fix for RT-29885
             spinner.getProperties().put("FOCUSED", hasFocus);