Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8157285

TreeTableView produces incorrect selection model state when requested from expandedItemCount property listener

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 9
    • None
    • javafx
    • None

      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);
                  }
              }
          }
      }

            jgiles Jonathan Giles
            jgiles Jonathan Giles
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: