Skip to content

Instantly share code, notes, and snippets.

@oddbjornkvalsund
Created September 17, 2015 10:08
Show Gist options
  • Save oddbjornkvalsund/f232c0f61fdc368d704f to your computer and use it in GitHub Desktop.
Save oddbjornkvalsund/f232c0f61fdc368d704f to your computer and use it in GitHub Desktop.
Automatic vertical resizing of VirtualFlow
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.fxmisc.flowless.Cell;
import org.fxmisc.flowless.VirtualFlow;
import java.time.LocalTime;
import static java.util.stream.IntStream.range;
import static javafx.beans.binding.Bindings.isNotEmpty;
public class Example extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
final ObservableList<String> lines = createGrowingList();
final VirtualFlow<String, Cell<String, TextFlow>> flow = createVerticalFlow(lines);
final HBox buttonRow = createButtonRow(lines);
stage.setScene(new Scene(new VBox(flow, buttonRow)));
stage.setWidth(800);
stage.setHeight(600);
stage.show();
}
private ObservableList<String> createGrowingList() {
final ObservableList<String> list = FXCollections.observableArrayList();
final Timeline timeline = new Timeline(new KeyFrame(Duration.millis(500), ae -> list.add("Local time is now: " + LocalTime.now().toString())));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
return list;
}
private VirtualFlow<String, Cell<String, TextFlow>> createVerticalFlow(ObservableList<String> lines) {
final SimpleDoubleProperty calcHeight = new SimpleDoubleProperty(-1);
final VirtualFlow<String, Cell<String, TextFlow>> flow = VirtualFlow.createVertical(lines, line -> new Cell<String, TextFlow>() {
final TextFlow node = new TextFlow(new Text(line));
@Override
public TextFlow getNode() {
return node;
}
@Override
public boolean isReusable() {
return true;
}
@Override
public void updateItem(String line) {
this.node.getChildren().setAll(new Text(line));
}
@Override
public String toString() {
return node.toString();
}
});
flow.visibleProperty().bind(isNotEmpty(lines));
flow.managedProperty().bind(isNotEmpty(lines));
lines.addListener((ListChangeListener.Change<? extends String> change) -> {
while (change.next()) {
if (change.wasAdded()) {
if (calcHeight.getValue() < 0) {
if (flow.isNeedsLayout()) {
System.err.println("*** Flow needs layout, calculated height might be wrong!");
}
final double cellHeight = getCellHeight(flow, 0, lines.size());
System.out.println("Setting height: " + cellHeight + ".");
calcHeight.set(cellHeight);
} else {
final double cellHeight = getCellHeight(flow, change.getFrom(), change.getTo());
System.out.println("Adding " + cellHeight + " to existing height of " + calcHeight.get() + ".");
calcHeight.set(calcHeight.get() + cellHeight);
}
} else if (change.wasRemoved()) {
if (lines.isEmpty()) {
System.out.println("Lines are empty, setting height to -1.");
calcHeight.set(-1);
} else {
final double cellHeight = getCellHeight(flow, 0, lines.size());
System.out.println("Lines were removed, setting height to " + cellHeight + ".");
calcHeight.set(cellHeight);
}
}
}
System.out.println("Setting height to: " + calcHeight.get() + ".\n");
flow.setPrefHeight(calcHeight.get());
flow.setMaxHeight(calcHeight.get());
flow.scrollY(Double.MAX_VALUE);
});
return flow;
}
private double getCellHeight(VirtualFlow<?, ?> flow, int startIndex, int stopIndex) {
return range(startIndex, stopIndex).mapToDouble((i) -> flow.getCell(i).getNode().getBoundsInLocal().getHeight()).sum();
}
private HBox createButtonRow(ObservableList<String> lines) {
final Button clearButton = new Button("Clear");
clearButton.setOnAction((ae) -> lines.clear());
clearButton.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(clearButton, Priority.ALWAYS);
final Button quitButton = new Button("Quit");
quitButton.setOnAction((ae) -> System.exit(0));
quitButton.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(quitButton, Priority.ALWAYS);
return new HBox(clearButton, quitButton);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment