package org.fxmisc.easybind;
import org.fxmisc.easybind.monadic.MonadicBinding;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.WeakInvalidationListener;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.value.ObservableValue;
class FirstNonNullBinding<T> extends ObjectBinding<T> implements MonadicBinding<T> {
private final ObservableValue<? extends T>[] chain;
private final InvalidationListener listener = obs -> srcInvalidated(obs);
private final InvalidationListener weakListener = new WeakInvalidationListener(listener);
private int startAt = 0;
@SafeVarargs
public FirstNonNullBinding(ObservableValue<? extends T>... chain) {
this.chain = chain;
for(int i = 0; i < chain.length; ++i) {
chain[i].addListener(weakListener);
}
}
@Override
public void dispose() {
for(int i = 0; i < chain.length; ++i) {
chain[i].removeListener(weakListener);
}
}
@Override
protected T computeValue() {
for(int i = startAt; i < chain.length; ++i) {
T val = chain[i].getValue();
if(val != null) {
startAt = i;
return val;
}
}
startAt = chain.length;
return null;
}
private void srcInvalidated(Observable src) {
for(int i = 0; i < chain.length; ++i) {
if(chain[i] == src) {
srcInvalidated(i);
break;
}
}
}
private void srcInvalidated(int index) {
if(index <= startAt) {
startAt = index;
invalidate();
}
}
}