Skip to content

Commit

Permalink
🔖 Minor changes, bump version to 21.1.1
Browse files Browse the repository at this point in the history
⬆️ Upgrade Gradle to version 8.5
⬆️ Upgrade JavaFX to version 21.0.1

List Package
✨ VirtualizedList: add two more convenience methods
✨ VirtualizedListCache: add method to retrieve cache size
♻️ VirtualizedListHelper: remove unnecessary override for the range property as we use a binding instead
 ♻️ VirtualizedListManager: check against invalid range too on position changed
 ♻️ VirtualizedListSkin: whoops, re-enable clip

 Utils Package
 ♻️ StateMap: replace assertion with meaningful debug error

 Tests
 ♻️ Move misc methods to ListTestUtils
 ✅ Add one more init test to VirtualizedListTests
 ✨ Utils: Added convenience method to start ScenicView

Signed-off-by: palexdev <[email protected]>
  • Loading branch information
palexdev committed Dec 29, 2023
1 parent e3a361c commit 0149334
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 214 deletions.
6 changes: 6 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## General

- [ ] Review names
- [ ] Review APIs (classes, simplify as much as possible/re-organize at least)
- [ ] Maybe define a common Interface for Virtualized containers

## VirtualFlow

- [x] Items changed (property)
Expand Down
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#--------------------------------------#
GROUP=io.github.palexdev
POM_ARTIFACT_ID=virtualizedfx
VERSION_NAME=21.1.0
VERSION_NAME=21.1.1
POM_NAME=virtualizedfx
POM_DESCRIPTION=Alternative VirtualFlows for JavaFX
POM_INCEPTION_YEAR=2021
Expand All @@ -19,13 +19,13 @@ POM_PACKAGING=jar
#--------------------------------------#
# Versions #
#--------------------------------------#
vfx=21.1.0
vfx=21.1.1
jdk=21
# Plugins
jfxPlugin=0.1.0
mavenPublish=0.25.3
# Dependencies
jfx=21
jfx=21.0.1
mfxcore=11.8.0
mfxeffects=11.3.1
mfxresources=11.9.1
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,20 @@ public void scrollToIndex(int index) {
getHelper().scrollToIndex(index);
}

/**
* Shortcut for {@code scrollToIndex(0)}.
*/
public void scrollToFirst() {
scrollToIndex(0);
}

/**
* Shortcut for {@code scrollToIndex(size() - 1)}.
*/
public void scrollToLast() {
scrollToIndex(size() - 1);
}

//================================================================================
// Styleable Properties
//================================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ public VirtualizedListCache<T, C> clear() {
return this;
}

public int size() {
return queue.size();
}

/**
* Sets the cache's capacity. Visibility is restricted because capacity is meant to be set through the
* {@link VirtualizedList#cacheCapacityProperty()}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import io.github.palexdev.mfxcore.base.beans.Position;
import io.github.palexdev.mfxcore.base.beans.range.IntegerRange;
import io.github.palexdev.mfxcore.base.beans.range.NumberRange;
import io.github.palexdev.mfxcore.base.properties.PositionProperty;
import io.github.palexdev.mfxcore.base.properties.range.IntegerRangeProperty;
import io.github.palexdev.mfxcore.builders.bindings.DoubleBindingBuilder;
Expand All @@ -17,7 +16,6 @@
import javafx.geometry.Orientation;
import javafx.scene.Node;

import java.util.Objects;
import java.util.Optional;

/**
Expand Down Expand Up @@ -182,14 +180,7 @@ default void dispose() {}
*/
abstract class AbstractHelper<T, C extends Cell<T>> implements VirtualizedListHelper<T, C> {
protected final VirtualizedList<T, C> list;
protected final IntegerRangeProperty range = new IntegerRangeProperty() {
@Override
public void set(NumberRange<Integer> newValue) {
NumberRange<Integer> oldValue = get();
if (Objects.equals(oldValue, newValue)) return;
super.set(newValue);
}
};
protected final IntegerRangeProperty range = new IntegerRangeProperty();
protected final ReadOnlyDoubleWrapper estimatedLength = new ReadOnlyDoubleWrapper();
protected final ReadOnlyDoubleWrapper maxBreadth = new ReadOnlyDoubleWrapper();
protected final PositionProperty viewportPosition = new PositionProperty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ protected void onPositionChanged() {
VirtualizedListHelper<T, C> helper = list.getHelper();
IntegerRange lastRange = state.getRange();
IntegerRange range = helper.range();
if (Objects.equals(lastRange, range)) return;
if (Objects.equals(lastRange, range) || Utils.INVALID_RANGE.equals(range)) return;

// Compute the new state
// Commons are just moved to the new state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ protected void layoutChildren() {
clip.heightProperty().bind(list.heightProperty());
clip.arcWidthProperty().bind(list.clipBorderRadiusProperty());
clip.arcHeightProperty().bind(list.clipBorderRadiusProperty());
//list.setClip(clip);
list.setClip(clip);

// End initialization
addListeners();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ public C getCell(T item) {
* [Item -> Index].
*/
public void put(Integer index, T item, C cell) {
assert index != null && item != null && cell != null;
if (index == null || item == null || cell == null)
throw new NullPointerException("Cannot add entry [Index:%s; Item:%s; Cell:%s] in state map".formatted(index, item, cell));
byIndex.put(index, cell);
byItem.put(item, index);
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/app/Playground.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package app;

import interactive.VirtualizedListTests.SimpleCell;
import interactive.list.ListTestUtils.SimpleCell;
import io.github.palexdev.mfxcore.builders.InsetsBuilder;
import io.github.palexdev.mfxcore.events.WhenEvent;
import io.github.palexdev.mfxcore.utils.RandomUtils;
Expand Down
247 changes: 247 additions & 0 deletions src/test/java/interactive/list/ListTestUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
package interactive.list;

import io.github.palexdev.mfxcore.base.beans.range.IntegerRange;
import io.github.palexdev.mfxcore.controls.Label;
import io.github.palexdev.mfxcore.controls.SkinBase;
import io.github.palexdev.mfxcore.observables.When;
import io.github.palexdev.virtualizedfx.cells.CellBase;
import io.github.palexdev.virtualizedfx.cells.CellBaseBehavior;
import io.github.palexdev.virtualizedfx.list.VirtualizedList;
import io.github.palexdev.virtualizedfx.list.VirtualizedListHelper;
import io.github.palexdev.virtualizedfx.list.VirtualizedListSkin;
import io.github.palexdev.virtualizedfx.list.VirtualizedListState;
import javafx.collections.ObservableList;
import javafx.geometry.Bounds;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import org.opentest4j.AssertionFailedError;
import org.testfx.api.FxToolkit;

import java.util.Map;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class ListTestUtils {
//================================================================================
// Static Properties
//================================================================================
static final Counter counter = new Counter();

//================================================================================
// Constructors
//================================================================================
private ListTestUtils() {}

//================================================================================
// Methods
//================================================================================
static StackPane setupStage() {
StackPane pane = new StackPane();
try {
Scene scene = new Scene(pane, 400, 400);
FxToolkit.setupStage(s -> {
s.setWidth(400);
s.setHeight(400);
s.setScene(scene);
});
} catch (TimeoutException e) {
throw new RuntimeException(e);
}
return pane;
}

static void assertState(VirtualizedList<Integer, SimpleCell> list, IntegerRange range) {
VirtualizedListState<Integer, SimpleCell> state = list.getState();
VirtualizedListHelper<Integer, SimpleCell> helper = list.getHelper();
if (IntegerRange.of(-1).equals(range)) {
assertEquals(VirtualizedListState.EMPTY, state);
return;
}

assertEquals(helper.range(), range);
assertEquals(helper.totalNum(), range.diff() + 1);

Map<Integer, SimpleCell> cells = state.getCellsByIndexUnmodifiable();
ObservableList<Integer> items = list.getItems();
for (Integer index : range) {
SimpleCell cell = cells.get(index);
try {
assertNotNull(cell);
} catch (AssertionFailedError error) {
// For debug purposes
System.err.println("Null cell for index: " + index);
throw error;
}
assertEquals(index, cell.getIndex());
assertEquals(items.get(index), cell.getItem());
assertPosition(list, index - range.getMin(), cell);
}
}

static void assertPosition(VirtualizedList<Integer, SimpleCell> list, int iteration, SimpleCell cell) {
Orientation o = list.getOrientation();
Function<Bounds, Double> inParentPos = (o == Orientation.VERTICAL) ? Bounds::getMinY : Bounds::getMinX;
double pos = iteration * list.getHelper().getTotalCellSize();
assertEquals(pos, inParentPos.apply(cell.toNode().getBoundsInParent()));
}

static void assertCounter(int created, int layouts, int ixUpdates, int itUpdates, int deCached, int cached) {
assertEquals(created, counter.created);
assertEquals(layouts, counter.layoutCnt);
assertEquals(ixUpdates, counter.updIndexCnt);
assertEquals(itUpdates, counter.updItemCnt);
assertEquals(deCached, counter.fromCache);
assertEquals(cached, counter.toCache);
counter.reset();
}

//================================================================================
// Internal Classes
//================================================================================
public static class List extends VirtualizedList<Integer, SimpleCell> {
public List(ObservableList<Integer> items, Function<Integer, SimpleCell> cellFactory) {
super(items, cellFactory);
}

@Override
public void setCellFactory(Function<Integer, SimpleCell> cellFactory) {
super.setCellFactory(cellFactory.andThen(c -> {
counter.created();
return c;
}));
}

@Override
protected SkinBase<?, ?> buildSkin() {
return new VirtualizedListSkin<>(this) {
@Override
protected void onLayoutCompleted(boolean done) {
super.onLayoutCompleted(done);
if (done) counter.layout();
}
};
}
}

public static class SimpleCell extends CellBase<Integer> {
public SimpleCell() {}

public SimpleCell(Integer item) {super(item);}

@Override
public void onDeCache() {
counter.fCache();
}

@Override
public void onCache() {
counter.tCache();
}

@Override
protected SkinBase<?, ?> buildSkin() {
return new SkinBase<>(this) {
final Label label = new Label();

{
CellBase<Integer> cell = getSkinnable();
listeners(
When.onInvalidated(cell.itemProperty())
.then(this::byItem)
.executeNow(),
When.onInvalidated(cell.indexProperty())
.then(this::byIndex)
.executeNow()
);
label.setStyle("-fx-border-color: red");
getChildren().add(label);
}

private void byItem(Integer it) {
counter.item();
int idx = getIndex();
label.setText("Index: %d Item: %s".formatted(
idx,
it != null ? it.toString() : ""
));
}

private void byIndex(Number index) {
counter.index();
Integer it = getItem();
label.setText("Index: %d Item: %s".formatted(
index.intValue(),
it != null ? it.toString() : ""
));
}

@Override
protected void initBehavior(CellBaseBehavior<Integer> behavior) {}

@Override
protected void layoutChildren(double x, double y, double w, double h) {
label.resizeRelocate(x, y, w, h);
}
};
}
}

public static class Counter {
public int created = 0;
private int layoutCnt = 0;
private int updIndexCnt = 0;
private int updItemCnt = 0;
private int fromCache = 0;
private int toCache = 0;

public void created() {created++;}

public int getCreated() {
return created;
}

public void layout() {layoutCnt++;}

public int getLayoutCnt() {
return layoutCnt;
}

public void index() {updIndexCnt++;}

public int getUpdIndexCnt() {
return updIndexCnt;
}

public void item() {updItemCnt++;}

public int getUpdItemCnt() {
return updItemCnt;
}

public void fCache() {fromCache++;}

public int getFromCache() {
return fromCache;
}

public void tCache() {toCache++;}

public int getToCache() {
return toCache;
}

public void reset() {
created = 0;
layoutCnt = 0;
updIndexCnt = 0;
updItemCnt = 0;
fromCache = 0;
toCache = 0;
}
}
}

Loading

0 comments on commit 0149334

Please sign in to comment.