changeset 5237:2f48570d437f

RT-33301: ctrl+shift+down is looping in all virtualised controls RT-33307: Ctrl+shift+up/down should map to up/down in virtualised controls when in single selection mode
author jgiles
date Wed, 02 Oct 2013 12:29:14 +1300
parents 988cdf5dfc94
children dfe5f213aab4
files modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java modules/controls/src/test/java/javafx/scene/control/ListViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java
diffstat 7 files changed, 525 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java	Wed Oct 02 10:10:38 2013 +1300
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java	Wed Oct 02 12:29:14 2013 +1300
@@ -749,6 +749,11 @@
     private void discontinuousSelectPreviousRow() {
         MultipleSelectionModel<T> sm = getControl().getSelectionModel();
         if (sm == null) return;
+
+        if (sm.getSelectionMode() != SelectionMode.MULTIPLE) {
+            selectPreviousRow();
+            return;
+        }
         
         FocusModel<T> fm = getControl().getFocusModel();
         if (fm == null) return;
@@ -769,12 +774,19 @@
     private void discontinuousSelectNextRow() {
         MultipleSelectionModel<T> sm = getControl().getSelectionModel();
         if (sm == null) return;
+
+        if (sm.getSelectionMode() != SelectionMode.MULTIPLE) {
+            selectNextRow();
+            return;
+        }
         
         FocusModel<T> fm = getControl().getFocusModel();
         if (fm == null) return;
 
         int focusIndex = fm.getFocusedIndex();
         final int newFocusIndex = focusIndex + 1;
+        if (newFocusIndex >= getRowCount()) return;
+
         int startIndex = focusIndex;
         if (isShiftDown) {
             startIndex = getAnchor() == -1 ? focusIndex : getAnchor();
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java	Wed Oct 02 10:10:38 2013 +1300
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java	Wed Oct 02 12:29:14 2013 +1300
@@ -1091,6 +1091,11 @@
     protected void discontinuousSelectPreviousRow() {
         TableSelectionModel sm = getSelectionModel();
         if (sm == null) return;
+
+        if (sm.getSelectionMode() != SelectionMode.MULTIPLE) {
+            selectPreviousRow();
+            return;
+        }
         
         TableFocusModel fm = getFocusModel();
         if (fm == null) return;
@@ -1119,12 +1124,19 @@
     protected void discontinuousSelectNextRow() {
         TableSelectionModel sm = getSelectionModel();
         if (sm == null) return;
-        
+
+        if (sm.getSelectionMode() != SelectionMode.MULTIPLE) {
+            selectNextRow();
+            return;
+        }
+
         TableFocusModel fm = getFocusModel();
         if (fm == null) return;
 
         int focusIndex = fm.getFocusedIndex();
         final int newFocusIndex = focusIndex + 1;
+        if (newFocusIndex >= getItemCount()) return;
+
         int startIndex = focusIndex;
         final TableColumnBase col = sm.isCellSelectionEnabled() ? getFocusedCell().getTableColumn() : null;
         if (isShiftDown) {
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java	Wed Oct 02 10:10:38 2013 +1300
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java	Wed Oct 02 12:29:14 2013 +1300
@@ -740,6 +740,11 @@
     private void discontinuousSelectPreviousRow() {
         MultipleSelectionModel<TreeItem<T>> sm = getControl().getSelectionModel();
         if (sm == null) return;
+
+        if (sm.getSelectionMode() != SelectionMode.MULTIPLE) {
+            selectPreviousRow();
+            return;
+        }
         
         FocusModel<TreeItem<T>> fm = getControl().getFocusModel();
         if (fm == null) return;
@@ -762,12 +767,19 @@
     private void discontinuousSelectNextRow() {
         MultipleSelectionModel<TreeItem<T>> sm = getControl().getSelectionModel();
         if (sm == null) return;
+
+        if (sm.getSelectionMode() != SelectionMode.MULTIPLE) {
+            selectNextRow();
+            return;
+        }
         
         FocusModel<TreeItem<T>> fm = getControl().getFocusModel();
         if (fm == null) return;
 
         int focusIndex = fm.getFocusedIndex();
         final int newFocusIndex = focusIndex + 1;
+        if (newFocusIndex >= getControl().getExpandedItemCount()) return;
+
         int startIndex = focusIndex;
         if (isShiftDown) {
             startIndex = getAnchor() == -1 ? focusIndex : getAnchor();
--- a/modules/controls/src/test/java/javafx/scene/control/ListViewKeyInputTest.java	Wed Oct 02 10:10:38 2013 +1300
+++ b/modules/controls/src/test/java/javafx/scene/control/ListViewKeyInputTest.java	Wed Oct 02 12:29:14 2013 +1300
@@ -1529,4 +1529,124 @@
         assertTrue(isSelected(7,5,4,3));
         assertEquals(4, sm.getSelectedItems().size());
     }
+
+    @Test public void test_rt33301_multipleSelection_down() {
+        final int items = 5;
+        listView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            listView.getItems().add("Row " + i);
+        }
+
+        final FocusModel fm = listView.getFocusModel();
+        final MultipleSelectionModel sm = listView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1));
+        assertTrue(isSelected(2,3,4));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1));
+        assertTrue(isSelected(2,3,4));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue("Focus index incorrectly at: " + fm.getFocusedIndex(), fm.isFocused(4));
+    }
+
+    @Test public void test_rt33301_multipleSelection_up() {
+        final int items = 5;
+        listView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            listView.getItems().add("Row " + i);
+        }
+
+        final FocusModel fm = listView.getFocusModel();
+        final MultipleSelectionModel sm = listView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(3,4));
+        assertTrue(isSelected(0,1,2));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(3,4));
+        assertTrue(isSelected(0,1,2));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+    }
+
+    @Test public void test_rt33301_singleSelection_down() {
+        final int items = 5;
+        listView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            listView.getItems().add("Row " + i);
+        }
+
+        final FocusModel fm = listView.getFocusModel();
+        final MultipleSelectionModel sm = listView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isSelected(4));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isSelected(4));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+    }
+
+    @Test public void test_rt33301_singleSelection_up() {
+        final int items = 5;
+        listView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            listView.getItems().add("Row " + i);
+        }
+
+        final FocusModel fm = listView.getFocusModel();
+        final MultipleSelectionModel sm = listView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(1,2,3,4));
+        assertTrue(isSelected(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(1,2,3,4));
+        assertTrue(isSelected(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java	Wed Oct 02 10:10:38 2013 +1300
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java	Wed Oct 02 12:29:14 2013 +1300
@@ -2314,4 +2314,128 @@
         assertTrue(isSelected(7,5,4,3));
         assertEquals(4, sm.getSelectedItems().size());
     }
+
+    @Test public void test_rt33301_multipleSelection_down() {
+        final int items = 5;
+        tableView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            tableView.getItems().add("Row " + i);
+        }
+
+        final TableFocusModel fm = tableView.getFocusModel();
+        final TableSelectionModel sm = tableView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+        sm.setCellSelectionEnabled(false);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1));
+        assertTrue(isSelected(2,3,4));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1));
+        assertTrue(isSelected(2,3,4));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue("Focus index incorrectly at: " + fm.getFocusedIndex(), fm.isFocused(4));
+    }
+
+    @Test public void test_rt33301_multipleSelection_up() {
+        final int items = 5;
+        tableView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            tableView.getItems().add("Row " + i);
+        }
+
+        final TableFocusModel fm = tableView.getFocusModel();
+        final TableSelectionModel sm = tableView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+        sm.setCellSelectionEnabled(false);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(3,4));
+        assertTrue(isSelected(0,1,2));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(3,4));
+        assertTrue(isSelected(0,1,2));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+    }
+
+    @Test public void test_rt33301_singleSelection_down() {
+        final int items = 5;
+        tableView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            tableView.getItems().add("Row " + i);
+        }
+
+        final TableFocusModel fm = tableView.getFocusModel();
+        final TableSelectionModel sm = tableView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.setCellSelectionEnabled(false);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isSelected(4));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isSelected(4));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+    }
+
+    @Test public void test_rt33301_singleSelection_up() {
+        final int items = 5;
+        tableView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            tableView.getItems().add("Row " + i);
+        }
+
+        final TableFocusModel fm = tableView.getFocusModel();
+        final TableSelectionModel sm = tableView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.setCellSelectionEnabled(false);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(1,2,3,4));
+        assertTrue(isSelected(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(1,2,3,4));
+        assertTrue(isSelected(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Wed Oct 02 10:10:38 2013 +1300
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Wed Oct 02 12:29:14 2013 +1300
@@ -2789,4 +2789,128 @@
         assertTrue(isSelected(7,5,4,3));
         assertEquals(4, sm.getSelectedItems().size());
     }
+
+    @Test public void test_rt33301_multipleSelection_down() {
+        final int items = 4;
+        root.getChildren().clear();
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        final TableFocusModel fm = tableView.getFocusModel();
+        final TableSelectionModel sm = tableView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+        sm.setCellSelectionEnabled(false);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1));
+        assertTrue(isSelected(2,3,4));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1));
+        assertTrue(isSelected(2,3,4));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue("Focus index incorrectly at: " + fm.getFocusedIndex(), fm.isFocused(4));
+    }
+
+    @Test public void test_rt33301_multipleSelection_up() {
+        final int items = 4;
+        root.getChildren().clear();
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        final TableFocusModel fm = tableView.getFocusModel();
+        final TableSelectionModel sm = tableView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+        sm.setCellSelectionEnabled(false);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(3,4));
+        assertTrue(isSelected(0,1,2));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(3,4));
+        assertTrue(isSelected(0,1,2));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+    }
+
+    @Test public void test_rt33301_singleSelection_down() {
+        final int items = 4;
+        root.getChildren().clear();
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        final TableFocusModel fm = tableView.getFocusModel();
+        final TableSelectionModel sm = tableView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.setCellSelectionEnabled(false);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isSelected(4));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isSelected(4));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+    }
+
+    @Test public void test_rt33301_singleSelection_up() {
+        final int items = 4;
+        root.getChildren().clear();
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        final TableFocusModel fm = tableView.getFocusModel();
+        final TableSelectionModel sm = tableView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.setCellSelectionEnabled(false);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(1,2,3,4));
+        assertTrue(isSelected(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(1,2,3,4));
+        assertTrue(isSelected(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java	Wed Oct 02 10:10:38 2013 +1300
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java	Wed Oct 02 12:29:14 2013 +1300
@@ -1722,4 +1722,124 @@
         assertTrue(isSelected(7,5,4,3));
         assertEquals(4, sm.getSelectedItems().size());
     }
+
+    @Test public void test_rt33301_multipleSelection_down() {
+        final int items = 4;
+        root.getChildren().clear();
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        final FocusModel fm = treeView.getFocusModel();
+        final MultipleSelectionModel sm = treeView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1));
+        assertTrue(isSelected(2,3,4));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1));
+        assertTrue(isSelected(2,3,4));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue("Focus index incorrectly at: " + fm.getFocusedIndex(), fm.isFocused(4));
+    }
+
+    @Test public void test_rt33301_multipleSelection_up() {
+        final int items = 4;
+        root.getChildren().clear();
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        final FocusModel fm = treeView.getFocusModel();
+        final MultipleSelectionModel sm = treeView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(3,4));
+        assertTrue(isSelected(0,1,2));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(3,4));
+        assertTrue(isSelected(0,1,2));
+        assertEquals(3, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+    }
+
+    @Test public void test_rt33301_singleSelection_down() {
+        final int items = 4;
+        root.getChildren().clear();
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        final FocusModel fm = treeView.getFocusModel();
+        final MultipleSelectionModel sm = treeView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isSelected(4));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isSelected(4));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(4));
+    }
+
+    @Test public void test_rt33301_singleSelection_up() {
+        final int items = 4;
+        root.getChildren().clear();
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        final FocusModel fm = treeView.getFocusModel();
+        final MultipleSelectionModel sm = treeView.getSelectionModel();
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.clearAndSelect(2);
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(1,2,3,4));
+        assertTrue(isSelected(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
+        Toolkit.getToolkit().firePulse();
+        assertTrue(isNotSelected(1,2,3,4));
+        assertTrue(isSelected(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertTrue(fm.isFocused(0));
+    }
 }