JDK-8157285 : TreeTableView produces incorrect selection model state when requested from expandedItemCount property listener
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-05-19
  • Updated: 2016-05-19
  • Resolved: 2016-05-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Fixed
Related Reports
Relates :  
Description
Test application code reproduced below. 

Steps to reproduce:
1) Select 'Child Node 1'
2) Expand 'Child Node 1' by clicking on arrow
3) Collapse 'Child Node 1' by clicking on arrow

Output from before fix applied:
expandedItems: 4
select range 2 to 4
collapsed, selectedIndices: [1, 2, 3]
collapsed, selectedItems: [TreeItem [ value: Child Node 1 ], null, null]

The issue is that only index 1 is selected (so 2 and 3 should not be in selected indices), and there should not be two nulls in the selected items list.

Test application:

import javafx.application.Application;
import javafx.collections.*;
import javafx.collections.transformation.*;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.control.TreeTableColumn.CellDataFeatures;
import javafx.stage.Stage;

import java.util.Collection;
import java.util.Objects;

public class TreeTableViewSample extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        final TreeItem<String> childNode1 = new TreeItem<>("Child Node 1");
        childNode1.getChildren().addAll(
                new TreeItem<String>("Node 1-1"),
                new TreeItem<String>("Node 1-2")
        );

        final TreeItem<String> root = new TreeItem<>("Root node");
        root.setExpanded(true);
        root.getChildren().add(childNode1);

        TreeTableColumn<String,String> column = new TreeTableColumn<>("Column");
        column.setPrefWidth(190);
        column.setCellValueFactory((CellDataFeatures<String, String> p) ->
                new ReadOnlyStringWrapper(p.getValue().getValue()));

        final TreeTableView<String> treeTableView = new TreeTableView<>(root);
        treeTableView.getColumns().add(column);
        treeTableView.setPrefWidth(200);
        treeTableView.setShowRoot(true);
        treeTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        // Select all children of expanded node.
        treeTableView.expandedItemCountProperty().addListener((observable, oldCount, newCount) -> {
            if (newCount.intValue() > oldCount.intValue()) {
                System.out.println("expandedItems: " + newCount);
                selectChildrenOfRows(treeTableView, treeTableView.getSelectionModel().getSelectedIndices());
            } else {
                System.out.println("collapsed, selectedIndices: " + treeTableView.getSelectionModel().getSelectedIndices());
                System.out.println("collapsed, selectedItems: " + treeTableView.getSelectionModel().getSelectedItems());
            }
        });

        final Scene scene = new Scene(new Group(), 200, 400);
        Group sceneRoot = (Group)scene.getRoot();
        sceneRoot.getChildren().add(treeTableView);

        stage.setTitle("Tree Table View Samples");
        stage.setScene(scene);
        stage.show();
    }

    private void selectChildrenOfRows(TreeTableView<String> table, Collection<Integer> selectedRows) {
        for (int index: selectedRows) {
            TreeItem<String> item = table.getTreeItem(index);

            if (item != null && item.isExpanded() && !item.getChildren().isEmpty()) {
                int startIndex = index + 1;
                int maxCount = startIndex + item.getChildren().size();

                System.out.println("select range " + startIndex + " to " + maxCount);
                table.getSelectionModel().selectRange(startIndex, maxCount);
            }
        }
    }
} 
Comments
Changeset: http://hg.openjdk.java.net/openjfx/9-dev/rt/rev/95f0d363d485
19-05-2016

After fix is applied, the following output is shown: expandedItems: 4 select range 2 to 4 collapsed, selectedIndices: [1] collapsed, selectedItems: [TreeItem [ value: Child Node 1 ]] This is what is expected.
19-05-2016