Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8235491: Tree/TableView: implementation of isSelected(int) violates contract #839

Closed
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, 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
@@ -198,9 +198,8 @@ public SelectionModel() { }
public abstract void clearSelection();

/**
* <p>Convenience method to inform if the given index is currently selected
* in this SelectionModel. Is functionally equivalent to calling
* <code>getSelectedIndices().contains(index)</code>.
* This method tests whether the given index is currently selected
* in this SelectionModel.
*
* @param index The index to check as to whether it is currently selected
* or not.
Original file line number Diff line number Diff line change
@@ -2813,8 +2813,9 @@ private void quietClearSelection() {
stopAtomic();
}

@Override public boolean isSelected(int index) {
return isSelected(index, null);
@Override
public boolean isSelected(int index) {
return super.isSelected(index);
}

@Override
Original file line number Diff line number Diff line change
@@ -3165,8 +3165,19 @@ private void quietClearSelection() {
stopAtomic();
}

@Override public boolean isSelected(int index) {
return isSelected(index, null);
@Override
public boolean isSelected(int index) {
if (isCellSelectionEnabled()) {
int columnCount = treeTableView.getVisibleLeafColumns().size();
for (int col = 0; col < columnCount; col++) {
if (selectedCellsMap.isSelected(index, col)) {
return true;
}
}
return false;
} else {
return selectedCellsMap.isSelected(index, -1);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as tableView - just to not forget :)


@Override public boolean isSelected(int row, TableColumnBase<TreeItem<S>,?> column) {
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2022, 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
@@ -714,7 +714,7 @@ private void test_rt_38306(boolean selectTwoRows) {
assertFalse(sm.isSelected(row, firstNameCol));
assertFalse(sm.isSelected(row, lastNameCol));
assertTrue(sm.isSelected(row, emailCol));
assertFalse(sm.isSelected(row));
assertTrue(sm.isSelected(row));

// and assert that the visuals are accurate
// (some TableCells should be selected, but TableRows should not be)
@@ -787,7 +787,7 @@ private void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(boolean ce
if (cellSelection) {
// Because we are in cell selection mode, this has the effect of
// selecting just the one cell.
assertFalse(sm.isSelected(0));
assertTrue(sm.isSelected(0));
assertTrue(sm.isSelected(0, firstNameCol));
assertFalse(sm.isSelected(0, lastNameCol));
assertFalse(sm.isSelected(0, emailCol));
@@ -813,7 +813,7 @@ private void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(boolean ce
if (cellSelection) {
// Everything should remain the same, except the
// column of the single selected cell should change to lastNameCol.
assertFalse(sm.isSelected(0));
assertTrue(sm.isSelected(0));
assertFalse(sm.isSelected(0, firstNameCol));
assertTrue(sm.isSelected(0, lastNameCol));
assertFalse(sm.isSelected(0, emailCol));
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, 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
@@ -40,6 +40,8 @@
import javafx.scene.control.TableView.TableViewSelectionModel;
import javafx.scene.control.TableViewShim;
import javafx.scene.control.TreeViewShim;
import javafx.scene.control.cell.PropertyValueFactory;
import test.com.sun.javafx.scene.control.test.Person;

import org.junit.After;
import org.junit.AfterClass;
@@ -172,7 +174,7 @@ private TablePosition pos(int row, TableColumn<String,?> col) {
assertFalse(model.isSelected(1, col0));
assertFalse(model.isSelected(3, col0));
assertFalse(cells(model), model.isSelected(3, null));
assertFalse(model.isSelected(3));
assertTrue(model.isSelected(3));
assertEquals(1, model.getSelectedCells().size());
}

Comment on lines -175 to 180
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have tests isSelected(index) for all combinations of single/multiple/cellSelection? If not, now might be a good time to add them :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a very good point!
should definitely cover all the scenarios.

@@ -185,7 +187,7 @@ private TablePosition pos(int row, TableColumn<String,?> col) {
assertFalse(model.isSelected(1, col0));
assertFalse(model.isSelected(3, col0));
assertFalse(cells(model), model.isSelected(3, null));
assertFalse(model.isSelected(3));
assertTrue(model.isSelected(3));
assertEquals(1, model.getSelectedCells().size());
}

@@ -522,6 +524,52 @@ private TablePosition pos(int row, TableColumn<String,?> col) {
assertTrue(model.isSelected(4));
}

@Test
public void selectIndividualCells() {
model.setSelectionMode(SelectionMode.MULTIPLE);
model.setCellSelectionEnabled(true);
model.clearSelection();

model.select(0, col0);
assertTrue(cells(model), model.isSelected(0));
assertFalse(cells(model), model.isSelected(1));
assertFalse(cells(model), model.isSelected(2));

model.select(1, col0);
model.select(1, col1);
assertTrue(cells(model), model.isSelected(0));
assertTrue(cells(model), model.isSelected(1));
assertFalse(cells(model), model.isSelected(2));

model.select(2, col0);
model.select(2, col1);
model.select(2, col2);
assertTrue(cells(model), model.isSelected(0));
assertTrue(cells(model), model.isSelected(1));
assertTrue(cells(model), model.isSelected(2));

assertFalse(cells(model), model.isSelected(3));

assertEquals(6, model.getSelectedCells().size());

model.clearSelection(0, col0);
assertFalse(cells(model), model.isSelected(0));

model.clearSelection(1, col0);
assertTrue(cells(model), model.isSelected(1));
model.clearSelection(1, col1);
assertFalse(cells(model), model.isSelected(1));

model.clearSelection(2, col0);
assertTrue(cells(model), model.isSelected(2));
model.clearSelection(2, col1);
assertTrue(cells(model), model.isSelected(2));
model.clearSelection(2, col2);
assertFalse(cells(model), model.isSelected(2));

assertEquals(0, model.getSelectedCells().size());
}

/***************************************************************************
*
* FOCUS TESTS
@@ -852,4 +900,97 @@ private TablePosition pos(int row, TableColumn<String,?> col) {
model.clearSelection(2);
model.getSelectedItems().removeListener(listener);
}

/**
* Analysing failing tests when fixing JDK-8219720.
*
* Suspect: isSelected(int row) violates contract.
*
* @see #selectRowWhenInSingleCellSelectionMode()
* @see #selectRowWhenInSingleCellSelectionMode2()
*/
@Test
public void testSelectRowWhenInSingleCellSelectionModeIsSelected() {
model.setSelectionMode(SelectionMode.SINGLE);
model.setCellSelectionEnabled(true);
model.select(3);
// test against contract
assertEquals("selected index", 3, model.getSelectedIndex());
assertTrue("contained in selected indices", model.getSelectedIndices().contains(3));
// test against spec
assertEquals("is selected index", model.getSelectedIndices().contains(3), model.isSelected(3));
}

