diff --git a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java --- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java +++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java @@ -267,14 +268,22 @@ } } - // RT-21444: We need to put the range in in the correct - // order or else the last selected row will not be the - // last item in the selectedItems list of the selection - // model, - if (asc) { - sm.selectRange(minRow, maxRow + 1); + if (minRow == maxRow) { + // RT-32560: This prevents the anchor 'sticking' in + // the wrong place when a range is selected and then + // selection goes back to the anchor position. + // (Refer to the video in RT-32560 for more detail). + sm.select(minRow); } else { - sm.selectRange(maxRow, minRow - 1); + // RT-21444: We need to put the range in the correct + // order or else the last selected row will not be the + // last item in the selectedItems list of the selection + // model, + if (asc) { + sm.selectRange(minRow, maxRow + 1); + } else { + sm.selectRange(maxRow, minRow - 1); + } } } diff --git a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableRowBehavior.java b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableRowBehavior.java --- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableRowBehavior.java +++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableRowBehavior.java @@ -175,14 +175,22 @@ } } - // RT-21444: We need to put the range in in the correct - // order or else the last selected row will not be the - // last item in the selectedItems list of the selection - // model, - if (asc) { - sm.selectRange(minRow, maxRow + 1); + if (minRow == maxRow) { + // RT-32560: This prevents the anchor 'sticking' in + // the wrong place when a range is selected and then + // selection goes back to the anchor position. + // (Refer to the video in RT-32560 for more detail). + sm.select(minRow); } else { - sm.selectRange(maxRow, minRow - 1); + // RT-21444: We need to put the range in the correct + // order or else the last selected row will not be the + // last item in the selectedItems list of the selection + // model, + if (asc) { + sm.selectRange(minRow, maxRow + 1); + } else { + sm.selectRange(maxRow, minRow - 1); + } } } else { sm.clearAndSelect(tableRow.getIndex()); diff --git a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeTableRowBehavior.java b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeTableRowBehavior.java --- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeTableRowBehavior.java +++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeTableRowBehavior.java @@ -195,14 +195,22 @@ } } - // RT-21444: We need to put the range in in the correct - // order or else the last selected row will not be the - // last item in the selectedItems list of the selection - // model, - if (asc) { - sm.selectRange(minRow, maxRow + 1); + if (minRow == maxRow) { + // RT-32560: This prevents the anchor 'sticking' in + // the wrong place when a range is selected and then + // selection goes back to the anchor position. + // (Refer to the video in RT-32560 for more detail). + sm.select(minRow); } else { - sm.selectRange(maxRow, minRow - 1); + // RT-21444: We need to put the range in the correct + // order or else the last selected row will not be the + // last item in the selectedItems list of the selection + // model, + if (asc) { + sm.selectRange(minRow, maxRow + 1); + } else { + sm.selectRange(maxRow, minRow - 1); + } } } else { sm.clearAndSelect(treeTableRow.getIndex()); diff --git a/modules/controls/src/test/java/javafx/scene/control/ListViewMouseInputTest.java b/modules/controls/src/test/java/javafx/scene/control/ListViewMouseInputTest.java --- a/modules/controls/src/test/java/javafx/scene/control/ListViewMouseInputTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/ListViewMouseInputTest.java @@ -243,4 +243,29 @@ assertEquals("Row 5", sm.getSelectedItem()); assertEquals("Row 5", sm.getSelectedItems().get(1)); } + + @Test public void test_rt32560_cell() { + final int items = 8; + listView.getItems().clear(); + for (int i = 0; i < items; i++) { + listView.getItems().add("Row " + i); + } + + final MultipleSelectionModel sm = listView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + sm.clearAndSelect(0); + + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + + VirtualFlowTestUtils.clickOnRow(listView, 5, KeyModifier.SHIFT); + assertEquals(5, sm.getSelectedIndex()); + assertEquals(5, fm.getFocusedIndex()); + assertEquals(6, sm.getSelectedItems().size()); + + VirtualFlowTestUtils.clickOnRow(listView, 0, KeyModifier.SHIFT); + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + assertEquals(1, sm.getSelectedItems().size()); + } } diff --git a/modules/controls/src/test/java/javafx/scene/control/TableViewMouseInputTest.java b/modules/controls/src/test/java/javafx/scene/control/TableViewMouseInputTest.java --- a/modules/controls/src/test/java/javafx/scene/control/TableViewMouseInputTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/TableViewMouseInputTest.java @@ -332,4 +332,54 @@ assertEquals("Row 4", sm.getSelectedItem()); assertEquals("Row 4", sm.getSelectedItems().get(1)); } + + @Test public void test_rt32560_cell() { + final int items = 8; + tableView.getItems().clear(); + for (int i = 0; i < items; i++) { + tableView.getItems().add("Row " + i); + } + + final MultipleSelectionModel sm = tableView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + sm.clearAndSelect(0); + + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + + VirtualFlowTestUtils.clickOnRow(tableView, 5, KeyModifier.SHIFT); + assertEquals(5, sm.getSelectedIndex()); + assertEquals(5, fm.getFocusedIndex()); + assertEquals(6, sm.getSelectedItems().size()); + + VirtualFlowTestUtils.clickOnRow(tableView, 0, KeyModifier.SHIFT); + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + assertEquals(1, sm.getSelectedItems().size()); + } + + @Test public void test_rt32560_row() { + final int items = 8; + tableView.getItems().clear(); + for (int i = 0; i < items; i++) { + tableView.getItems().add("Row " + i); + } + + final MultipleSelectionModel sm = tableView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + sm.clearAndSelect(0); + + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + + VirtualFlowTestUtils.clickOnRow(tableView, 5, true, KeyModifier.SHIFT); + assertEquals(5, sm.getSelectedIndex()); + assertEquals(5, fm.getFocusedIndex()); + assertEquals(6, sm.getSelectedItems().size()); + + VirtualFlowTestUtils.clickOnRow(tableView, 0, true, KeyModifier.SHIFT); + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + assertEquals(1, sm.getSelectedItems().size()); + } } diff --git a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java --- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java @@ -402,4 +402,57 @@ VirtualFlowTestUtils.clickOnRow(tableView, selectRow + 1, true, KeyModifier.SHIFT); assertEquals("Row 4", sm.getSelectedItem().getValue()); } + + @Test public void test_rt32560_cell() { + final int items = 8; + root.getChildren().clear(); + for (int i = 0; i < items; i++) { + root.getChildren().add(new TreeItem<>("Row " + i)); + } + + final MultipleSelectionModel sm = tableView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + sm.clearAndSelect(0); + + assertEquals(0, sm.getSelectedIndex()); + assertEquals(root, sm.getSelectedItem()); + assertEquals(0, fm.getFocusedIndex()); + + VirtualFlowTestUtils.clickOnRow(tableView, 5, KeyModifier.SHIFT); + assertEquals(5, sm.getSelectedIndex()); + assertEquals(5, fm.getFocusedIndex()); + assertEquals(6, sm.getSelectedItems().size()); + + VirtualFlowTestUtils.clickOnRow(tableView, 0, KeyModifier.SHIFT); + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + assertEquals(1, sm.getSelectedItems().size()); + } + + @Test public void test_rt32560_row() { + final int items = 8; + root.getChildren().clear(); + for (int i = 0; i < items; i++) { + root.getChildren().add(new TreeItem<>("Row " + i)); + } + + tableView.setShowRoot(true); + final MultipleSelectionModel sm = tableView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + sm.clearAndSelect(0); + + assertEquals(0, sm.getSelectedIndex()); + assertEquals(root, sm.getSelectedItem()); + assertEquals(0, fm.getFocusedIndex()); + + VirtualFlowTestUtils.clickOnRow(tableView, 5, true, KeyModifier.SHIFT); + assertEquals(5, sm.getSelectedIndex()); + assertEquals(5, fm.getFocusedIndex()); + assertEquals(sm.getSelectedItems().toString(), 6, sm.getSelectedItems().size()); + + VirtualFlowTestUtils.clickOnRow(tableView, 0, true, KeyModifier.SHIFT); + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + assertEquals(1, sm.getSelectedItems().size()); + } } diff --git a/modules/controls/src/test/java/javafx/scene/control/TreeViewMouseInputTest.java b/modules/controls/src/test/java/javafx/scene/control/TreeViewMouseInputTest.java --- a/modules/controls/src/test/java/javafx/scene/control/TreeViewMouseInputTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewMouseInputTest.java @@ -312,4 +312,30 @@ assertEquals("Row 4", sm.getSelectedItem().getValue()); assertEquals("Row 4", sm.getSelectedItems().get(1).getValue()); } + + @Test public void test_rt32560() { + final int items = 8; + root.getChildren().clear(); + for (int i = 0; i < items; i++) { + root.getChildren().add(new TreeItem<>("Row " + i)); + } + + final MultipleSelectionModel sm = treeView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + sm.clearAndSelect(0); + + assertEquals(0, sm.getSelectedIndex()); + assertEquals(root, sm.getSelectedItem()); + assertEquals(0, fm.getFocusedIndex()); + + VirtualFlowTestUtils.clickOnRow(treeView, 5, KeyModifier.SHIFT); + assertEquals(5, sm.getSelectedIndex()); + assertEquals(5, fm.getFocusedIndex()); + assertEquals(6, sm.getSelectedItems().size()); + + VirtualFlowTestUtils.clickOnRow(treeView, 0, KeyModifier.SHIFT); + assertEquals(0, sm.getSelectedIndex()); + assertEquals(0, fm.getFocusedIndex()); + assertEquals(1, sm.getSelectedItems().size()); + } }