On Tue, 27 Jul 2021 23:15:10 GMT, Michael Strauß <[email protected]> wrote:
> Based on previous discussions, this PR attempts to improve the JavaFX
> property system by enforcing correct API usage in several cases that are
> outlined below. It also streamlines the API by deprecating untyped APIs in
> favor of typed APIs that better express intent.
>
> ### 1. Behavioral changes for regular bindings
>
> var target = new SimpleObjectProperty(bean, "target");
> var source = new SimpleObjectProperty(bean, "source");
> target.bind(source);
> target.bindBidirectional(source);
>
> _Before:_ `RuntimeException` --> "bean.target: A bound value cannot be set."
> _After:_ `IllegalStateException` --> "bean.target: Bidirectional binding
> cannot target a bound property."
>
>
> var target = new SimpleObjectProperty(bean, "target");
> var source = new SimpleObjectProperty(bean, "source");
> var other = new SimpleObjectProperty(bean, "other");
> source.bind(other);
> target.bindBidirectional(source);
>
> _Before:_ no error
> _After:_ `IllegalArgumentException` --> "bean.source: Bidirectional binding
> cannot target a bound property."
>
>
> var target = new SimpleObjectProperty(bean, "target");
> var source = new SimpleObjectProperty(bean, "source");
> target.bindBidirectional(source);
> target.bind(source);
>
> _Before:_ no error
> _After:_ `IllegalStateException` --> "bean.target: Cannot bind a property
> that is targeted by a bidirectional binding."
>
>
> ### 2. Behavioral changes for content bindings
>
> var target = new SimpleListProperty(bean, "target");
> var source = new SimpleListProperty(bean, "source");
> target.bindContent(source);
> target.bindContentBidirectional(source);
>
> _Before:_ no error
> _After:_ `IllegalStateException` --> "bean.target: Bidirectional content
> binding cannot target a bound collection."
>
>
> var target = new SimpleListProperty(bean, "target");
> var source = new SimpleListProperty(bean, "source");
> var other = new SimpleListProperty();
> source.bindContent(other);
> target.bindContentBidirectional(source);
>
> _Before:_ no error
> _After:_ `IllegalArgumentException` --> "bean.source: Bidirectional content
> binding cannot target a bound collection."
>
>
> var target = new SimpleListProperty(bean, "target");
> var source = new SimpleListProperty(bean, "source");
> target.bindContentBidirectional(source);
> target.bindContent(source);
>
> _Before:_ no error
> _After:_ `IllegalStateException` --> "bean.target: Cannot bind a collection
> that is targeted by a bidirectional content binding."
>
>
> var target = new SimpleListProperty(bean, "target");
> var source = new SimpleListProperty(bean, "source");
> target.bindContent(source);
> target.set(FXCollections.observableArrayList());
>
> _Before:_ no error
> _After:_ `IllegalStateException` --> "bean.target: Cannot set the value of a
> content-bound property."
>
>
> var target = new SimpleListProperty(bean, "target");
> var source = new SimpleListProperty(bean, "source");
> target.bindContent(source);
> target.add("foo");
>
> _Before_: no error, but binding is broken because the lists are in an
> inconsistent state
> _After:_ `RuntimeExeption` via `Thread.UncaughtExceptionHandler` --> "Illegal
> list modification: Content binding was removed because the lists are
> out-of-sync."
>
>
> ### 3. Align un-binding of unidirectional content bindings with regular
> unidirectional bindings
> The API of unidirectional content bindings is aligned with regular
> unidirectional bindings because the semantics are similar. Like `unbind()`,
> `unbindContent(Object)` should not need an argument because there can only be
> a single content binding. For this reason, `unbindContent(Object)` will be
> deprecated in favor of `unbindContent()`:
>
> void bindContent(ObservableList<E> source);
> + void unbindContent();
> + boolean isContentBound();
>
> + @Deprecated(since = "18", forRemoval = true)
> void unbindContent(Object object);
>
>
> ### 4. Replace untyped binding APIs with typed APIs
> The following untyped APIs will be marked for removal in favor of typed
> replacements:
> In `javafx.beans.binding.Bindings`:
>
> @Deprecated(since = "18", forRemoval = true)
> void unbindBidirectional(Object property1, Object property2)
>
> @Deprecated(since = "18", forRemoval = true)
> void unbindContentBidirectional(Object obj1, Object obj2)
>
> @Deprecated(since = "18", forRemoval = true)
> void unbindContent(Object obj1, Object obj2)
>
>
> In `ReadOnlyListProperty`, `ReadOnlySetProperty`, `ReadOnlyMapProperty`:
>
> @Deprecated(since = "18", forRemoval = true)
> void unbindContentBidirectional(Object object)
>
>
> ~~5. Support un-binding bidirectional conversion bindings with typed API
> At this moment, `StringProperty` is the only property implementation that
> offers bidirectional conversion bindings, where the `StringProperty` is bound
> to a property of another type:~~
>
> <U> void bindBidirectional(Property<U> other, StringConverter<U> converter)
>
> ~~The inherited `Property.unbindBidirectional(Property<String>)` API cannot
> be used to unbind a conversion binding, because it only accepts arguments of
> type `Property<String>`.
> `StringProperty` solves this issue by adding an untyped overload:
> `unbindBidirectional(Object)`.~~
>
> ~~I propose to relax the definition of `Property.unbindBidirectional`:~~
>
> - void unbindBidirectional(Property<T> other);
> + void unbindBidirectional(Property<?> other);
>
> ~~This allows property implementations to use the same API to un-bind regular
> bidirectional bindings, as well as converting bidirectional bindings. The
> `Property` typing is retained with a minimal impact on existing code (most
> _usages_ of this API will continue to compile, while classes that override
> `unbindBidirectional` will need to be changed to match the new API).~~
>
> ~~As a side-effect, this allows the option of easily adding conversion
> bindings for other property implementations as well.~~
Moving to Draft until the discussion surrounding the API issues is resolved.
When they are, this will need a CSR and two reviewers.
-------------
PR: https://git.openjdk.java.net/jfx/pull/590