org.fxmisc.flowless.StableBidirectionalVar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Flowless Show documentation
Show all versions of Flowless Show documentation
Efficient VirtualFlow for JavaFX.
The newest version!
package org.fxmisc.flowless;
import java.util.function.Consumer;
import org.reactfx.Subscription;
import org.reactfx.value.ProxyVal;
import org.reactfx.value.Val;
import org.reactfx.value.Var;
import javafx.application.Platform;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
/**
* This class overrides the Var.bindBidirectional
method implementing a mechanism to prevent looping.
*
By default bindBidirectional
delegates to Bindings.bindBidirectional
* which isn't always stable for the Val -> Var paradigm, sometimes producing a continuous feedback loop.
*/
class StableBidirectionalVar extends ProxyVal implements Var
{
private final Consumer setval;
private Subscription binding = null;
private ChangeListener left, right;
private T last = null;
StableBidirectionalVar( Val underlying, Consumer setter )
{
super( underlying );
setval = setter;
}
@Override
public T getValue()
{
return getUnderlyingObservable().getValue();
}
@Override
protected Consumer super T> adaptObserver( Consumer super T> observer )
{
return observer; // no adaptation needed
}
@Override
public void bind( ObservableValue extends T> observable )
{
unbind();
binding = Val.observeChanges( observable, (ob,ov,nv) -> setValue( nv ) );
setValue( observable.getValue() );
}
@Override
public boolean isBound()
{
return binding != null;
}
@Override
public void unbind()
{
if( binding != null ) binding.unsubscribe();
binding = null;
}
@Override
public void setValue( T newVal )
{
setval.accept( newVal );
}
@Override
public void unbindBidirectional( Property prop )
{
if ( right != null ) prop.removeListener( right );
if ( left != null ) removeListener( left );
left = null; right = null;
}
@Override
public void bindBidirectional( Property prop )
{
unbindBidirectional( prop );
prop.addListener( right = (ob,ov,nv) -> adjustOther( this, nv ) );
addListener( left = (ob,ov,nv) -> adjustOther( prop, nv ) );
}
private void adjustOther( Property other, T nv )
{
if ( ! nv.equals( last ) )
{
Platform.runLater( () -> other.setValue( nv ) );
last = nv;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy