All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fxmisc.flowless.StableBidirectionalVar Maven / Gradle / Ivy

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 adaptObserver( Consumer observer ) { return observer; // no adaptation needed } @Override public void bind( ObservableValue 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