BindingsManager { public <T> void bindTwoWay(@NotNull SettableValue<T> first, @NotNull SettableValue<T> second) { releaseTwoWay(first, second); myTwoWayBindings.add(new TwoWayBinding<>(first, second)); } BindingsManager();  BindingsManager(@NotNull BatchInvoker.Strategy invokeStrategy); void bind(@NotNull SettableValue<T> dest, @NotNull ObservableValue<T> src); void bind(@NotNull SettableValue<T> dest, @NotNull ObservableValue<T> src, @NotNull ObservableValue<Boolean> enabled); void bindTwoWay(@NotNull SettableValue<T> first, @NotNull SettableValue<T> second); void release(@NotNull SettableValue<?> dest); void releaseTwoWay(@NotNull SettableValue<T> first, @NotNull SettableValue<T> second); void releaseTwoWay(@NotNull SettableValue<T> value); void releaseAll();  }
@Test public void twoWayBindingsAffectEachOther() throws Exception { BindingsManager bindings = new BindingsManager(BatchInvoker.INVOKE_IMMEDIATELY_STRATEGY); IntValueProperty property1 = new IntValueProperty(10); IntValueProperty property2 = new IntValueProperty(20); bindings.bindTwoWay(property1, property2); assertThat(property1.get()).isEqualTo(20); property1.set(30); assertThat(property2.get()).isEqualTo(30); property2.set(40); assertThat(property1.get()).isEqualTo(40); }
@Test public void twoWayBindingsCanBeChained() { BindingsManager bindings = new BindingsManager(BatchInvoker.INVOKE_IMMEDIATELY_STRATEGY); IntValueProperty a = new IntValueProperty(); IntValueProperty b = new IntValueProperty(); IntValueProperty c = new IntValueProperty(); bindings.bindTwoWay(a, b); bindings.bindTwoWay(b, c); c.set(30); assertThat(a.get()).isEqualTo(30); assertThat(b.get()).isEqualTo(30); assertThat(c.get()).isEqualTo(30); b.set(-100); assertThat(a.get()).isEqualTo(-100); assertThat(b.get()).isEqualTo(-100); assertThat(c.get()).isEqualTo(-100); a.set(9); assertThat(a.get()).isEqualTo(9); assertThat(b.get()).isEqualTo(9); assertThat(c.get()).isEqualTo(9); }