changeset 6347:717abe6489a8

RT-35840: [ComboBox] Keypress does not move selection or allow text entry when editable
author jgiles
date Mon, 24 Feb 2014 10:19:17 +1300
parents 5c228c4f399d
children 53fde3ac0336
files modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java modules/controls/src/test/java/com/sun/javafx/scene/control/infrastructure/KeyEventFirer.java modules/controls/src/test/java/javafx/scene/control/ComboBoxTest.java
diffstat 3 files changed, 46 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Wed Feb 19 10:30:17 2014 +1300
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Mon Feb 24 10:19:17 2014 +1300
@@ -144,20 +144,33 @@
             }
         });
 
+        comboBox.addEventFilter(KeyEvent.ANY, new EventHandler<KeyEvent>() {
+            @Override public void handle(KeyEvent ke) {
+                if (textField == null) return;
+
+                // This prevents a stack overflow from our rebroadcasting of the
+                // event to the textfield that occurs in the final else statement
+                // of the conditions below.
+                if (ke.getTarget().equals(textField)) return;
+
+                // Fix for the regression noted in a comment in RT-29885.
+                // This forwards the event down into the TextField when
+                // the key event is actually received by the ComboBox.
+                textField.fireEvent(ke.copyFor(textField, textField));
+                ke.consume();
+            }
+        });
+
         if (textField != null) {
             textField.addEventFilter(KeyEvent.ANY, new EventHandler<KeyEvent>() {
                 @Override public void handle(KeyEvent ke) {
                     if (textField == null) return;
 
-                    // This prevents a stack overflow from our rebroadcasting of the
-                    // event to the textfield that occurs in the final else statement
-                    // of the conditions below.
-                    if (ke.getTarget().equals(textField)) return;
-
                     // When the user hits the enter or F4 keys, we respond before
                     // ever giving the event to the TextField.
                     if (ke.getCode() == KeyCode.ENTER) {
                         setTextFromTextFieldIntoComboBoxValue();
+                        ke.consume();
                         return;
                     } else if (ke.getCode() == KeyCode.F4 && ke.getEventType() == KeyEvent.KEY_RELEASED) {
                         if (comboBox.isShowing()) comboBox.hide();
@@ -172,12 +185,6 @@
                         // events and stop them from going any further.
                         ke.consume();
                         return;
-                    } else {
-                        // Fix for the regression noted in a comment in RT-29885.
-                        // This forwards the event down into the TextField when
-                        // the key event is actually received by the ComboBox.
-                        textField.fireEvent(ke.copyFor(textField, textField));
-                        ke.consume();
                     }
                 }
             });
--- a/modules/controls/src/test/java/com/sun/javafx/scene/control/infrastructure/KeyEventFirer.java	Wed Feb 19 10:30:17 2014 +1300
+++ b/modules/controls/src/test/java/com/sun/javafx/scene/control/infrastructure/KeyEventFirer.java	Mon Feb 24 10:19:17 2014 +1300
@@ -61,6 +61,10 @@
     public void doKeyPress(KeyCode keyCode, KeyModifier... modifiers) {
         fireEvents(createMirroredEvents(keyCode, modifiers));
     }
+
+    public void doKeyTyped(KeyCode keyCode, KeyModifier... modifiers) {
+        fireEvents(createEvent(keyCode, KeyEvent.KEY_TYPED, modifiers));
+    }
     
     private void fireEvents(KeyEvent... events) {
         for (KeyEvent evt : events) {
@@ -78,12 +82,12 @@
     private KeyEvent createEvent(KeyCode keyCode, EventType<KeyEvent> evtType, KeyModifier... modifiers) {
         List<KeyModifier> ml = Arrays.asList(modifiers);
 
-        return new KeyEvent( null,
-                target, // EventTarget
-                evtType,  // eventType
-                null,     // Character (unused unless KeyCode == KEY_TYPED
-                null,     // text
-                keyCode, // KeyCode
+        return new KeyEvent(null,
+                target,                            // EventTarget
+                evtType,                           // eventType
+                evtType == KeyEvent.KEY_TYPED ? keyCode.impl_getChar() : null,  // Character (unused unless evtType == KEY_TYPED)
+                keyCode.impl_getChar(),            // text
+                keyCode,                           // KeyCode
                 ml.contains(KeyModifier.SHIFT),    // shiftDown
                 ml.contains(KeyModifier.CTRL),     // ctrlDown
                 ml.contains(KeyModifier.ALT),      // altDown
--- a/modules/controls/src/test/java/javafx/scene/control/ComboBoxTest.java	Wed Feb 19 10:30:17 2014 +1300
+++ b/modules/controls/src/test/java/javafx/scene/control/ComboBoxTest.java	Mon Feb 24 10:19:17 2014 +1300
@@ -1243,4 +1243,22 @@
         assertEquals("bbc", combo.getEditor().getText());
         assertEquals("bbc", combo.getSelectionModel().getSelectedItem());
     }
+
+    @Test public void test_rt35840() {
+        final ComboBox<String> cb = new ComboBox<String>();
+        cb.setEditable(true);
+        StageLoader sl = new StageLoader(cb);
+        cb.requestFocus();
+
+        KeyEventFirer keyboard = new KeyEventFirer(cb);
+        keyboard.doKeyTyped(KeyCode.T);
+        keyboard.doKeyTyped(KeyCode.E);
+        keyboard.doKeyTyped(KeyCode.S);
+        keyboard.doKeyTyped(KeyCode.T);
+        assertEquals("TEST", cb.getEditor().getText());
+
+        assertNull(cb.getValue());
+        keyboard.doKeyPress(KeyCode.ENTER);
+        assertEquals("TEST", cb.getValue());
+    }
 }