diff --git a/modules/controls/src/main/java/javafx/scene/control/ListView.java b/modules/controls/src/main/java/javafx/scene/control/ListView.java --- a/modules/controls/src/main/java/javafx/scene/control/ListView.java +++ b/modules/controls/src/main/java/javafx/scene/control/ListView.java @@ -1386,6 +1386,15 @@ **********************************************************************/ /** {@inheritDoc} */ + @Override public void selectAll() { + // when a selectAll happens, the anchor should not change, so we store it + // before, and restore it afterwards + final int anchor = ListCellBehavior.getAnchor(listView, -1); + super.selectAll(); + ListCellBehavior.setAnchor(listView, anchor, false); + } + + /** {@inheritDoc} */ @Override public void clearAndSelect(int row) { ListCellBehavior.setAnchor(listView, row, false); super.clearAndSelect(row); diff --git a/modules/controls/src/main/java/javafx/scene/control/TreeView.java b/modules/controls/src/main/java/javafx/scene/control/TreeView.java --- a/modules/controls/src/main/java/javafx/scene/control/TreeView.java +++ b/modules/controls/src/main/java/javafx/scene/control/TreeView.java @@ -27,6 +27,7 @@ import com.sun.javafx.collections.NonIterableChange; import com.sun.javafx.css.converters.SizeConverter; +import com.sun.javafx.scene.control.behavior.ListCellBehavior; import com.sun.javafx.scene.control.behavior.TreeCellBehavior; import com.sun.javafx.scene.control.skin.TreeViewSkin; @@ -1387,6 +1388,15 @@ **********************************************************************/ /** {@inheritDoc} */ + @Override public void selectAll() { + // when a selectAll happens, the anchor should not change, so we store it + // before, and restore it afterwards + final int anchor = ListCellBehavior.getAnchor(treeView, -1); + super.selectAll(); + ListCellBehavior.setAnchor(treeView, anchor, false); + } + + /** {@inheritDoc} */ @Override public void select(TreeItem obj) { // if (getRowCount() <= 0) return; diff --git a/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java b/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java --- a/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java @@ -41,6 +41,7 @@ import com.sun.javafx.scene.control.behavior.ListCellBehavior; import com.sun.javafx.scene.control.behavior.TableCellBehavior; import com.sun.javafx.scene.control.infrastructure.KeyEventFirer; +import com.sun.javafx.scene.control.infrastructure.KeyModifier; import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.property.ObjectProperty; @@ -1417,4 +1418,45 @@ assertEquals(expectedString, rt_39482_list.get(0)); assertEquals(1, rt_39482_list.size()); } + + @Test public void test_rt_39559_useSM_selectAll() { + test_rt_39559(true); + } + + @Test public void test_rt_39559_useKeyboard_selectAll() { + test_rt_39559(false); + } + + private void test_rt_39559(boolean useSMSelectAll) { + ListView stringListView = new ListView<>(); + stringListView.getItems().addAll("a", "b", "c", "d"); + + MultipleSelectionModel sm = stringListView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + + StageLoader sl = new StageLoader(stringListView); + KeyEventFirer keyboard = new KeyEventFirer(stringListView); + + assertEquals(0, sm.getSelectedItems().size()); + + sm.clearAndSelect(0); + + if (useSMSelectAll) { + sm.selectAll(); + } else { + keyboard.doKeyPress(KeyCode.A, KeyModifier.CTRL); + } + + assertEquals(4, sm.getSelectedItems().size()); + assertEquals(0, (int) ListCellBehavior.getAnchor(stringListView, -1)); + + keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); + + assertEquals(0, (int) ListCellBehavior.getAnchor(stringListView, -1)); + assertEquals(2, sm.getSelectedItems().size()); + assertEquals("a", sm.getSelectedItems().get(0)); + assertEquals("b", sm.getSelectedItems().get(1)); + + sl.dispose(); + } } \ No newline at end of file diff --git a/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java b/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java --- a/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java @@ -37,8 +37,10 @@ import com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList; import com.sun.javafx.scene.control.SelectedCellsMap; +import com.sun.javafx.scene.control.behavior.ListCellBehavior; import com.sun.javafx.scene.control.behavior.TableCellBehavior; import com.sun.javafx.scene.control.infrastructure.KeyEventFirer; +import com.sun.javafx.scene.control.infrastructure.KeyModifier; import com.sun.javafx.scene.control.infrastructure.MouseEventFirer; import com.sun.javafx.scene.control.infrastructure.StageLoader; import com.sun.javafx.scene.control.skin.*; @@ -4644,4 +4646,49 @@ assertEquals(expectedString, rt_39482_list.get(0)); assertEquals(1, rt_39482_list.size()); } + + @Test public void test_rt_39559_useSM_selectAll() { + test_rt_39559(true); + } + + @Test public void test_rt_39559_useKeyboard_selectAll() { + test_rt_39559(false); + } + + private void test_rt_39559(boolean useSMSelectAll) { + TableView stringTableView = new TableView<>(); + stringTableView.getItems().addAll("a","b", "c", "d"); + + TableColumn column = new TableColumn<>("Column"); + column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); + stringTableView.getColumns().add(column); + + TableView.TableViewSelectionModel sm = stringTableView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + + StageLoader sl = new StageLoader(stringTableView); + KeyEventFirer keyboard = new KeyEventFirer(stringTableView); + + assertEquals(0, sm.getSelectedItems().size()); + + sm.clearAndSelect(0); + + if (useSMSelectAll) { + sm.selectAll(); + } else { + keyboard.doKeyPress(KeyCode.A, KeyModifier.CTRL); + } + + assertEquals(4, sm.getSelectedItems().size()); + assertEquals(0, ((TablePosition) TableCellBehavior.getAnchor(stringTableView, null)).getRow()); + + keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); + + assertEquals(0, ((TablePosition) TableCellBehavior.getAnchor(stringTableView, null)).getRow()); + assertEquals(2, sm.getSelectedItems().size()); + assertEquals("a", sm.getSelectedItems().get(0)); + assertEquals("b", sm.getSelectedItems().get(1)); + + sl.dispose(); + } } diff --git a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java --- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java @@ -41,6 +41,7 @@ import com.sun.javafx.scene.control.behavior.TreeCellBehavior; import com.sun.javafx.scene.control.behavior.TreeTableCellBehavior; import com.sun.javafx.scene.control.infrastructure.KeyEventFirer; +import com.sun.javafx.scene.control.infrastructure.KeyModifier; import com.sun.javafx.scene.control.infrastructure.MouseEventFirer; import com.sun.javafx.scene.control.skin.TreeTableCellSkin; import com.sun.javafx.scene.control.test.Data; @@ -4820,4 +4821,59 @@ assertEquals(expectedString, rt_39482_list.get(0).getValue()); assertEquals(1, rt_39482_list.size()); } + + @Test public void test_rt_39559_useSM_selectAll() { + test_rt_39559(true); + } + + @Test public void test_rt_39559_useKeyboard_selectAll() { + test_rt_39559(false); + } + + private void test_rt_39559(boolean useSMSelectAll) { + TreeItem a, b; + TreeItem root = new TreeItem<>("Root"); + root.setExpanded(true); + root.getChildren().addAll( + a = new TreeItem<>("a"), + b = new TreeItem<>("b"), + new TreeItem<>("c"), + new TreeItem<>("d") + ); + + TreeTableView stringTreeTableView = new TreeTableView<>(root); + stringTreeTableView.setShowRoot(false); + + TreeTableColumn column = new TreeTableColumn<>("Column"); + column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue().getValue())); + stringTreeTableView.getColumns().add(column); + + TreeTableView.TreeTableViewSelectionModel sm = stringTreeTableView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + + StageLoader sl = new StageLoader(stringTreeTableView); + KeyEventFirer keyboard = new KeyEventFirer(stringTreeTableView); + + assertEquals(0, sm.getSelectedItems().size()); + + sm.clearAndSelect(0); + + if (useSMSelectAll) { + sm.selectAll(); + } else { + keyboard.doKeyPress(KeyCode.A, KeyModifier.CTRL); + } + + assertEquals(4, sm.getSelectedItems().size()); + assertEquals(0, ((TreeTablePosition) TreeTableCellBehavior.getAnchor(stringTreeTableView, null)).getRow()); + + keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); + + assertEquals(0, ((TreeTablePosition) TreeTableCellBehavior.getAnchor(stringTreeTableView, null)).getRow()); + assertEquals(2, sm.getSelectedItems().size()); + assertEquals(a, sm.getSelectedItems().get(0)); + assertEquals(b, sm.getSelectedItems().get(1)); + + sl.dispose(); + } } diff --git a/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java b/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java --- a/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java +++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java @@ -29,6 +29,7 @@ import com.sun.javafx.scene.control.behavior.ListCellBehavior; import com.sun.javafx.scene.control.behavior.TreeCellBehavior; import com.sun.javafx.scene.control.infrastructure.KeyEventFirer; +import com.sun.javafx.scene.control.infrastructure.KeyModifier; import com.sun.javafx.scene.control.infrastructure.StageLoader; import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils; import com.sun.javafx.scene.control.skin.TextFieldSkin; @@ -2623,4 +2624,55 @@ assertEquals(expectedString, rt_39482_list.get(0).getValue()); assertEquals(1, rt_39482_list.size()); } + + @Test public void test_rt_39559_useSM_selectAll() { + test_rt_39559(true); + } + + @Test public void test_rt_39559_useKeyboard_selectAll() { + test_rt_39559(false); + } + + private void test_rt_39559(boolean useSMSelectAll) { + TreeItem a, b; + TreeItem root = new TreeItem<>("Root"); + root.setExpanded(true); + root.getChildren().addAll( + a = new TreeItem<>("a"), + b = new TreeItem<>("b"), + new TreeItem<>("c"), + new TreeItem<>("d") + ); + + TreeView stringTreeView = new TreeView<>(root); + stringTreeView.setShowRoot(false); + + MultipleSelectionModel> sm = stringTreeView.getSelectionModel(); + sm.setSelectionMode(SelectionMode.MULTIPLE); + + StageLoader sl = new StageLoader(stringTreeView); + KeyEventFirer keyboard = new KeyEventFirer(stringTreeView); + + assertEquals(0, sm.getSelectedItems().size()); + + sm.clearAndSelect(0); + + if (useSMSelectAll) { + sm.selectAll(); + } else { + keyboard.doKeyPress(KeyCode.A, KeyModifier.CTRL); + } + + assertEquals(4, sm.getSelectedItems().size()); + assertEquals(0, (int) TreeCellBehavior.getAnchor(stringTreeView, -1)); + + keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); + + assertEquals(0, (int) TreeCellBehavior.getAnchor(stringTreeView, -1)); + assertEquals(2, sm.getSelectedItems().size()); + assertEquals(a, sm.getSelectedItems().get(0)); + assertEquals(b, sm.getSelectedItems().get(1)); + + sl.dispose(); + } }