@Test
public void testRowSelectionAfterSelectAndHideLastColumnMultipleCellEnabled() {
assertRowSelectionAfterSelectAndHideLastColumn(SelectionMode.MULTIPLE, true);
}

@Test
public void testRowSelectionAfterSelectAndHideLastColumnMultipleNotCellEnabled() {
assertRowSelectionAfterSelectAndHideLastColumn(SelectionMode.MULTIPLE, false);
}

@Test
public void testRowSelectionAfterSelectAndHideLastColumnSingleCellEnabled() {
assertRowSelectionAfterSelectAndHideLastColumn(SelectionMode.SINGLE, true);
}

@Test
public void testRowSelectionAfterSelectAndHideLastColumnSingleNotCellEnabled() {
assertRowSelectionAfterSelectAndHideLastColumn(SelectionMode.SINGLE, false);
}

public void assertRowSelectionAfterSelectAndHideLastColumn(SelectionMode mode, boolean cellEnabled) {
TableView<Person> table = createPersonTableView();

TableView.TableViewSelectionModel<Person> sm = table.getSelectionModel();
sm.setCellSelectionEnabled(cellEnabled);
sm.setSelectionMode(mode);
int row = 1;
int col = table.getColumns().size() - 1;
assertRowSelectionAfterSelectAndHideColumn(table, row, col);
}

private void assertRowSelectionAfterSelectAndHideColumn(TableView<Person> table, int row, int col) {
TableViewSelectionModel<Person> sm = table.getSelectionModel();
TableColumn<Person, ?> column = table.getColumns().get(col);
TablePosition<Person, ?> pos = new TablePosition<>(table, row, column);

sm.select(row, column);
assertTrue("sanity: row " + row + "contained in selectedIndices", sm.getSelectedIndices().contains(row));
assertTrue("sanity: row must be selected" , sm.isSelected(row));
column.setVisible(false);
assertTrue("after hiding column: row " + row + "contained in selectedIndices", sm.getSelectedIndices().contains(row));
assertTrue("after hiding column: row must be selected" , sm.isSelected(row));
}

/**
* Creates and returns a TableView with Persons and columns for all their properties.
*/
private TableView<Person> createPersonTableView() {
final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person("Jacob", "Smith", "jacob.smith@example.com"),
new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
new Person("Ethan", "Williams", "ethan.williams@example.com"),
new Person("Emma", "Jones", "emma.jones@example.com"),
new Person("Michael", "Brown", "michael.brown@example.com"));

