-
Enhancement
-
Resolution: Unresolved
-
P4
-
None
Calling VirtualFlow.show(int index) repeatedly to show a cell whose length exceeds the viewport length causes this cell to hop up and down.
Here is the code to reproduce that behavior:
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import com.sun.javafx.scene.control.skin.VirtualFlow;
public class VirtualFlowHopping extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
ListView<Void> listView = new ListView<>();
listView.setCellFactory(lv -> new BigCell());
listView.getItems().add(null);
Button hopBtn = new Button("VirtualFlow.show(0)");
hopBtn.setOnAction(evt -> virtualFlowOf(listView).show(0));
VBox root = new VBox(hopBtn, listView);
stage.setScene(new Scene(root, 200, 300));
stage.show();
}
// the only point of a BigCell is to be taller than the height of ListView
private static class BigCell extends ListCell<Void> {
private final Node graphic = new VBox(
new Label("Cell start"),
new Rectangle(100, 400),
new Label("Cell end"));
@Override
protected void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
if(empty) {
setText(null);
setGraphic(null);
} else {
setText(null);
setGraphic(graphic);
}
}
}
private static <T> VirtualFlow<ListCell<T>> virtualFlowOf(ListView<T> lv) {
for(Node child: lv.getChildrenUnmodifiable()) {
if(child instanceof VirtualFlow)
return (VirtualFlow<ListCell<T>>) child;
}
return null;
}
}
Just click the button repeatedly to see the cell hopping.
I realize that VirtualFlow is not part of the public API. Though I'm using it in my RichTextFX project to bring the paragraph with the caret to the viewport. The reported behavior causes trouble when the paragraph exceeds the viewport.
I propose the following change to VirtualFlow.show(T cell) to fix this problem (not tested):
Original code:
if (start < 0) {
adjustPixels(start);
} else if (end > viewportLength) {
adjustPixels(end - viewportLength);
}
New code:
if (start < 0 && end < viewportLength) {
adjustPixels(Math.max(start, end - viewportLength));
} else if (end > viewportLength && start > 0) {
adjustPixels(Math.min(end - viewportLength, start));
}
Here is the code to reproduce that behavior:
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import com.sun.javafx.scene.control.skin.VirtualFlow;
public class VirtualFlowHopping extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
ListView<Void> listView = new ListView<>();
listView.setCellFactory(lv -> new BigCell());
listView.getItems().add(null);
Button hopBtn = new Button("VirtualFlow.show(0)");
hopBtn.setOnAction(evt -> virtualFlowOf(listView).show(0));
VBox root = new VBox(hopBtn, listView);
stage.setScene(new Scene(root, 200, 300));
stage.show();
}
// the only point of a BigCell is to be taller than the height of ListView
private static class BigCell extends ListCell<Void> {
private final Node graphic = new VBox(
new Label("Cell start"),
new Rectangle(100, 400),
new Label("Cell end"));
@Override
protected void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
if(empty) {
setText(null);
setGraphic(null);
} else {
setText(null);
setGraphic(graphic);
}
}
}
private static <T> VirtualFlow<ListCell<T>> virtualFlowOf(ListView<T> lv) {
for(Node child: lv.getChildrenUnmodifiable()) {
if(child instanceof VirtualFlow)
return (VirtualFlow<ListCell<T>>) child;
}
return null;
}
}
Just click the button repeatedly to see the cell hopping.
I realize that VirtualFlow is not part of the public API. Though I'm using it in my RichTextFX project to bring the paragraph with the caret to the viewport. The reported behavior causes trouble when the paragraph exceeds the viewport.
I propose the following change to VirtualFlow.show(T cell) to fix this problem (not tested):
Original code:
if (start < 0) {
adjustPixels(start);
} else if (end > viewportLength) {
adjustPixels(end - viewportLength);
}
New code:
if (start < 0 && end < viewportLength) {
adjustPixels(Math.max(start, end - viewportLength));
} else if (end > viewportLength && start > 0) {
adjustPixels(Math.min(end - viewportLength, start));
}