1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
| package treecheck;
import java.util.function.Function;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public final class Main extends Application {
private static final short MAX_TREE_DEPTH = 3;
@Override
public void start(final Stage primaryStage) throws Exception {
// Écouteur cellule.
final Label trucTitleLabel = new Label("Écouteur cellule");
final Label trucLabel = new Label();
final TreeView<Truc> trucTreeView = new TreeView(createTree(id -> {
final Truc result = new Truc(id);
result.selectedProperty().addListener((observable, oldValue, newValue) -> {
trucLabel.setText(String.format("%s - %b", result, result.isSelected()));
});
return result;
}));
trucTreeView.setShowRoot(false);
trucTreeView.setCellFactory(tree -> new TrucTreeCell());
VBox.setVgrow(trucTreeView, Priority.ALWAYS);
final VBox trucVBox = new VBox();
trucVBox.getChildren().addAll(trucTitleLabel, trucTreeView, trucLabel);
// Map de sélection.
final Label totoTitleLabel = new Label("Map de sélection");
final Label totoLabel = new Label();
final TreeView<Toto> tototTreeView = new TreeView(createTree(Toto::new));
tototTreeView.setShowRoot(false);
final ObservableMap<Toto, Boolean> totoSelectionMap = FXCollections.observableHashMap();
totoSelectionMap.addListener((MapChangeListener.Change<? extends Toto, ? extends Boolean> change) -> {
totoLabel.setText(String.format("%s - %b", change.getKey(), change.getValueAdded()));
});
tototTreeView.setCellFactory(tree -> new TotoTreeCell(totoSelectionMap));
VBox.setVgrow(tototTreeView, Priority.ALWAYS);
final VBox totoVBox = new VBox();
totoVBox.getChildren().addAll(totoTitleLabel, tototTreeView, totoLabel);
//
final SplitPane root = new SplitPane();
root.getItems().addAll(trucVBox, totoVBox);
final Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setWidth(500);
primaryStage.setHeight(800);
primaryStage.show();
Platform.runLater(() -> root.setDividerPositions(0.5));
}
private <T> TreeItem<T> createTree(final Function<String, T> provider) {
final TreeItem<T> root = new TreeItem<>();
populateTree(root, provider, MAX_TREE_DEPTH, "");
return root;
}
private <T> void populateTree(final TreeItem<T> root, final Function<String, T> provider, final int level, final String prefix) {
IntStream.range(0, level)
.mapToObj(index -> String.format("%s %d", prefix, index).trim())
.map(provider::apply)
.map(TreeItem::new)
.forEach(item -> {
populateTree(item, provider, level - 1, item.getValue().toString());
root.getChildren().add(item);
});
root.setExpanded(true);
}
private static final class Truc {
final String id;
public Truc(final String id) {
this.id = id;
}
@Override
public String toString() {
return id;
}
private final BooleanProperty selected = new SimpleBooleanProperty(this, "selected");
public final boolean isSelected() {
return selected.get();
}
public final void setSelected(boolean value) {
selected.set(value);
}
public final BooleanProperty selectedProperty() {
return selected;
}
}
private static final class TrucTreeCell extends TreeCell<Truc> {
private CheckBox renderer = null;
private Truc currentItem;
@Override
protected void updateItem(Truc item, boolean empty) {
super.updateItem(item, empty);
currentItem = item;
String text = null;
Node graphic = null;
if (item != null && !empty) {
final TreeItem treeItem = getTreeItem();
final boolean isLeaf = treeItem.isLeaf();
if (isLeaf) {
renderer = (renderer == null) ? new CheckBox() : renderer;
renderer.selectedProperty().removeListener(selectedChangeListener);
renderer.setText(item.toString());
renderer.setSelected(item.isSelected());
renderer.selectedProperty().addListener(selectedChangeListener);
text = null;
graphic = renderer;
} else {
text = item.toString();
}
}
setText(text);
setGraphic(graphic);
}
private final ChangeListener<Boolean> selectedChangeListener = (observable, oldValue, newValue) -> {
if (currentItem != null) {
currentItem.setSelected(newValue);
}
};
}
private static final class Toto {
final String id;
public Toto(final String id) {
this.id = id;
}
@Override
public String toString() {
return id;
}
}
private static final class TotoTreeCell extends TreeCell<Toto> {
private CheckBox renderer = null;
private Toto currentItem;
final ObservableMap<Toto, Boolean> selectionMap;
public TotoTreeCell(final ObservableMap<Toto, Boolean> selectionMap) {
this.selectionMap = selectionMap;
}
@Override
protected void updateItem(Toto item, boolean empty) {
super.updateItem(item, empty);
currentItem = item;
String text = null;
Node graphic = null;
if (item != null && !empty) {
final TreeItem treeItem = getTreeItem();
final boolean isLeaf = treeItem.isLeaf();
if (isLeaf) {
renderer = (renderer == null) ? new CheckBox() : renderer;
renderer.selectedProperty().removeListener(selectedChangeListener);
renderer.setText(item.toString());
final Boolean selected = selectionMap.get(item);
renderer.setSelected(selected == null ? false : selected);
renderer.selectedProperty().addListener(selectedChangeListener);
text = null;
graphic = renderer;
} else {
text = item.toString();
}
}
setText(text);
setGraphic(graphic);
}
private final ChangeListener<Boolean> selectedChangeListener = new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (currentItem != null) {
selectionMap.put(currentItem, newValue);
}
}
};
}
public static void Main(String... args) {
Application.launch(args);
}
} |
Partager