Skip to content

Instantly share code, notes, and snippets.

@kleopatra
Created June 4, 2020 08:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kleopatra/81bd34ad9d1180ed75cd2d204f4e484d to your computer and use it in GitHub Desktop.
Save kleopatra/81bd34ad9d1180ed75cd2d204f4e484d to your computer and use it in GitHub Desktop.
Compare handling of selection state after sort vs. replace
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