Discussion: Naming API method
John Hendrikx
john.hendrikx at gmail.com
Mon Nov 21 21:57:40 UTC 2022
Hi Michael,
Thanks for your suggestion.
The effect is not quite what you describe however, as the initial value
when the operation is first invoked is retained. It's true however that
when the condition is always `false` that the value will be a constant,
and that when it is always `true` it effectively is just a duplicate of
the left hand observable. Let me illustrate:
public static void main(String[] args) {
StringProperty sp = new SimpleStringProperty("foo");
BooleanProperty active = new SimpleBooleanProperty(false); //
inactive
ObservableValue<String> x = sp.when(active); // holds "foo"
despite being inactive
System.out.println(x.getValue()); // prints "foo"
sp.set("bar");
System.out.println(x.getValue()); // still prints "foo"
active.set(true);
System.out.println(x.getValue()); // prints "bar"
}
This behavior doesn't violate the rule that the new binding shouldn't
observe its source when the condition is false as no listener was
involved to get the initial value. The initial value is important as
all bindings must have some kind of value. The docs do describe this in
the first sentence:
"Returns an {@code ObservableValue} that holds this value and is updated
only when {@code condition} holds {@code true}"
I think `withScope` could work (or `scopedTo`) but not sure if "scope"
itself is a good description -- we'd need to update the description to
use the word scope in a way that makes clear what it does preferably
without having to resort to "updated only when" or "only observes when":
ie: "Returns an ObservableValue that is scoped to the given condition" ?
--John
On 15/11/2022 19:38, Michael Strauß wrote:
> The new operation returns a new ObservableValue that is only
> meaningfully "exists" when the condition holds.
> If the condition doesn't hold, the effect is as if the operation
> wasn't invoked at all, i.e. it doesn't meaningfully exist.
>
> With this in mind, here's another option:
> label.textProperty().bind(longLivedProperty.withScope(container::isShownProperty));
>
> On Mon, Nov 14, 2022 at 3:53 PM John Hendrikx <john.hendrikx at gmail.com> wrote:
>> Hi,
>>
>> I'm working on https://github.com/openjdk/jfx/pull/830 where I asked for
>> some opinions on the naming of a new method I'd like to introduce in
>> ObservableValue.
>>
>> I wrote a (perhaps too large) comment about the possible names and
>> rationales: https://github.com/openjdk/jfx/pull/830#issuecomment-1304846220
>>
>> I'd like to ask what others think what would be a good name for this new
>> method (Observable#when in the PR) in order to move the PR forward, as I
>> think it offers a very compelling feature to JavaFX (moving from weak
>> reference to deterministic behavior when it comes to listener
>> management). My opinion has always been that using weak listeners for
>> listener management is a crutch that relies far too much on the internal
>> workings of the JVM and Garbage Collector which offer no guarantees as
>> to the timely clean up of these references and the listeners related to
>> them.
>>
>> Leading contenders are (but not limited to these, if you have a better
>> name):
>>
>> 1) conditionOn
>>
>> 2) updateWhen
>>
>> 3) when
>>
>> 4) whenever
>>
>> Usage in code is nearly always going to be something like these constructs:
>>
>> // keeps text property in sync with longLivedProperty when label
>> is shown:
>> label.textProperty().bind(longLivedProperty.**when**(label::isShownProperty));
>>
>> // keeps text property in sync with longLivedProperty when
>> container is shown:
>> label.textProperty().bind(longLivedProperty.**when**(container::isShownProperty));
>>
>>
>> It can also be used to make a listener only actively listen when a
>> condition is met (the listener is added/removed immediately when the
>> condition changes, facilitating GC):
>>
>> // listen to changes of longLivedProperty when container is shown:
>> longLivedProperty.when(container::isShownProperty)
>> .addListener((obs, old, current) -> { ... change listener
>> ... });
>>
>> Or it can be used to disable updates temporarily (or permanently):
>>
>> BooleanProperty allowUpdates = new SimpleBooleanProperty(true)
>>
>> // keeps text property in sync when updates are allowed:
>> name.textProperty().bind(model.title.when(allowUpdates));
>> detail.textProperty().bind(model.subtitle.when(allowUpdates));
>> asyncImageProperty.imageHandleProperty().bind(model.imageHandle.when(allowUpdates));
>>
>> This last example can be useful in Skin#dispose, but has uses outside of
>> skins as well, for example when you want to prevent updates until things
>> have settled down.
>>
>> Thanks for reading!
>>
>> --John
>>
>>
More information about the openjfx-dev
mailing list