Created
June 4, 2020 08:16
-
-
Save kleopatra/81bd34ad9d1180ed75cd2d204f4e484d to your computer and use it in GitHub Desktop.
Compare handling of selection state after sort vs. replace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package control.table; | |
import java.util.Arrays; | |
import java.util.Locale; | |
import java.util.logging.Logger; | |
//import java.util.stream.Collectors; | |
import static java.util.Comparator.*; | |
import static java.util.stream.Collectors.*; | |
import static javafx.collections.FXCollections.*; | |
import static javafx.scene.control.TreeTableColumn.SortType.*; | |
import javafx.application.Application; | |
import javafx.beans.property.ReadOnlyObjectWrapper; | |
import javafx.collections.ObservableList; | |
import javafx.scene.Parent; | |
import javafx.scene.Scene; | |
import javafx.scene.control.Button; | |
import javafx.scene.control.ListView; | |
import javafx.scene.control.SelectionMode; | |
import javafx.scene.control.Tab; | |
import javafx.scene.control.TabPane; | |
import javafx.scene.control.TableColumn; | |
import javafx.scene.control.TableColumn.SortType; | |
import javafx.scene.control.TableView; | |
import javafx.scene.control.TreeItem; | |
import javafx.scene.control.TreeTableColumn; | |
import javafx.scene.control.TreeTableView; | |
import javafx.scene.control.TreeView; | |
import javafx.scene.control.cell.PropertyValueFactory; | |
import javafx.scene.layout.BorderPane; | |
import javafx.scene.layout.HBox; | |
import javafx.stage.Stage; | |
import support.FXUtils; | |
/** | |
* Compare virtualized controls in handling of selection state on sort/replace vs. re-ordered | |
* items. Run, select multiple, sort/reverse to see differences/similarities (and bugs ;). | |
* | |
* https://bugs.openjdk.java.net/browse/JDK-8193800 | |
* PR: https://github.com/openjdk/jfx/pull/244 | |
* | |
*/ | |
public class CompareSortAndReverse extends Application { | |
private ObservableList<Locale> data; | |
private ObservableList<String> textData; | |
private Parent createTreeTableContent() { | |
TreeTableView<String> tree = new TreeTableView<>(); | |
tree.setRoot(createRoot()); | |
tree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); | |
TreeTableColumn<String, String> col = new TreeTableColumn<String, String>("column"); | |
col.setPrefWidth(150); | |
col.setSortType(ASCENDING); | |
col.setCellValueFactory(param -> new ReadOnlyObjectWrapper<String>(param.getValue().getValue())); | |
tree.getColumns().add(col); | |
Button sort = new Button("sort"); | |
sort.setOnAction(e -> { | |
if (!tree.getSortOrder().contains(col)) { | |
tree.getSortOrder().add(col); | |
} else { | |
TreeTableColumn.SortType type = col.getSortType(); | |
col.setSortType(type == TreeTableColumn.SortType.ASCENDING | |
? TreeTableColumn.SortType.DESCENDING : TreeTableColumn.SortType.ASCENDING); | |
} | |
}); | |
Button reverse = new Button("reverse"); | |
reverse.setOnAction(e -> { | |
reverse(tree.getRoot().getChildren()); | |
}); | |
BorderPane content = new BorderPane(tree); | |
content.setBottom(new HBox(10, reverse)); | |
return content; | |
} | |
private Parent createTreeContent() { | |
TreeView<String> tree = new TreeView<>(); | |
tree.setRoot(createRoot()); | |
tree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); | |
Button sort = new Button("sort"); | |
sort.setOnAction(e -> { | |
sort(tree.getRoot().getChildren(), comparing(treeItem -> treeItem.getValue())); | |
}); | |
Button reverse = new Button("reverse"); | |
reverse.setOnAction(e -> { | |
reverse(tree.getRoot().getChildren()); | |
}); | |
BorderPane content = new BorderPane(tree); | |
content.setBottom(new HBox(10, sort, reverse)); | |
return content; | |
} | |
private Parent createListContent() { | |
ListView<String> list = new ListView<>(observableArrayList(textData)); | |
list.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); | |
Button sort = new Button("sort"); | |
sort.setOnAction(e -> { | |
sort(list.getItems()); | |
}); | |
Button reverse = new Button("reverse"); | |
reverse.setOnAction(e -> { | |
list.setItems(reversed(list.getItems())); | |
}); | |
BorderPane content = new BorderPane(list); | |
content.setBottom(new HBox(10, sort, reverse)); | |
return content; | |
} | |
private Parent createTableContent() { | |
TableView<Locale> table = new TableView<>(data); | |
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); | |
TableColumn<Locale, String> name = new TableColumn<>("Name"); | |
name.setCellValueFactory(new PropertyValueFactory<Locale, String>("displayName")); | |
table.getColumns().addAll(name); | |
Button sort = new Button("sort"); | |
sort.setOnAction(e -> { | |
if (!table.getSortOrder().contains(name)) { | |
table.getSortOrder().add(name); | |
} else { | |
SortType type = name.getSortType(); | |
name.setSortType(type == SortType.ASCENDING ? SortType.DESCENDING : SortType.ASCENDING); | |
} | |
}); | |
Button reverse = new Button("reverse"); | |
reverse.setOnAction(e -> { | |
table.setItems(reversed(table.getItems())); | |
}); | |
BorderPane content = new BorderPane(table); | |
content.setBottom(new HBox(10, sort, reverse)); | |
return content; | |
} | |
private <T> ObservableList<T> reversed(ObservableList<T> items) { | |
ObservableList<T> copy = observableArrayList(items); | |
reverse(copy); | |
return copy; | |
} | |
int childCount = 3; | |
int skipToFirst = 0; | |
private TreeItem<String> createRoot() { | |
skipToFirst = 0; | |
TreeItem<String> root = new TreeItem<>("Root"); | |
addExpandedChildren(root); | |
root.setExpanded(true); | |
root.getChildren().forEach(this::addExpandedChildren); | |
return root; | |
} | |
private void addExpandedChildren(TreeItem<String> parent) { | |
parent.getChildren().addAll(textData.stream().skip(skipToFirst++ * childCount).limit(childCount) | |
.map(l -> { | |
TreeItem<String> item = new TreeItem<>(l); | |
item.setExpanded(true); | |
return item; | |
}) | |
.collect(toList() | |
)); | |
} | |
protected Parent createContent() { | |
initData(); | |
TabPane pane = new TabPane(); | |
pane.getTabs().addAll( | |
new Tab("Table", createTableContent()), | |
new Tab("List", createListContent()), | |
new Tab("Tree", createTreeContent()), | |
new Tab("TreeTable", createTreeTableContent()) | |
); | |
return pane; | |
} | |
protected void initData() { | |
Locale[] availableLocales = Locale.getAvailableLocales(); | |
data = observableArrayList( | |
Arrays.stream(availableLocales) | |
.filter(e -> e.getDisplayName().length() > 0) | |
.limit(12) | |
.collect(toList()) | |
); | |
textData = observableArrayList( | |
data.stream().map(l -> l.getDisplayLanguage()).collect(toList()) | |
); | |
} | |
@Override | |
public void start(Stage stage) throws Exception { | |
stage.setScene(new Scene(createContent())); | |
stage.setTitle(FXUtils.version()); | |
stage.show(); | |
} | |
public static void main(String[] args) { | |
launch(args); | |
} | |
@SuppressWarnings("unused") | |
private static final Logger LOG = Logger | |
.getLogger(CompareSortAndReverse.class.getName()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment