org.reactfx.collection.ListReduction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richtextfx Show documentation
Show all versions of richtextfx Show documentation
FX-Text-Area for formatted text and other special effects.
package org.reactfx.collection;
import java.util.function.BinaryOperator;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.scene.control.IndexRange;
import org.reactfx.Subscription;
import org.reactfx.util.Experimental;
import org.reactfx.util.FingerTree;
import org.reactfx.util.ToSemigroup;
import org.reactfx.value.Val;
import org.reactfx.value.ValBase;
class ListReduction extends ValBase {
private final ObservableList input;
private final BinaryOperator reduction;
private final ToSemigroup monoid;
private FingerTree tree = null;
ListReduction(
ObservableList input,
BinaryOperator reduction) {
this.input = input;
this.reduction = reduction;
monoid = new ToSemigroup() {
@Override
public T apply(T t) {
return t;
}
@Override
public T reduce(T left, T right) {
return reduction.apply(left, right);
}
};
}
@Override
protected Subscription connect() {
assert tree == null;
tree = FingerTree.mkTree(input, monoid);
return LiveList.observeChanges(input, ch -> {
for(ListModification extends T> mod: ch) {
FingerTree left = tree.split(mod.getFrom())._1;
FingerTree right = tree.split(mod.getFrom() + mod.getRemovedSize())._2;
FingerTree middle = FingerTree.mkTree(mod.getAddedSubList(), monoid);
tree = left.join(middle).join(right);
}
invalidate();
})
.and(() -> tree = null);
}
protected int getFrom(int max) {
return 0;
}
protected int getTo(int max) {
return max;
}
@Override
protected final T computeValue() {
if(isObservingInputs()) {
assert tree != null;
int max = tree.getLeafCount();
return tree.getSummaryBetween(getFrom(max), getTo(max)).orElse(null);
} else {
assert tree == null;
int max = input.size();
return input.subList(getFrom(max), getTo(max))
.stream().reduce(reduction).orElse(null);
}
}
}
@Experimental
class ListRangeReduction extends ListReduction {
private final ObservableValue range;
ListRangeReduction(
ObservableList input,
ObservableValue range,
BinaryOperator reduction) {
super(input, reduction);
this.range = range;
}
@Override
protected Subscription connect() {
return super.connect().and(Val.observeInvalidations(range, obs -> invalidate()));
}
@Override
protected int getFrom(int max) {
return Math.min(range.getValue().getStart(), max);
}
@Override
protected int getTo(int max) {
return Math.min(range.getValue().getEnd(), max);
}
}