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.hendr...@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