<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>You are right, I did use an even older style, guess that shows
how rarely I even look at the `Bindings` class these days as
almost everything can be done fluently now.</p>
<p>The JEP I propose is specifically to fill a gap in the fluent
bindings, but that doesn't mean this is currently impossible to
achieve. It is similar to how `map` basically can replace 50% of
the methods in `Bindings` and how `flatMap` replaces all the
`select` methods.</p>
<p>The reason I'm proposing it is to make fluent bindings possible
with more than one source. I mean, I can do this:</p>
<p> Property<Point2D> point = ...;<br>
<br>
label.textProperty().bind(point.map(p -> "x: " + p.getX()
+ ", y: " + p.getY()));<br>
<br>
But when the things I need are stored in multiple properties,
`map` becomes useless:<br>
<br>
IntegerProperty xpos = ... ;<br>
IntegerProperty ypos = ... ;<br>
<br>
// can't use `map` on `xpos` or `ypos` as it would only react
if one of these properties change<br>
<br>
In the proposal, it would become possible to observe and react to
multiple sources:<br>
<br>
xpos.with(ypos).map((x, y) -> "x: " + x + ", y: " + y);<br>
<br>
I've limited the proposal to two sources as this is sufficient to
scale to an arbitrary number, albeit with additional mapping
steps. It is however open ended and can be extended to more than
2 sources easily (which is something open for discussion or
possible as an extension later). In other words, by adding
another helper interface we can also have:<br>
<br>
xpos.with(ypos, zpos).map((x, y, z) -> ... );<br>
<br>
In its most basic form however, two sources will also work:<br>
<br>
xpos.with(ypos).map(Point2D::new).with(zpos).map((p, z) ->
... );<br>
<br>
I think supporting two sources will cover 80% of the cases without
requiring additional mapping steps, and that quickly approaches
100% when you potentially allow for 3 or 4 sources.<br>
</p>
--John<br>
<br>
<div class="moz-cite-prefix">On 27/10/2025 20:48, Andy Goryachev
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CY8PR10MB72655E830791B5D49CFA80CDE5FCA@CY8PR10MB7265.namprd10.prod.outlook.com">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<div dir="ltr"
style="font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Doesn't </div>
<div dir="ltr"
style="font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div dir="ltr"
style="font-family: "Iosevka Fixed SS16"; font-size: 12pt;"><span
style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">DoubleBinding
</span><span
style="color: rgb(0, 0, 0); background-color: rgb(212, 212, 212);">createDoubleBinding</span><span
style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">(</span><span
style="color: rgb(78, 143, 0); background-color: rgb(255, 255, 255);">final</span><span
style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);"> Callable<Double>
func, </span><span
style="color: rgb(78, 143, 0); background-color: rgb(255, 255, 255);">final</span><span
style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);"> Observable...
dependencies)</span></div>
<div dir="ltr"
style="font-family: "Iosevka Fixed SS16"; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="background-color: rgb(255, 255, 255);"><br>
</span></div>
<div dir="ltr"
style="font-family: "Iosevka Fixed SS16"; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="background-color: rgb(255, 255, 255);">handles the
use case you describe?</span></div>
<div dir="ltr"
style="font-family: "Iosevka Fixed SS16"; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="background-color: rgb(255, 255, 255);"><br>
</span></div>
<div dir="ltr"
style="font-family: "Iosevka Fixed SS16"; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="background-color: rgb(255, 255, 255);">-andy</span></div>
<div dir="ltr"
style="font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="mail-editor-reference-message-container">
<div class="ms-outlook-mobile-reference-message skipProofing">
<meta name="Generator" content="Microsoft Exchange Server">
</div>
<div class="ms-outlook-mobile-reference-message skipProofing"
style="text-align: left; padding: 3pt 0in 0in; border-width: 1pt medium medium; border-style: solid none none; border-color: rgb(181, 196, 223) currentcolor currentcolor; font-family: Aptos; font-size: 12pt; color: black;">
<b>From: </b>openjfx-dev <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev-retn@openjdk.org"><openjfx-dev-retn@openjdk.org></a>
on behalf of John Hendrikx <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
<b>Date: </b>Sunday, October 26, 2025 at 02:59<br>
<b>To: </b>openjfx-dev <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>JEP Proposal: Fluent Bindings for multiple
observables<br>
<br>
</div>
<div class="PlainText" style="font-size: 11pt;">JEP: <a
href="https://gist.github.com/hjohn/611acb65769b68a845b8919c62a3e99a"
data-outlook-id="4ef3afb8-941c-4127-ae81-efc74a2f1438"
moz-do-not-send="true" class="moz-txt-link-freetext">
https://gist.github.com/hjohn/611acb65769b68a845b8919c62a3e99a</a><br>
<br>
Hi everyone,<br>
<br>
I'd like to propose an extension to the fluent bindings API on<br>
ObservableValue (map, flatMap, orElse) which were introduced
in JavaFX<br>
19 over 3 years ago.<br>
<br>
The API currently is very powerful when dealing with a single<br>
observable, but lacks support when dealing with multiple
observables. <br>
For example, let's say you want to compute a width/height
ratio. You<br>
could write this:<br>
<br>
ObservableValue<Double> ratio = width.map(w -> w
/ height.get());<br>
<br>
... but you'll quickly find that such an observable will not
update<br>
itself when height changes, only when width changes.<br>
<br>
The go-to solution for this is currently:<br>
<br>
DoubleBinding ratio = new DoubleBinding() {<br>
{ bind(width, height); }<br>
<br>
protected double computeValue() { return width.get() /<br>
height.get(); }<br>
}<br>
<br>
My proposal would extend ObservableValue with a new `with`
method that<br>
returns an intermediate stage that can be easily converted
back to an<br>
ObservableValue:<br>
<br>
ObservableValue<Double> ratio =
width.with(height).map((w, h) -> w /<br>
h); // yields a ratio that updates whenever w or h changes<br>
<br>
Or for example:<br>
<br>
ObservableValue<Point> point =
x.with(y).map(Point::new); //<br>
yields a Point that updates whenever x or y changes<br>
<br>
The intermediate stage would not be an observable value
itself. This<br>
limits the API surface, and makes this proposal fairly
lightweight and<br>
much easier to implement.<br>
<br>
Please see the JEP for the full proposal. I look forward to
your feedback!<br>
<br>
--John<br>
<br>
<br>
</div>
</div>
</blockquote>
</body>
</html>