On 07/08/2025 17:45, Martin Fox wrote: > > >> On Aug 6, 2025, at 3:54 PM, John Hendrikx <john.hendr...@gmail.com> >> wrote: >> >> >> On 06/08/2025 18:06, Martin Fox wrote: >>> 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). >> >> I disagree. A ComboBox and Spinner are primitives. Their >> implementation via replacable Skins may or may not use a TextField, >> that's completely up to the Skin. > > 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.
I took another look here, and printed this field. - It's a FakeFocusTextField (sigh) - It was available immediately even before a Skin was applied - It remains available even if another Skin is applied that doesn't have a TextField 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. All I'm seeing is a brilliant design idea (skinnable controls, with separated behaviors) executed poorly: - Behavior and Skins referring to each other - 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) - Behaviors installing Event Handlers directly mixing with user handlers - Controls exposing sub controls that it can't guarantee will be there or used, per how Skins work - Events not being targetted at the Control black box - Internal Skin level Events leaking to the outside world (completely unnecessarily as this can be 100% avoided already now) - 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) - Behavior's handling navigation events directly instead of letting them bubble up often blocking users from handling them first - ... and now another: failure to hoist up relevant properties to the main Control (or make them styleable and part of the Skin provided properties) > 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. 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. 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. Adding an extra field to events to support the internal event dispatching system (preferably not public API) is fine with me. > >> - Skins re-use listener and event handler endpoints on the Control, >> leaving users baffled by events sometimes being consumed before they see >> them (if they added their handler late) or after they see them (if they >> were the first to add their handler, or if the Skin was replaced causing >> a re-ordering -- something very interesting to deal with); for listeners >> this is relatively safe, as they don't have a consumption mechanism, but >> not for events -- another mistake; skin event handlers should have been >> part of a separate list so there can never be any intermixing of user >> and skin event handlers > > 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. I have no idea either, it's a no-brainer. --John > > Martin