TableView<Person> table = new TableView<>();
table.setItems(data);

TableColumn<Person, String> firstNameCol = new TableColumn("First Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));

TableColumn<Person, String> lastNameCol = new TableColumn("Last Name");
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));

TableColumn<Person, String> emailCol = new TableColumn("Email");
emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));

table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);

return table;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2022, 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
@@ -889,7 +889,7 @@ private void test_rt_38306(boolean selectTwoRows) {
assertFalse(sm.isSelected(row, firstNameCol));
assertFalse(sm.isSelected(row, lastNameCol));
assertTrue(sm.isSelected(row, emailCol));
assertFalse(sm.isSelected(row));
assertTrue(sm.isSelected(row));

// and assert that the visuals are accurate
// (some TableCells should be selected, but TableRows should not be)
@@ -903,7 +903,7 @@ private void test_rt_38306(boolean selectTwoRows) {
assertEquals(column == 2 ? true : false, cell.isSelected());
}
TreeTableRow cell = (TreeTableRow) VirtualFlowTestUtils.getCell(table, row);
assertFalse(cell.isSelected());
assertTrue(cell.isSelected());
}
}

@@ -966,7 +966,7 @@ private void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(boolean ce
if (cellSelection) {
// Because we are in cell selection mode, this has the effect of
// selecting just the one cell.
assertFalse(sm.isSelected(0));
assertTrue(sm.isSelected(0));
assertTrue(sm.isSelected(0, firstNameCol));
assertFalse(sm.isSelected(0, lastNameCol));
assertFalse(sm.isSelected(0, emailCol));
@@ -992,7 +992,7 @@ private void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(boolean ce
if (cellSelection) {
// Everything should remain the same, except the
// column of the single selected cell should change to lastNameCol.
assertFalse(sm.isSelected(0));
assertTrue(sm.isSelected(0));
assertFalse(sm.isSelected(0, firstNameCol));
assertTrue(sm.isSelected(0, lastNameCol));
assertFalse(sm.isSelected(0, emailCol));
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, 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
@@ -134,7 +134,7 @@ private TreeTablePosition pos(int row, TreeTableColumn<String,?> col) {
assertFalse(model.isSelected(1, col0));
assertFalse(model.isSelected(3, col0));
assertFalse(cells(model), model.isSelected(3, null));
assertFalse(model.isSelected(3));
assertTrue(model.isSelected(3));
assertEquals(1, model.getSelectedCells().size());
}
Comment on lines 141 to 144
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as TableView :)


@@ -148,7 +148,7 @@ private TreeTablePosition pos(int row, TreeTableColumn<String,?> col) {
assertFalse(model.isSelected(1, col0));
assertFalse(model.isSelected(3, col0));
assertFalse(cells(model), model.isSelected(3, null));
assertFalse(model.isSelected(3));
assertTrue(model.isSelected(3));
assertEquals(1, model.getSelectedCells().size());
}

@@ -485,6 +485,52 @@ private TreeTablePosition pos(int row, TreeTableColumn<String,?> col) {
assertTrue(model.isSelected(4));
}

@Test
public void selectIndividualCells() {
model.setSelectionMode(SelectionMode.MULTIPLE);
model.setCellSelectionEnabled(true);
model.clearSelection();

model.select(0, col0);
assertTrue(cells(model), model.isSelected(0));
assertFalse(cells(model), model.isSelected(1));
assertFalse(cells(model), model.isSelected(2));

model.select(1, col0);
model.select(1, col1);
assertTrue(cells(model), model.isSelected(0));
assertTrue(cells(model), model.isSelected(1));
assertFalse(cells(model), model.isSelected(2));

model.select(2, col0);
model.select(2, col1);
model.select(2, col2);
assertTrue(cells(model), model.isSelected(0));
assertTrue(cells(model), model.isSelected(1));
assertTrue(cells(model), model.isSelected(2));

assertFalse(cells(model), model.isSelected(3));

assertEquals(6, model.getSelectedCells().size());

model.clearSelection(0, col0);
assertFalse(cells(model), model.isSelected(0));

model.clearSelection(1, col0);
assertTrue(cells(model), model.isSelected(1));
model.clearSelection(1, col1);
assertFalse(cells(model), model.isSelected(1));

model.clearSelection(2, col0);
assertTrue(cells(model), model.isSelected(2));
model.clearSelection(2, col1);
assertTrue(cells(model), model.isSelected(2));
model.clearSelection(2, col2);
assertFalse(cells(model), model.isSelected(2));

assertEquals(0, model.getSelectedCells().size());
}

/***************************************************************************
*
* FOCUS TESTS