<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p><br>
</p>
<div class="moz-cite-prefix">On 07/08/2025 17:45, Martin Fox wrote:<br>
</div>
<blockquote type="cite"
cite="mid:9A6D0794-D1A5-45CE-9CF9-838D9A55016E@gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<br id="lineBreakAtBeginningOfMessage">
<div><br>
<blockquote type="cite">
<div>On Aug 6, 2025, at 3:54 PM, John Hendrikx
<a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a> wrote:</div>
<br class="Apple-interchange-newline">
<div>
<meta charset="UTF-8">
<br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">On
06/08/2025 18:06, Martin Fox wrote:</span>
<blockquote type="cite"
style="font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">The
TextField of a ComboBox or Spinner is not just an artifact
of its skin. They are both explicitly composite controls
that contains a TextField inside. It’s part of the API.
And if you were to install some filters on the Scene to
track Key and InputMethod events you could easily conclude
that that TextField is the focus owner (it walks like the
focus owner, it quacks like the focus owner).<br>
</blockquote>
<br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">I
disagree. A ComboBox and Spinner are primitives. Their</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">implementation
via replacable Skins may or may not use a TextField,</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">that's
completely up to the Skin.</span></div>
</blockquote>
<div><br>
</div>
As I mentioned in my earlier e-mail (in the paragraph you
quoted) the TextField is part of the ComboBox and Spinner API.
Accessing it is the only way to, say, attach a TextFormatter to
a Spinner. Consult the docs starting at version 2.2.</div>
</blockquote>
<p>I took another look here, and printed this field.<br>
<br>
- It's a FakeFocusTextField (sigh)<br>
- It was available immediately even before a Skin was applied<br>
- It remains available even if another Skin is applied that
doesn't have a TextField<br>
<br>
This really is only another example of lazy design, exposing part
of the inner workings of a Control to avoid having to duplicate
some properties that are relevant to Spinners as a primitive. The
returned TextField is not mandated to be used by the Skin, and so
it can just do nothing (ie. if the Skin prefers using a Label).
The TextFormatter would be relevant in either case, and should
have been a top level property, that the Skin may bind to.</p>
<p>All I'm seeing is a brilliant design idea (skinnable controls,
with separated behaviors) executed poorly:</p>
<p>- Behavior and Skins referring to each other<br>
- Skins given too much access to Controls (write access to any
property should not be allowed, nor should Skins be allowed to
install event handlers on their host Control)<br>
- Behaviors installing Event Handlers directly mixing with user
handlers<br>
- Controls exposing sub controls that it can't guarantee will be
there or used, per how Skins work<br>
- Events not being targetted at the Control black box<br>
- Internal Skin level Events leaking to the outside world
(completely unnecessarily as this can be 100% avoided already now)<br>
- Skins not being isolated properly so replacing Skins can leave
old listeners behind (it requires co-operation of the Skin, while
it should be automatic)<br>
- Behavior's handling navigation events directly instead of
letting them bubble up often blocking users from handling them
first<br>
- ... and now another: failure to hoist up relevant properties to
the main Control (or make them styleable and part of the Skin
provided properties)</p>
<blockquote type="cite"
cite="mid:9A6D0794-D1A5-45CE-9CF9-838D9A55016E@gmail.com">
<div>The proposal (lifted from WPF) is to provide a mechanism
which would allow a Control to replace an event’s original
target with itself. This is a low-cost way of making the control
appear to be a black box at the event level. It would certainly
have a lower cost than, say, trying to hide skin nodes from the
rest of the scene graph. I’m not aware of any toolkit that even
attempts that.</div>
</blockquote>
Skins by their definition have free reign what nodes they create.
It's not hiding anything when you simply can't, nor should rely on
anything being there specifically. It therefore makes sense to
disallow access to these nodes programmatically for the user. These
extra nodes (if they exist) are only targettable by CSS, which is
fine in my book as CSS can set a Skin, or know what Skins are
present by default for a default stylesheet. <br>
<br>
I'm not saying this can be changed still, I'm saying what it should
have been had the idea of Skins not been subverted into its current
state. I would like to prevent adding any more leaks, and plugging
leaks that we can.<br>
<br>
Adding an extra field to events to support the internal event
dispatching system (preferably not public API) is fine with me.<br>
<blockquote type="cite"
cite="mid:9A6D0794-D1A5-45CE-9CF9-838D9A55016E@gmail.com">
<div><br>
</div>
<div>
<blockquote type="cite">
<div><span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">-
Skins re-use listener and event handler endpoints on the
Control,</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">leaving
users baffled by events sometimes being consumed before
they see</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">them
(if they added their handler late) or after they see them
(if they</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">were
the first to add their handler, or if the Skin was
replaced causing</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">a
re-ordering -- something very interesting to deal with);
for listeners</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">this
is relatively safe, as they don't have a consumption
mechanism, but</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">not
for events -- another mistake; skin event handlers should
have been</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">part
of a separate list so there can never be any intermixing
of user</span><br
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<span
style="caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">and
skin event handlers</span></div>
</blockquote>
<br>
</div>
This is a known pain point for developers that can be fixed
without re-writing the underpinnings of JavaFX (in other words,
with a reasonable cost/benefit ratio). I’m not sure why it hasn’t
been done already.<br>
</blockquote>
I have no idea either, it's a no-brainer.<br>
<br>
--John<br>
<blockquote type="cite"
cite="mid:9A6D0794-D1A5-45CE-9CF9-838D9A55016E@gmail.com">
<div>
<div><br>
</div>
<div>Martin</div>
</div>
</blockquote>
</body>
</html>