... in particular when modifying the underlying items?
Below is a quick example that selects a range and adds an item above the selection for TableView and ListView. The selectedIndices before/after adding:
indices before modification: [2, 3]
indices after modification: [3, 4]
Expected options:
- a single wasReplaced for the whole range
- a wasRemoved for the "2" and a wasAdded for the "4"
- ??
Actual:
- table's selection fires two events, each with a single wasAdded
- list's selection fires a wasPermutated (that's nuts, or what am I missing?)
Output (jdk8u40b12):
Change #0 on TableView indices
list = [3]
Change event data:
class javafx.scene.control.MultipleSelectionModelBase$3
javafx.scene.control.MultipleSelectionModelBase$3@4ececa
cursor = 0
Kind of change: added
Affected range: [0, 1]
Added size: 1
Added sublist: [3]
Change #1 on TableView indices
list = [3, 4]
Change event data:
class javafx.scene.control.MultipleSelectionModelBase$3
javafx.scene.control.MultipleSelectionModelBase$3@b0161d
cursor = 0
Kind of change: added
Affected range: [1, 2]
Added size: 1
Added sublist: [4]
Change #0 on ListView indices
list = [3, 4]
Change event data:
class com.sun.javafx.collections.NonIterableChange$SimplePermutationChange
{ permutated by [4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0] }
cursor = 0
Kind of change: permutated
Affected range: [0, 2]
Permutation: [0->4, 1->3]
The producing code:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.ListChangeListener.Change;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class SelectedIndicesOnItemsModified extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<Integer> items = FXCollections.observableArrayList(1, 2, 3, 4);
TableView<Integer> table = new TableView<>(items);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.getSelectionModel().selectRange(2, 4);
System.out.println("indices before modification: " +
table.getSelectionModel().getSelectedIndices());
ListView<Integer> list = new ListView<>(items);
list.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
list.getSelectionModel().selectRange(2, 4);
new PrintingListChangeListener("TableView indices ",
table.getSelectionModel().getSelectedIndices());
new PrintingListChangeListener("ListView indices ",
list.getSelectionModel().getSelectedIndices());
items.add(0, 111);
}
public static void main(String[] args) {
launch(args);
}
public static <T> void prettyPrint(Change<? extends T> change) {
StringBuilder sb = new StringBuilder("\tChange event data:\n");
sb.append("\n " + change.getClass() + "\n " + change);
int i = 0;
change.reset();
while (change.next()) {
sb.append("\n\tcursor = ").append(i++).append("\n");
final String kind = change.wasPermutated() ? "permutated" : change
.wasReplaced() ? "replaced"
: change.wasRemoved() ? "removed"
: change.wasAdded() ? "added"
: change.wasUpdated() ? "updated" : "none";
sb.append("\t\tKind of change: ").append(kind).append("\n");
sb.append("\t\tAffected range: [").append(change.getFrom())
.append(", ").append(change.getTo()).append("]\n");
if (kind.equals("added") || kind.equals("replaced")) {
sb.append("\t\tAdded size: ").append(change.getAddedSize())
.append("\n");
sb.append("\t\tAdded sublist: ")
.append(change.getAddedSubList()).append("\n");
}
if (kind.equals("removed") || kind.equals("replaced")) {
sb.append("\t\tRemoved size: ").append(change.getRemovedSize())
.append("\n");
sb.append("\t\tRemoved: ").append(change.getRemoved())
.append("\n");
}
if (kind.equals("permutated")) {
StringBuilder permutationStringBuilder = new StringBuilder("[");
for (int k = change.getFrom(); k < change.getTo(); k++) {
permutationStringBuilder.append(k).append("->")
.append(change.getPermutation(k));
if (k < change.getTo() - 1) {
permutationStringBuilder.append(", ");
}
}
permutationStringBuilder.append("]");
String permutation = permutationStringBuilder.toString();
sb.append("\t\tPermutation: ").append(permutation).append("\n");
}
}
System.out.println(sb.toString());
};
public static class PrintingListChangeListener implements ListChangeListener {
String source;
int counter;
public PrintingListChangeListener() {
}
public PrintingListChangeListener(String message, ObservableList<?> list) {
list.addListener(this);
source = message;
}
@Override
public void onChanged(Change change) {
System.out.println("Change #" + counter++ + " on " +source +
"\nlist = " + change.getList());
prettyPrint(change);
}
}
}
Filed two issues, RT-39393 for ListView, RT-39394 for TableView