From 9db3eca31ea4369a0a9f0f37ad39650bf40c5b74 Mon Sep 17 00:00:00 2001 From: Jurgen Date: Tue, 8 Sep 2020 11:54:17 +0200 Subject: [PATCH] Fix cells larger than viewport layout efficiency (#80) --- .../java/org/fxmisc/flowless/Navigator.java | 12 ++++- ...igCellCreationAndLayoutEfficiencyTest.java | 49 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/test/java/org/fxmisc/flowless/BigCellCreationAndLayoutEfficiencyTest.java diff --git a/src/main/java/org/fxmisc/flowless/Navigator.java b/src/main/java/org/fxmisc/flowless/Navigator.java index 80ecc10..90eabf7 100644 --- a/src/main/java/org/fxmisc/flowless/Navigator.java +++ b/src/main/java/org/fxmisc/flowless/Navigator.java @@ -127,16 +127,24 @@ void showLengthRegion(int itemIndex, double fromY, double toY) { @Override public void visit(StartOffStart targetPosition) { - placeStartAtMayCrop(targetPosition.itemIndex, targetPosition.offsetFromStart); + cropToNeighborhoodOf( targetPosition.itemIndex ); // Fix for issue #70 (!) + positioner.placeStartAt( targetPosition.itemIndex, targetPosition.offsetFromStart ); fillViewportFrom(targetPosition.itemIndex); } @Override public void visit(EndOffEnd targetPosition) { - placeEndOffEndMayCrop(targetPosition.itemIndex, targetPosition.offsetFromEnd); + cropToNeighborhoodOf( targetPosition.itemIndex ); // Related to issue #70 (?) + positioner.placeEndFromEnd( targetPosition.itemIndex, targetPosition.offsetFromEnd ); fillViewportFrom(targetPosition.itemIndex); } + private void cropToNeighborhoodOf( int itemIndex ) { + int begin = Math.max( 0, getFirstVisibleIndex() ); + int end = Math.max( itemIndex, getLastVisibleIndex() ); + positioner.cropTo( Math.min( begin, itemIndex ), end+1 ); + } + @Override public void visit(MinDistanceTo targetPosition) { Optional cell = positioner.getCellIfVisible(targetPosition.itemIndex); diff --git a/src/test/java/org/fxmisc/flowless/BigCellCreationAndLayoutEfficiencyTest.java b/src/test/java/org/fxmisc/flowless/BigCellCreationAndLayoutEfficiencyTest.java new file mode 100644 index 0000000..d814c68 --- /dev/null +++ b/src/test/java/org/fxmisc/flowless/BigCellCreationAndLayoutEfficiencyTest.java @@ -0,0 +1,49 @@ +package org.fxmisc.flowless; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.Scene; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import javafx.stage.Stage; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class BigCellCreationAndLayoutEfficiencyTest extends FlowlessTestBase { + + private ObservableList items; + private Counter cellCreations = new Counter(); + private VirtualFlow flow; + + @Override + public void start(Stage stage) { + // set up items + items = FXCollections.observableArrayList(); + items.addAll("red", "green", "blue", "purple"); + + // set up virtual flow + flow = VirtualFlow.createVertical( + items, + color -> { + cellCreations.inc(); + Region reg = new Region(); + reg.setStyle("-fx-background-color: " + color); + if ( color.equals( "purple" ) ) reg.setPrefHeight(500.0); + else reg.setPrefHeight(100.0); + return Cell.wrapNode(reg); + }); + + StackPane stackPane = new StackPane(flow); + stage.setScene(new Scene(stackPane, 200, 400)); + stage.show(); + } + + @Test // Relates to issue #70 + public void having_a_very_tall_item_in_viewport_only_creates_and_lays_out_cell_once() { + // if this fails then it's probably because the very big purple cell is being created multiple times + assertEquals(4, cellCreations.get()); + } + +} \ No newline at end of file