/* * Copyright (c) 2010, 2014, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javafx.scene.control; import com.sun.javafx.scene.control.infrastructure.ControlTestUtils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.*; import com.sun.javafx.scene.control.infrastructure.StageLoader; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.scene.control.ListView.ListViewFocusModel; import javafx.scene.control.TableView.TableViewFocusModel; import javafx.scene.control.TableView.TableViewSelectionModel; import javafx.scene.control.TreeTableView.TreeTableViewFocusModel; import javafx.scene.control.TreeTableView.TreeTableViewSelectionModel; import javafx.scene.control.TreeView.TreeViewFocusModel; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils; /** * Unit tests for the SelectionModel abstract class used by ListView * and TreeView. This unit test attempts to test all known implementations, and * as such contains some conditional logic to handle the various controls as * simply as possible. */ @RunWith(Parameterized.class) public class MultipleSelectionModelImplTest { private MultipleSelectionModel model; private FocusModel focusModel; private Class modelClass; private Control currentControl; // ListView private ListView listView; // ListView model data private static ObservableList defaultData = FXCollections.observableArrayList(); private static ObservableList data = FXCollections.observableArrayList(); private static final String ROW_1_VALUE = "Row 1"; private static final String ROW_2_VALUE = "Row 2"; private static final String ROW_3_VALUE = "Long Row 3"; private static final String ROW_5_VALUE = "Row 5"; private static final String ROW_20_VALUE = "Row 20"; // TreeView private TreeView treeView; private TreeItem root; private TreeItem ROW_2_TREE_VALUE; private TreeItem ROW_5_TREE_VALUE; // TreeTableView private TreeTableView treeTableView; // TableView private TableView tableView; @Parameters public static Collection implementations() { return Arrays.asList(new Object[][] { { ListView.ListViewBitSetSelectionModel.class }, { TreeView.TreeViewBitSetSelectionModel.class }, { TableView.TableViewArrayListSelectionModel.class }, { TreeTableView.TreeTableViewArrayListSelectionModel.class }, }); } public MultipleSelectionModelImplTest(Class modelClass) { this.modelClass = modelClass; } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { // ListView init defaultData.setAll(ROW_1_VALUE, ROW_2_VALUE, ROW_3_VALUE, "Row 4", ROW_5_VALUE, "Row 6", "Row 7", "Row 8", "Row 9", "Row 10", "Row 11", "Row 12", "Row 13", "Row 14", "Row 15", "Row 16", "Row 17", "Row 18", "Row 19", ROW_20_VALUE); data.setAll(defaultData); listView = new ListView<>(data); // --- ListView init // TreeView init root = new TreeItem<>(ROW_1_VALUE); root.setExpanded(true); for (int i = 1; i < data.size(); i++) { root.getChildren().add(new TreeItem<>(data.get(i))); } ROW_2_TREE_VALUE = root.getChildren().get(0); ROW_5_TREE_VALUE = root.getChildren().get(3); treeView = new TreeView(root); // --- TreeView init // TreeTableView init treeTableView = new TreeTableView(root); // --- TreeView init // TableView init tableView = new TableView(); tableView.setItems(data); // --- TableView init try { // reset the data model data = FXCollections.observableArrayList(); data.setAll(defaultData); // we create a new SelectionModel per test to ensure it is always back // at the default settings if (modelClass.equals(ListView.ListViewBitSetSelectionModel.class)) { // recreate the selection model model = modelClass.getConstructor(ListView.class).newInstance(listView); listView.setSelectionModel((MultipleSelectionModel)model); // create a new focus model focusModel = new ListViewFocusModel(listView); listView.setFocusModel(focusModel); currentControl = listView; } else if (modelClass.equals(TreeView.TreeViewBitSetSelectionModel.class)) { model = modelClass.getConstructor(TreeView.class).newInstance(treeView); treeView.setSelectionModel((MultipleSelectionModel)model); focusModel = treeView.getFocusModel(); // create a new focus model focusModel = new TreeViewFocusModel(treeView); treeView.setFocusModel(focusModel); currentControl = treeView; } else if (TableViewSelectionModel.class.isAssignableFrom(modelClass)) { // recreate the selection model model = modelClass.getConstructor(TableView.class).newInstance(tableView); tableView.setSelectionModel((TableViewSelectionModel) model); // create a new focus model focusModel = new TableViewFocusModel(tableView); tableView.setFocusModel((TableViewFocusModel) focusModel); currentControl = tableView; } else if (TreeTableViewSelectionModel.class.isAssignableFrom(modelClass)) { // recreate the selection model model = modelClass.getConstructor(TreeTableView.class).newInstance(treeTableView); treeTableView.setSelectionModel((TreeTableViewSelectionModel) model); // create a new focus model focusModel = new TreeTableViewFocusModel(treeTableView); treeTableView.setFocusModel((TreeTableViewFocusModel) focusModel); currentControl = treeTableView; } // ensure the selection mode is set to multiple model.setSelectionMode(SelectionMode.MULTIPLE); } catch (Exception ex) { ex.printStackTrace(); } } @After public void tearDown() { model = null; } private Object getValue(Object item) { if (item instanceof TreeItem) { return ((TreeItem)item).getValue(); } return item; } private String indices(MultipleSelectionModel sm) { return "Selected Indices: " + sm.getSelectedIndices(); } private String items(MultipleSelectionModel sm) { return "Selected Items: " + sm.getSelectedItems(); } private MultipleSelectionModel msModel() { return model; } private boolean isTree() { return model instanceof TreeView.TreeViewBitSetSelectionModel || model instanceof TreeTableView.TreeTableViewArrayListSelectionModel; } private void ensureInEmptyState() { assertEquals(-1, model.getSelectedIndex()); assertNull(model.getSelectedItem()); if (focusModel != null) { assertEquals(-1, focusModel.getFocusedIndex()); assertNull(focusModel.getFocusedItem()); } assertNotNull(msModel().getSelectedIndices()); assertNotNull(msModel().getSelectedItems()); assertEquals(0, msModel().getSelectedIndices().size()); assertEquals(0, msModel().getSelectedItems().size()); } @Test public void ensureInDefaultState() { assertEquals(-1, model.getSelectedIndex()); assertNull(model.getSelectedItem()); if (focusModel != null) { assertEquals(0, focusModel.getFocusedIndex()); assertNotNull(focusModel.getFocusedItem()); } assertNotNull(msModel().getSelectedIndices()); assertNotNull(msModel().getSelectedItems()); assertEquals(0, msModel().getSelectedIndices().size()); assertEquals(0, msModel().getSelectedItems().size()); } @Test public void selectValidIndex() { int index = 4; model.clearSelection(); model.select(index); assertEquals(index, model.getSelectedIndex()); assertNotNull(model.getSelectedItem()); assertEquals(ROW_5_VALUE, getValue(model.getSelectedItem())); if (focusModel != null) { assertEquals(index, focusModel.getFocusedIndex()); assertNotNull(focusModel.getFocusedItem()); assertEquals(ROW_5_VALUE, getValue(focusModel.getFocusedItem())); } assertNotNull(msModel().getSelectedIndices()); assertNotNull(msModel().getSelectedItems()); assertEquals(1, msModel().getSelectedIndices().size()); assertEquals(index, msModel().getSelectedIndices().get(0)); assertEquals(1, msModel().getSelectedItems().size()); assertEquals(ROW_5_VALUE, getValue(msModel().getSelectedItems().get(0))); } @Test public void testSelectAllWithSingleSelection() { msModel().setSelectionMode(SelectionMode.SINGLE); msModel().selectAll(); ensureInDefaultState(); } @Test public void testSelectAllWithMultipleSelection() { msModel().clearSelection(); msModel().selectAll(); assertEquals(19, model.getSelectedIndex()); assertNotNull(model.getSelectedItem()); assertEquals(ROW_20_VALUE, getValue(model.getSelectedItem())); assertEquals(19, focusModel.getFocusedIndex()); assertNotNull(focusModel.getFocusedItem()); assertEquals(ROW_20_VALUE, getValue(focusModel.getFocusedItem())); assertNotNull(msModel().getSelectedIndices()); assertNotNull(msModel().getSelectedItems()); assertEquals(20, msModel().getSelectedIndices().size()); assertEquals(20, msModel().getSelectedItems().size()); } @Test public void clearAllSelection() { msModel().selectAll(); model.clearSelection(); ensureInEmptyState(); } @Test public void clearPartialSelectionWithSingleSelection() { model.clearSelection(); assertFalse(model.isSelected(5)); model.select(5); assertTrue(model.isSelected(5)); model.clearSelection(5); assertFalse(model.isSelected(5)); assertEquals(0, msModel().getSelectedIndices().size()); assertEquals(0, msModel().getSelectedItems().size()); } @Test public void clearPartialSelectionWithMultipleSelection() { msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectAll(); model.clearSelection(5); assertTrue(model.isSelected(4)); assertFalse(model.isSelected(5)); assertTrue(model.isSelected(6)); } @Test public void testSelectedIndicesObservableListIsEmpty() { assertTrue(msModel().getSelectedIndices().isEmpty()); } @Test public void testSelectedIndicesIteratorIsNotNull() { assertNotNull(msModel().getSelectedIndices().iterator()); } @Test public void testSelectedIndicesIteratorHasNoNext() { assertFalse(msModel().getSelectedIndices().iterator().hasNext()); } @Test public void testSelectedIndicesIteratorWorksWithSingleSelection() { msModel().clearSelection(); model.select(5); Iterator it = msModel().getSelectedIndices().iterator(); assertEquals(5, (int) it.next()); assertFalse(it.hasNext()); } @Test public void testSelectedIndicesIteratorWorksWithMultipleSelection() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectIndices(1, 2, 5); Iterator it = msModel().getSelectedIndices().iterator(); assertEquals(indices(msModel()), 1, (int) it.next()); assertEquals(indices(msModel()), 2, (int) it.next()); assertEquals(indices(msModel()), 5, (int) it.next()); assertFalse(it.hasNext()); } @Test public void testSelectedIndicesContains() { model.select(5); assertTrue(msModel().getSelectedIndices().contains(5)); } @Test public void testSelectedItemsObservableListIsEmpty() { assertTrue(msModel().getSelectedItems().isEmpty()); } @Test public void testSelectedItemsIndexOf() { msModel().clearSelection(); if (isTree()) { model.select(ROW_2_TREE_VALUE); assertEquals(1, msModel().getSelectedItems().size()); assertEquals(0, msModel().getSelectedItems().indexOf(ROW_2_TREE_VALUE)); } else { model.select(ROW_2_VALUE); assertEquals(1, msModel().getSelectedItems().size()); assertEquals(0, msModel().getSelectedItems().indexOf(ROW_2_VALUE)); } } @Test public void testSelectedItemsIteratorIsNotNull() { assertNotNull(msModel().getSelectedIndices().iterator()); } @Test public void testSelectedItemsLastIndexOf() { msModel().clearSelection(); if (isTree()) { model.select(ROW_2_TREE_VALUE); assertEquals(1, msModel().getSelectedItems().size()); assertEquals(0, msModel().getSelectedItems().lastIndexOf(ROW_2_TREE_VALUE)); } else { model.select(ROW_2_VALUE); assertEquals(1, msModel().getSelectedItems().size()); assertEquals(0, msModel().getSelectedItems().lastIndexOf(ROW_2_VALUE)); } } @Test public void testSelectedItemsContains() { model.select(5); assertTrue(msModel().getSelectedIndices().contains(5)); } @Test public void testSingleSelectionMode() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.SINGLE); assertTrue(model.isEmpty()); model.select(5); assertTrue(model.isSelected(5)); model.select(10); assertTrue(model.isSelected(10)); assertFalse(model.isSelected(5)); assertEquals(1, msModel().getSelectedIndices().size()); assertEquals(1, msModel().getSelectedItems().size()); } @Test public void testMultipleSelectionMode() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); assertTrue(model.isEmpty()); model.select(5); assertTrue(model.isSelected(5)); model.select(10); assertTrue(model.isSelected(10)); assertTrue(model.isSelected(5)); assertEquals(2, msModel().getSelectedIndices().size()); assertEquals(2, msModel().getSelectedItems().size()); } @Test public void testChangeSelectionMode() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectIndices(5, 10, 15); assertEquals(indices(msModel()), 3, msModel().getSelectedIndices().size()); assertEquals(3, msModel().getSelectedItems().size()); assertTrue(model.isSelected(5)); assertTrue(model.isSelected(10)); assertTrue(model.isSelected(15)); msModel().setSelectionMode(SelectionMode.SINGLE); assertEquals(1, msModel().getSelectedIndices().size()); assertEquals(1, msModel().getSelectedItems().size()); assertFalse(indices(msModel()), model.isSelected(5)); assertFalse(indices(msModel()), model.isSelected(10)); assertTrue(indices(msModel()), model.isSelected(15)); } // @Test public void testSelectNullObject() { // model.select(null); // } @Test public void testSelectRange() { // should select all indices starting at 5, and finishing just before // the 10th item msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectRange(5, 10); assertEquals(indices(msModel()), 5, msModel().getSelectedIndices().size()); assertEquals(5, msModel().getSelectedItems().size()); assertFalse(model.isSelected(4)); assertTrue(model.isSelected(5)); assertTrue(model.isSelected(6)); assertTrue(model.isSelected(7)); assertTrue(model.isSelected(8)); assertTrue(model.isSelected(9)); assertFalse(model.isSelected(10)); } @Test public void testDeselectionFromASelectionRange() { msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectRange(2, 10); model.clearSelection(5); assertTrue(indices(msModel()), model.isSelected(4)); assertFalse(indices(msModel()), model.isSelected(5)); assertTrue(indices(msModel()), model.isSelected(6)); } @Test public void testAccurateItemSelection() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectRange(2, 5); ObservableList selectedItems = msModel().getSelectedItems(); assertEquals(3, selectedItems.size()); if (isTree()) { assertFalse(selectedItems.contains(root.getChildren().get(0))); assertTrue(selectedItems.contains(root.getChildren().get(1))); assertTrue(selectedItems.contains(root.getChildren().get(2))); assertTrue(selectedItems.contains(root.getChildren().get(3))); assertFalse(selectedItems.contains(root.getChildren().get(4))); } else { assertFalse(selectedItems.contains(data.get(1))); assertTrue(selectedItems.contains(data.get(2))); assertTrue(selectedItems.contains(data.get(3))); assertTrue(selectedItems.contains(data.get(4))); assertFalse(selectedItems.contains(data.get(5))); } } @Test public void ensureSelectedIndexAndItemIsAlwaysTheLastSelectionWithSelect() { msModel().setSelectionMode(SelectionMode.MULTIPLE); model.select(3); assertEquals(3, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(2), model.getSelectedItem()); } else { assertEquals(data.get(3), model.getSelectedItem()); } model.select(1); assertEquals(1, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(0), model.getSelectedItem()); } else { assertEquals(data.get(1), model.getSelectedItem()); } model.select(5); assertEquals(5, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(4), model.getSelectedItem()); } else { assertEquals(data.get(5), model.getSelectedItem()); } model.select(1); assertEquals(1, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(0), model.getSelectedItem()); } else { assertEquals(data.get(1), model.getSelectedItem()); } } @Test public void ensureSelectedIndexAndItemIsAlwaysTheLastSelectionWithMultipleSelect() { msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectIndices(3,4,5); assertEquals(5, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(4), model.getSelectedItem()); } else { assertEquals(data.get(5), model.getSelectedItem()); } model.select(1); assertEquals(1, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(0), model.getSelectedItem()); } else { assertEquals(data.get(1), model.getSelectedItem()); } msModel().selectIndices(8,7,6); assertEquals(6, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(5), model.getSelectedItem()); } else { assertEquals(data.get(6), model.getSelectedItem()); } } @Test public void ensureSelectedIndexAndItemIsAlwaysTheLastSelectionWithSelectRange() { msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectRange(3,10); assertEquals(9, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(8), model.getSelectedItem()); } else { assertEquals(data.get(9), model.getSelectedItem()); } model.select(1); assertEquals(1, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(0), model.getSelectedItem()); } else { assertEquals(data.get(1), model.getSelectedItem()); } msModel().selectRange(6, 8); assertEquals(7, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(6), model.getSelectedItem()); } else { assertEquals(data.get(7), model.getSelectedItem()); } } @Test public void testMultipleSelectionWithEmptyArray() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectIndices(3,new int[] { }); assertEquals(3, model.getSelectedIndex()); assertEquals(1, msModel().getSelectedIndices().size()); assertEquals(1, msModel().getSelectedItems().size()); if (isTree()) { assertEquals(root.getChildren().get(2), model.getSelectedItem()); } else { assertEquals(data.get(3), model.getSelectedItem()); } } @Test public void selectOnlyValidIndicesInSingleSelection() { msModel().setSelectionMode(SelectionMode.SINGLE); msModel().selectIndices(750397, 3, 709709375, 4, 8597998, 47929); assertEquals(4, model.getSelectedIndex()); assertFalse(model.isSelected(3)); assertTrue(model.isSelected(4)); assertEquals(1, msModel().getSelectedIndices().size()); assertEquals(1, msModel().getSelectedItems().size()); if (isTree()) { assertEquals(root.getChildren().get(3), model.getSelectedItem()); } else { assertEquals(data.get(4), model.getSelectedItem()); } } @Test public void selectOnlyValidIndicesInMultipleSelection() { msModel().setSelectionMode(SelectionMode.MULTIPLE); model.clearSelection(); msModel().selectIndices(750397, 3, 709709375, 4, 8597998, 47929); assertEquals(4, model.getSelectedIndex()); assertTrue(model.isSelected(3)); assertTrue(model.isSelected(4)); assertEquals(2, msModel().getSelectedIndices().size()); assertEquals(2, msModel().getSelectedItems().size()); if (isTree()) { assertEquals(root.getChildren().get(3), model.getSelectedItem()); } else { assertEquals(data.get(4), model.getSelectedItem()); } } @Test public void testNullArrayInMultipleSelection() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectIndices(-20, null); assertEquals(-1, model.getSelectedIndex()); assertNull(model.getSelectedItem()); assertEquals(indices(msModel()), 0, msModel().getSelectedIndices().size()); assertEquals(items(msModel()), 0, msModel().getSelectedItems().size()); } @Test public void testMultipleSelectionWithInvalidIndices() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectIndices(-20, 23505, 78125); assertEquals(-1, model.getSelectedIndex()); assertNull(model.getSelectedItem()); assertEquals(indices(msModel()), 0, msModel().getSelectedIndices().size()); assertEquals(items(msModel()), 0, msModel().getSelectedItems().size()); } @Test public void testInvalidSelection() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.SINGLE); msModel().selectIndices(-20, null); assertEquals(-1, model.getSelectedIndex()); assertNull(model.getSelectedItem()); assertEquals(indices(msModel()), 0, msModel().getSelectedIndices().size()); assertEquals(items(msModel()), 0, msModel().getSelectedItems().size()); } @Test public void ensureSwappedSelectRangeWorks() { // first test a valid range - there should be 6 selected items model.clearSelection(); model.setSelectionMode(SelectionMode.MULTIPLE); model.selectRange(3, 10); assertEquals(indices(model), 7, model.getSelectedIndices().size()); assertEquals(9, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(8), model.getSelectedItem()); } else { assertEquals(data.get(9), model.getSelectedItem()); } model.clearSelection(); // we should select the range from 10 - 4 inclusive model.selectRange(10, 3); assertEquals(7, model.getSelectedIndices().size()); assertEquals(indices(model), 4, model.getSelectedIndex()); if (isTree()) { assertEquals(root.getChildren().get(3), model.getSelectedItem()); } else { assertEquals(data.get(4), model.getSelectedItem()); } } @Test public void testInvalidSelectRange() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectRange(200, 220); assertEquals(-1, model.getSelectedIndex()); assertEquals(null, model.getSelectedItem()); assertEquals(indices(msModel()), 0, msModel().getSelectedIndices().size()); assertEquals(items(msModel()), 0, msModel().getSelectedItems().size()); } @Test public void testEmptySelectRange() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectRange(10, 10); assertEquals(-1, model.getSelectedIndex()); assertEquals(null, model.getSelectedItem()); assertEquals(indices(msModel()), 0, msModel().getSelectedIndices().size()); assertEquals(items(msModel()), 0, msModel().getSelectedItems().size()); } @Test public void testNegativeSelectRange() { msModel().clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().selectRange(-10, -1); assertEquals(-1, model.getSelectedIndex()); assertEquals(null, model.getSelectedItem()); assertEquals(indices(msModel()), 0, msModel().getSelectedIndices().size()); assertEquals(items(msModel()), 0, msModel().getSelectedItems().size()); } @Test(expected=IllegalArgumentException.class) public void testNullListViewInSelectionModel() { new ListView.ListViewBitSetSelectionModel(null); } @Test(expected=IllegalArgumentException.class) public void testNullTreeViewInSelectionModel() { new TreeView.TreeViewBitSetSelectionModel(null); } @Test public void selectAllInEmptySingleSelectionMode() { model.clearSelection(); msModel().setSelectionMode(SelectionMode.SINGLE); assertTrue(model.isEmpty()); msModel().selectAll(); assertTrue(model.isEmpty()); } @Test public void selectAllInSingleSelectionModeWithSelectedRow() { msModel().setSelectionMode(SelectionMode.SINGLE); model.clearSelection(); assertTrue(model.isEmpty()); model.select(3); msModel().selectAll(); assertTrue(model.isSelected(3)); assertEquals(1, msModel().getSelectedIndices().size()); } @Test public void selectionModePropertyHasReferenceToBean() { assertSame(model, model.selectionModeProperty().getBean()); } @Test public void selectionModePropertyHasName() { assertSame("selectionMode", model.selectionModeProperty().getName()); } @Ignore("Not yet implemented in TreeView and TableView") @Test public void testSelectionChangesWhenItemIsInsertedAtStartOfModel() { /* Select the fourth item, and insert a new item at the start of the * data model. The end result should be that the fourth item should NOT * be selected, and the fifth item SHOULD be selected. */ model.select(3); assertTrue(model.isSelected(3)); data.add(0, "Inserted String"); assertFalse(model.isSelected(3)); assertTrue(model.isSelected(4)); } private int rt_28615_row_1_hit_count = 0; private int rt_28615_row_2_hit_count = 0; @Test public void test_rt_28615() { model.clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().getSelectedItems().addListener((ListChangeListener.Change change) -> { while (change.next()) { if (change.wasAdded()) { for (Object item : change.getAddedSubList()) { if (isTree()) { if (root.equals(item)) { rt_28615_row_1_hit_count++; } else if (ROW_2_TREE_VALUE.equals(item)) { rt_28615_row_2_hit_count++; } } else { if (ROW_1_VALUE.equals(item)) { rt_28615_row_1_hit_count++; } else if (ROW_2_VALUE.equals(item)) { rt_28615_row_2_hit_count++; } } } } } }); assertEquals(0, rt_28615_row_1_hit_count); assertEquals(0, rt_28615_row_2_hit_count); msModel().select(0); assertEquals(1, rt_28615_row_1_hit_count); assertEquals(0, rt_28615_row_2_hit_count); msModel().select(1); assertEquals(1, rt_28615_row_1_hit_count); assertEquals(1, rt_28615_row_2_hit_count); } private int rt_29860_size_count = 0; @Test public void test_rt_29860_add() { model.clearSelection(); msModel().setSelectionMode(SelectionMode.MULTIPLE); msModel().getSelectedIndices().addListener((ListChangeListener.Change change) -> { while (change.next()) { if (change.wasAdded()) { rt_29860_size_count += change.getAddedSize(); } } }); assertEquals(0, rt_29860_size_count); // 0,1,2,3 are all selected. The bug is not that the msModel().getSelectedIndices() // list is wrong (it isn't - it's correct). The bug is that the addedSize // reported in the callback above is incorrect. msModel().selectIndices(0, 1, 2, 3); assertEquals(msModel().getSelectedIndices().toString(), 4, rt_29860_size_count); rt_29860_size_count = 0; msModel().selectIndices(0,1,2,3,4); assertEquals(msModel().getSelectedIndices().toString(), 1, rt_29860_size_count); // only 4 was selected rt_29860_size_count = 0; msModel().selectIndices(6,7,8); assertEquals(3, rt_29860_size_count); // 6,7,8 was selected } @Test public void test_rt_29821() { msModel().setSelectionMode(SelectionMode.MULTIPLE); IndexedCell cell_3 = VirtualFlowTestUtils.getCell(currentControl, 3); assertNotNull(cell_3); assertFalse(cell_3.isSelected()); msModel().clearSelection(); msModel().select(3); assertTrue(cell_3.isSelected()); assertEquals(1, msModel().getSelectedIndices().size()); // in multiple selection passing in select(null) is a no-op. In single // selection (tested elsewhere), this would result in a clearSelection() // call msModel().select(null); assertTrue(msModel().isSelected(3)); assertTrue(cell_3.isSelected()); } private int rt_32411_add_count = 0; private int rt_32411_remove_count = 0; @Test public void test_rt_32411_selectedItems() { model.clearSelection(); model.getSelectedItems().addListener((ListChangeListener.Change change) -> { while (change.next()) { rt_32411_remove_count += change.getRemovedSize(); rt_32411_add_count += change.getAddedSize(); } }); // reset fields rt_32411_add_count = 0; rt_32411_remove_count = 0; // select a row - no problems here model.select(2); assertEquals(1, rt_32411_add_count); assertEquals(0, rt_32411_remove_count); // clear and select a new row. We should receive a remove event followed // by an added event - but this bug shows we don't get the remove event. model.clearAndSelect(4); assertEquals(2, rt_32411_add_count); assertEquals(1, rt_32411_remove_count); } @Test public void test_rt_32411_selectedIndices() { model.clearSelection(); model.getSelectedIndices().addListener((ListChangeListener.Change change) -> { while (change.next()) { rt_32411_remove_count += change.getRemovedSize(); rt_32411_add_count += change.getAddedSize(); } }); // reset fields rt_32411_add_count = 0; rt_32411_remove_count = 0; // select a row - no problems here model.select(2); assertEquals(1, rt_32411_add_count); assertEquals(0, rt_32411_remove_count); // clear and select a new row. We should receive a remove event followed // by an added event - but this bug shows we don't get the remove event. model.clearAndSelect(4); assertEquals(2, rt_32411_add_count); assertEquals(1, rt_32411_remove_count); } private int rt32618_count = 0; @Test public void test_rt32618_multipleSelection() { model.selectedItemProperty().addListener((ov, t, t1) -> rt32618_count++); assertEquals(0, rt32618_count); model.select(1); assertEquals(1, rt32618_count); assertEquals(ROW_2_VALUE, getValue(model.getSelectedItem())); model.clearAndSelect(2); assertEquals(2, rt32618_count); assertEquals(ROW_3_VALUE, getValue(model.getSelectedItem())); } @Test public void test_rt33324_selectedIndices() { // pre-select item 0 model.select(0); // install listener model.getSelectedIndices().addListener((ListChangeListener.Change change) -> { while (change.next()) { assertTrue(change.wasRemoved()); assertTrue(change.wasAdded()); assertTrue(change.wasReplaced()); assertFalse(change.wasPermutated()); } }); // change selection to index 1. This should result in a change event // being fired where wasAdded() is true, wasRemoved() is true, but most // importantly, wasReplaced() is true model.clearAndSelect(1); } @Test public void test_rt33324_selectedItems() { // pre-select item 0 model.select(0); // install listener model.getSelectedItems().addListener((ListChangeListener.Change change) -> { while (change.next()) { assertTrue(change.wasRemoved()); assertTrue(change.wasAdded()); assertTrue(change.wasReplaced()); assertFalse(change.wasPermutated()); } }); // change selection to index 1. This should result in a change event // being fired where wasAdded() is true, wasRemoved() is true, but most // importantly, wasReplaced() is true model.clearAndSelect(1); } @Test public void test_rt33324_selectedCells() { if (! (msModel() instanceof TableViewSelectionModel)) { return; } TableViewSelectionModel tableSM = (TableViewSelectionModel) msModel(); // pre-select item 0 tableSM.select(0); // install listener tableSM.getSelectedCells().addListener((ListChangeListener.Change change) -> { while (change.next()) { assertTrue(change.wasRemoved()); assertTrue(change.wasAdded()); assertTrue(change.wasReplaced()); assertFalse(change.wasPermutated()); } }); // change selection to index 1. This should result in a change event // being fired where wasAdded() is true, wasRemoved() is true, but most // importantly, wasReplaced() is true tableSM.clearAndSelect(1); } @Test public void test_rt35624_selectedIndices_downwards() { model.clearSelection(); model.select(2); msModel().getSelectedIndices().addListener((ListChangeListener.Change change) -> { while (change.next()) { // we expect two items in the added list: 3 and 4, as index // 2 has previously been selected Assert.assertEquals(2, change.getAddedSize()); Assert.assertEquals(FXCollections.observableArrayList(3, 4), change.getAddedSubList()); } // In the actual list, we expect three items: 2, 3 and 4 Assert.assertEquals(3, change.getList().size()); Assert.assertEquals(FXCollections.observableArrayList(2, 3, 4), change.getList()); }); model.selectIndices(2, 3, 4); } @Test public void test_rt35624_selectedIndices_upwards() { model.clearSelection(); model.select(4); msModel().getSelectedIndices().addListener(((ListChangeListener.Change change) -> { while (change.next()) { // we expect two items in the added list: 3 and 2, as index // 4 has previously been selected assertEquals(2, change.getAddedSize()); assertEquals(FXCollections.observableArrayList(2, 3), change.getAddedSubList()); } // In the actual list, we expect three items: 2, 3 and 4 assertEquals(3, change.getList().size()); assertEquals(FXCollections.observableArrayList(2, 3, 4), change.getList()); })); model.selectIndices(4, 3, 2); } @Test public void test_rt35624_selectedItems_downwards() { model.clearSelection(); model.select(2); msModel().getSelectedItems().addListener(((ListChangeListener.Change change) -> { while (change.next()) { // we expect two items in the added list: the items in index // 3 and 4, as index 2 has previously been selected assertEquals(2, change.getAddedSize()); if (isTree()) { assertEquals(FXCollections.observableArrayList( root.getChildren().get(2), root.getChildren().get(3) ), change.getAddedSubList()); } else { assertEquals(FXCollections.observableArrayList( data.get(3), data.get(4) ), change.getAddedSubList()); } } // In the actual list, we expect three items: the values at index // 2, 3 and 4 assertEquals(3, change.getList().size()); if (isTree()) { assertEquals(FXCollections.observableArrayList( root.getChildren().get(1), root.getChildren().get(2), root.getChildren().get(3) ), change.getList()); } else { assertEquals(FXCollections.observableArrayList( data.get(2), data.get(3), data.get(4) ), change.getList()); } })); model.selectIndices(2, 3, 4); } @Test public void test_rt35624_selectedItems_upwards() { model.clearSelection(); model.select(4); msModel().getSelectedItems().addListener(((ListChangeListener.Change change) -> { while (change.next()) { // we expect two items in the added list: the items in index // 2 and 3, as index 4 has previously been selected assertEquals(2, change.getAddedSize()); if (isTree()) { assertEquals(FXCollections.observableArrayList( root.getChildren().get(1), root.getChildren().get(2) ), change.getAddedSubList()); } else { assertEquals(FXCollections.observableArrayList( data.get(2), data.get(3) ), change.getAddedSubList()); } } // In the actual list, we expect three items: the values at index // 2, 3 and 4 assertEquals(3, change.getList().size()); if (isTree()) { assertEquals(FXCollections.observableArrayList( root.getChildren().get(1), root.getChildren().get(2), root.getChildren().get(3) ), change.getList()); } else { assertEquals(FXCollections.observableArrayList( data.get(2), data.get(3), data.get(4) ), change.getList()); } })); model.selectIndices(4, 3, 2); } @Test public void test_rt39548_positiveValue_outOfRange() { // for this test we want there to be no data in the controls clearModelData(); model.clearAndSelect(10); } @Test public void test_rt39548_negativeValue() { // for this test we want there to be no data in the controls clearModelData(); model.clearAndSelect(-1); } @Ignore @Test public void test_rt38884_invalidChange() { model.select(3); int removedSize = model.getSelectedItems().size(); ListChangeListener l = (ListChangeListener.Change c) -> { c.next(); assertEquals(removedSize, c.getRemovedSize()); }; model.getSelectedItems().addListener(l); clearModelData(); } private void clearModelData() { listView.getItems().clear(); tableView.getItems().clear(); treeView.setRoot(null); treeTableView.setRoot(null); } @Test public void test_rt40804() { StageLoader sl = new StageLoader(currentControl); model.setSelectionMode(SelectionMode.MULTIPLE); model.select(0); model.select(1); model.clearSelection(); final Thread.UncaughtExceptionHandler exceptionHandler = ControlTestUtils.setHandler(); try { model.select(3); // this is where the test failed } finally { ControlTestUtils.resetHandler(exceptionHandler); } sl.dispose(); } }