diff --git a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/ComboBoxListViewBehavior.java b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/ComboBoxListViewBehavior.java index c40b69b6a94..3fb031bd3c2 100644 --- a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/ComboBoxListViewBehavior.java +++ b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/ComboBoxListViewBehavior.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2021, 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 @@ -26,9 +26,55 @@ package com.sun.javafx.scene.control.behavior; import javafx.scene.control.ComboBox; +import javafx.scene.control.ComboBoxBase; +import javafx.scene.control.SelectionModel; +import com.sun.javafx.scene.control.inputmap.InputMap; + +import static javafx.scene.input.KeyCode.DOWN; +import static javafx.scene.input.KeyCode.UP; public class ComboBoxListViewBehavior<T> extends ComboBoxBaseBehavior<T> { + + /*************************************************************************** + * * + * Constructors * + * * + **************************************************************************/ + + /** + * + */ public ComboBoxListViewBehavior(final ComboBox<T> comboBox) { super(comboBox); + + // Add these bindings as a child input map, so they take precedence + InputMap<ComboBoxBase<T>> comboBoxListViewInputMap = new InputMap<>(comboBox); + comboBoxListViewInputMap.getMappings().addAll( + new InputMap.KeyMapping(UP, e -> selectPrevious()), + new InputMap.KeyMapping(DOWN, e -> selectNext()) + ); + addDefaultChildMap(getInputMap(), comboBoxListViewInputMap); + } + + /*************************************************************************** + * * + * Key event handling * + * * + **************************************************************************/ + + private ComboBox<T> getComboBox() { + return (ComboBox<T>) getNode(); + } + + private void selectPrevious() { + SelectionModel<T> sm = getComboBox().getSelectionModel(); + if (sm == null) return; + sm.selectPrevious(); + } + + private void selectNext() { + SelectionModel<T> sm = getComboBox().getSelectionModel(); + if (sm == null) return; + sm.selectNext(); } } diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/ComboBoxTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/ComboBoxTest.java index cbd090eb0f2..17aaa5304e9 100644 --- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/ComboBoxTest.java +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/ComboBoxTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, 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 @@ -1308,6 +1308,27 @@ public void defaultConverterCanHandleIncorrectType_2() { assertTrue(cb.isShowing()); } + @Test public void testEditorKeyInputsWhenPopupIsNotShowing() { + final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b")); + sl = new StageLoader(cb); + KeyEventFirer keyboard = new KeyEventFirer(cb); + cb.requestFocus(); + + // Sanity + assertFalse(cb.isShowing()); + assertEquals(null, cb.getValue()); + + // Test DOWN and UP key + keyboard.doKeyPress(KeyCode.DOWN); + assertEquals("a", cb.getValue()); + keyboard.doKeyPress(KeyCode.DOWN); + assertEquals("b", cb.getValue()); + keyboard.doKeyPress(KeyCode.UP); + assertEquals("a", cb.getValue()); + keyboard.doKeyPress(KeyCode.UP); + assertEquals("a", cb.getValue()); + } + @Test public void testEditorKeyInputsWhenPopupIsShowing() { final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c")); cb.setEditable(true);