[External] : Re: Proof of concept pull request for Behavior API (PR 1265)
John Hendrikx
john.hendrikx at gmail.com
Tue Oct 31 23:13:45 UTC 2023
Hi Andy,
I'm sorry if you feel I blocked your proposal. Discussions better
happen at a stage far before a PR is being reviewed, and instead of
having these discussions here, we could have had them on the PR.
I'll try and formalize my proposals.
--John
On 30/10/2023 20:32, Andy Goryachev wrote:
>
> Dear John:
>
> I'm unsure what the JEP format would contribute here
>
> The benefit of JEP format is
>
> a) to explicitly state the problem being solved (in the Motivation
> section)
>
> b) to enumerate the public APIs
>
> I have several proposals, and some are too big for a single proposal
> (IMHO) which would you like me to focus on?
>
> The main reason I am asking you to go through the process is because
> you effectively blocked by InputMap proposal. I keep hearing that my
> proposal is not good for various reasons, while there is a much better
> way for doing things, so let’s see it in full detail. It would be
> nice to have proof-of-concept code based on a complex control rather
> than a simple Button, but it is not a requirement, at least initially.
>
> I still want to see code examples (pseudo code is fine) for my questions:
>
> Q1. Changing an existing key binding from one key combination to another.
>
> Q2. Remapping an existing key binding to a different function.
>
> Q3. Unmapping an existing key binding.
>
> Q4. Adding a new key binding mapped to a new function.
>
> Q5. (Q1...Q4) scenarios, at run time.
>
> Q6. How the set behavior handles a change from the default skin to a
> custom skin with some visual elements that expects input removed, and
> some added.
>
> Q7. Once the key binding has been modified, is it possible to invoke
> the default functionality?
>
> Q8. How are the platform-specific key bindings created?
>
> Q9. How are the skin-specific (see Q6) handlers removed when changing
> the skins?
>
> Q10. When a key press happens, does it cause a linear search through
> listeners or just a map lookup?
>
> I think it is important to answer all questions during the discussion,
> as it helps all sides to understand how things work, and possibly make
> corrections. Since the bulk of my proposal deals with key bindings
> and user-/skin- installed handlers, I would like to see how you
> propose to deal with these problems.
>
> Another reason I asked you for a JEP is that you seem to brush aside
> my objections. For example, my objection to the stateless behavior
> was dealt with by inventing BehaviorContext, which I basically take as
> an acknowledgement that behaviors are not stateless. So let’s see
> exactly you envision things by describing the public API and perhaps
> the proof of concept code should also have two non-trivial controls,
> just to see whether BehaviorContext depends on the control class or not.
>
> How key bindings are done is IMHO more of an implementation detail of
> **specific** behaviors,
>
> I categorically disagree with this statement. As an application
> developer, I want to be able to set/modify/unmap key bindings via
> common public mechanism, make sure that the user mappings and handlers
> always take precedence over the skin ones, and make sure that skin
> changes leave the user mappings and handlers in place.
>
> It is certainly not an implementation detail and not a property of any
> specific behavior.
>
> Thank you, and I am looking forward to seeing answers to the questions
> posted earlier.
>
> -andy
>
> *From: *John Hendrikx <john.hendrikx at gmail.com>
> *Date: *Saturday, October 28, 2023 at 12:55
> *To: *Andy Goryachev <andy.goryachev at oracle.com>,
> openjfx-dev at openjdk.org <openjfx-dev at openjdk.org>, Kevin Rushforth
> <kevin.rushforth at oracle.com>
> *Subject: *Re: [External] : Re: Proof of concept pull request for
> Behavior API (PR 1265)
>
> Hi Andy,
>
> On 27/10/2023 19:10, Andy Goryachev wrote:
>
> Dear John:
>
> I think our goal is for all of us to agree on a solution which
> solves the problems. We are still talking, right?
>
> I have to say - it is very difficult to have a meaningful
> conversation when questions are not being answered. It is even
> more difficult to do over email and time zones, as the context can
> often be lost.
>
> I'm really a bit surprised, as I think I responded quite quickly to a
> lot of the posts surrounding the proposals, and also answered quite a
> lot of questions. The mailinglist format seems to have served Java
> quite well for this purpose for years now, and if memory serves,
> earlier FX proposals also were discussed here. I'm unsure what the
> JEP format would contribute here, given that it does not allow for
> inline comments or threads, but I'm not unwilling to try my hand at one.
>
>
>
> To reiterate, a proposal in a JEP format would be nice, so we can
> see the public API.
>
> Alright, this will take a bit of time. I have several proposals, and
> some are too big for a single proposal (IMHO) which would you like me
> to focus on?
>
> 1. A public Behavior API with the initial focus on being able to reuse
> and replace default behaviors
>
> This proposal would like to achieve a clear definition of a Behavior
> and clear separation (to aid in reusability and creation). It would
> define a Behavior interface, and a clean way of
> installing/uninstalling a behavior on controls. This would be
> primarily the Behavior/BehaviorContext part of my sample PR
> https://github.com/openjdk/jfx/pull/1265
> <https://urldefense.com/v3/__https:/github.com/openjdk/jfx/pull/1265__;!!ACWV5N9M2RV99hQ!LvWBWlmjB-JYcKnpZTbvjYwd1CItXTmycfx2D-BYmkbS7lxG6f4kwt2bmokpBwh63Gg_MNX5JzP747J1wgPuPY6Rq1H1$>,
> leaving the more controversial event definition parts out for now
>
> 1.1. A possible extension of the above Behavior API to allow changing
> high level behavior
>
> I'm not sure yet what would be a good approach here. I would probably
> either lean towards reusing the Event system for this, or doing this
> with overridable methods; ie. in order to override a function, listen
> for its event and call different code or trigger a different event;
> or, ensure there is an overridable method so it can be overriden
> directly in code.
>
> 1.2. An extension to the above behavior API to allow for more user
> friendly key rebinding
>
> The idea here would be to create a custom behavior (allowed by 1.),
> call into a behavior you want to modify to install its defaults, and
> then make changes after. There is more than one possible approach
> here. One I raised earlier was offering more specific methods on
> BehaviorContext. Another possiblity is to make it specific to certain
> behaviors only (MappableBehavior), or behaviors that can somehow
> provide an InputMap (without entangling everything).
>
> 2. An improved event handling system (Michael Strauss already did some
> work there) that would allow users to override or disable default
> event processing
>
> This would be a low-level improvement that would allow 3rd parties to
> override large parts of JavaFX in a supported manner. It would open
> the way to a 3rd party behavior system or navigation system, but also
> simpler things like just changing a key mapping, even ones claimed by
> behaviors currently. As it is a low level API, this would be somewhat
> cumbersome for seemingly simple tasks, and the various platforms would
> need to be supported manually.
>
> In essence the above proposal would allow user installed event
> handlers to receive any event before a default handler can get to it,
> so that say remapping the LEFT_ARROW key is actualy possible and
> doesn't magically disappear (many new users, including me at the time
> were/are somewhat surprised that an event handler installed on the
> control is not receiving all events). The root cause of this is the
> sharing of the event handling lists on the control with (magically)
> installed behaviors. The above proposal would change this (in a
> backwards compatible way) to work more like how default exception
> handlers work -- only unconsumed events that bubble up to the root
> level are considered for default behavior actions.
>
> ------
>
> As you can see, one my problems with answering the key rebinding
> questions is that IMHO this more of a later extension on a Behavior
> API; this means to get to the key remapping design, there first would
> need to be a Behavior API design. How key bindings are done is IMHO
> more of an implementation detail of **specific** behaviors, as there
> are probably more ways to do this. So for my proposals, a somewhat
> fleshed out Behavior API design is an important prerequisite before
> offering key rebinding.
>
> If we can advance this design far enough, we may see a way to do this
> without needing a Behavior API first; for example, we could have a
> Behavior interface, and a subtype, MappableBehavior; only behaviors of
> that sub type support key remapping, while general behaviors don't
> have to. This would make the key rebinding just something that
> **some** behaviors support, and not a general feature if it instead
> was added to say Control, Behavior or BehaviorContext. This may be a
> short cut that we could take to get to key rebinding quickly, without
> closing off a future behavior API.
>
> Again, thanks for reading, I look forward to some feedback, and as
> said, I will try put some time towards writing a JEP. I'm also happy
> to collaborate on this once a design direction becomes a bit more clear.
>
> --John
>
>
>
> Please, if you have time, answer these questions. A short
> pseudo-code example will be fine.
>
> Q1. Changing an existing key binding from one key combination to
> another.
>
> Q2. Remapping an existing key binding to a different function.
>
> Q3. Unmapping an existing key binding.
>
> Q4. Adding a new key binding mapped to a new function.
>
> Q5. (Q1...Q4) scenarios, at run time.
>
> Q6. How the set behavior handles a change from the default skin to
> a custom skin with some visual elements that expects input
> removed, and some added.
>
> Q7. Once the key binding has been modified, is it possible to
> invoke the default functionality?
>
> Q8. How are the platform-specific key bindings created?
>
> Q9. How are the skin-specific (see Q6) handlers removed when
> changing the skins?
>
> Q10. When a key press happens, does it cause a linear search
> through listeners or just a map lookup?
>
> Lastly, I do think prototyping the alternative proposal using
> simple control like Button is insufficient. TextArea would be
> much better, as it has a ton of key bindings, platform-specific
> logic, various handlers that do and do not consume events by default.
>
> Thank you
>
> -andy
>
> P.S. I noticed that I switched my PR to Open by mistake. Sorry,
> it’s back in Draft.
>
> *From: *John Hendrikx <john.hendrikx at gmail.com>
> <mailto:john.hendrikx at gmail.com>
> *Date: *Thursday, October 26, 2023 at 02:15
> *To: *Andy Goryachev <andy.goryachev at oracle.com>
> <mailto:andy.goryachev at oracle.com>, openjfx-dev at openjdk.org
> <openjfx-dev at openjdk.org> <mailto:openjfx-dev at openjdk.org>, Kevin
> Rushforth <kevin.rushforth at oracle.com>
> <mailto:kevin.rushforth at oracle.com>
> *Subject: *Re: [External] : Re: Proof of concept pull request for
> Behavior API (PR 1265)
>
> The normal procedure I think is also to first provide a JEP for
> review, before starting on the implementation...
>
> Given the doubts raised, feedback given and potential alternatives
> proposed, I don't see why you are still moving forward with your
> own proposal. The critiques I've given have been mostly hand waved
> with arguments that have no place in JEP evaluation (time
> restrictions, existing code already works this way, false
> equivalency with MVC pattern), and therefore have IMHO not been
> taken serious at all.
>
> This leaves me in the position of putting in a lot of work that
> will essentially be ignored as I feel an (internal) decision has
> already been reached, regardless of the feedback on the mailinglist.
>
> The (partial) proposal I've made, and also simpler proposals so
> that 3rd parties could do a keybinding implementation, should be
> sufficient to reconsider the current proposal that is being moved
> forward.
>
> I'll reiterate my problems with your proposal:
>
> - Introduces a lot of API for what is essentially the
> configuration of internal event handlers
> - The proposed API partially overlaps with the existing event
> handler API, meaning that some keys could be changed with just
> event handlers, while some can only be changed with the
> BaseBehavior API; it also provides for creating new functions and
> assigning them to keys, essentially a new (very limited) API for
> what was already possible in the much more flexible event handling API
> - Introduces the term "Behavior" in public API without clearly
> specifying what that is, nor showing enough forethought that may
> make it possible in the future to have public Behaviors
> - Introduces the term "InputMap" in public API, which is just an
> implementation detail of the internal event handlers
> - Doesn't address the real issue IMHO, which is that JavaFX
> Skins/Behaviors install their Event Handlers directly on Controls,
> mixing them with user event handlers leading to all sorts of
> unpredictable behavior due to call order and internal handlers
> essentially stealing and consuming events before the user has a
> chance to look at them (and thus blocking any 3rd party key
> alterations) which leads to the (false) need to change key
> bindings and Behaviors directly...
>
> So if you want me to work on such a proposal, fully fleshing it
> out, I would like to know if it will be given consideration. I
> would also like some more feedback on what is already there, as I
> think it is sufficient to decide if a full proposal is worth it or
> not.
>
> My proposals in short:
>
> 1.
>
> - Fix the issues with Events being stolen before users can get a them
> - Users should be able to have priority on Events, Michael
> Strauss already has a PR that fixes the issue in part
> - Events should not be consumed when not used (navigation does
> this) as this precludes the user being able to change their meaning
> - Even better would be if internal event handlers were
> isolated and did not mix themselves with user event handlers at all
>
> The above can be done separately, and should already make it
> possible to do a lot of things that were close to impossible
> before when it comes to changing key handling, but certainly not
> everything.
>
> - Building on top of the improved event handling system, introduce
> a flag to indicate an event is not to be consumed by internal
> event handlers
>
> These two together can form the basis for a 3rd party Behavior
> implementation as standard behavior can be prevented from
> occurring. It leaves platform dependent behavior to be addressed
> by such a 3rd party / user implementation as it is a very low
> level API. Any key remapping logic would be provided by the 3rd
> party API.
>
> 2.
>
> I also have a more fleshed out alternative proposal that attempts
> to introduce Behaviors into JavaFX as a first class concept,
> instead of a potential 3rd party add-on. Recap:
>
> - Introduce a Behavior interface with a single method "install" to
> be called by a Control
> - The "install" method is provided a context object,
> BehaviorContext. This indirects any changes the Behavior can make
> to a Control, so the Control is fully aware of all changes and can
> uninstall them without further co-operation from the behavior.
> - The BehaviorContext provides low level functions to add/remove
> event handlers and listeners, but can also provide higher level
> functions (in perhap a later PR) to allow for some kind of control
> provided input map system
> - Standard Behaviors can be made public and can be easily
> subclassed or composed as they need not have any state. State is
> tracked inside the behavorial installed listeners and handlers
> themselves (either directly or by referring to some shared State
> object).
> - Clear separation of concerns; Behaviors, a resuable concept that
> can be applied to a control; BehaviorContext, manages behavior
> lifecycle by abstracting away direct Control access; behavior
> state management left up to the implementation and created (on
> demand and as needed) when "install" is called.
> - Indirection from key mapping to semantic meaning is provided by
> introducing control specific events. These semantic events can be
> handled, filtered and consumed like all other events, allowing for
> changing/remapping/blocking or ignoring; this part can be left out
> from an initial implementation to further evaluate how such events
> might interact with Skins that need specific events (there is
> nothing stopping us from having some of these semantic events be
> handled by the Control directly, and some by the specific needs of
> the Skin)
>
> To get at the internal key mappings, you'd need to subclass or
> compose a Behavior. The Behaviors are setup to allow this
> easily. To modify the bindings of a Control, one would install
> such a modified Behavior as a whole; overkill perhaps for one
> binding change, but convenient when multiple bindings are changed,
> and reusable accross controls (the Behavior only need to be
> created once).
>
> The proposal also includes an indirection between Key/Mouse event
> and its semantic meaning. This is achieved by firing higher level
> more meaningful events, but that's not the only option; it could
> also be done with overridable methods on the Behavior, or a
> behavior specific interface if the Event based proposal is seen as
> too audacious.
>
> This proposal advocates a clear seperation of the Behavior from
> the Skin, essentially making them Controller and View, where the
> View has no knowledge of the Controller. I see no reason why this
> wouldn't be possible, given that it is a standard pattern. That
> existing controls may be difficult to untangle is IMHO irrelevant,
> especially when this can be done one at a time. I realize that
> Controllers (Behaviors) may have functions that are sort of View
> (Skin) specific; this is not an issue, as it should be fine to
> trigger a behavior without it being consumed; unconsumed
> behaviorial events just bubble up. This allows Behaviors to have
> events specific to a Skin without them interfering if they're
> unused by an alternative Skin. An alternative Skin that also
> needs new behavior will also need to create a new behavior to go
> along with it (or when paired with the standard one, accept that
> those new behaviors won't be triggered).
>
> Thanks for reading.
>
> --John
>
> On 26/10/2023 00:59, Andy Goryachev wrote:
>
> Dear John:
>
> It is difficult to review the alternative proposal for a
> number of reasons. A prototype is a good start, but for any
> proposal to go forward we need a bit more work. Let me
> enumerate the steps that we expect:
>
> 1. Provide an overview of the proposal following a JEP outline:
>
> *Summary*
>
> *Goals*
>
> *Non-Goals*
>
> *Motivation*
>
> *Description*
>
> *Alternatives*
>
> *Risks and Assumptions*
>
> *Dependencies*
>
> 2. A draft PR that provides a proof of concept, using, in this
> case, a few complex controls like TextArea, TableView, ComboBox.
>
> 3. Address the question raised earlier, perhaps by providing
> code examples (pseudo code is acceptable, I think).
>
> More specifically, I’d like to know how the following concerns
> will be addressed by the new proposal:
>
> Q1. Changing an existing key binding from one key combination
> to another.
>
> Q2. Remapping an existing key binding to a different function.
>
> Q3. Unmapping an existing key binding.
>
> Q4. Adding a new key binding mapped to a new function.
>
> Q5. (Q1...Q4) scenarios, at run time.
>
> Q6. How the set behavior handles a change from the default
> skin to a custom skin with some visual elements that expects
> input removed, and some added.
>
> Q7. Once the key binding has been modified, is it possible to
> invoke the default functionality?
>
> Q8. How are the platform-specific key bindings created?
>
> Q9. How are the skin-specific (see Q6) handlers removed when
> changing the skins?
>
> Q10. When a key press happens, does it cause a linear search
> or a map lookup?
>
> Thank you
>
> -andy
>
> *From: *John Hendrikx <john.hendrikx at gmail.com>
> <mailto:john.hendrikx at gmail.com>
> *Date: *Tuesday, October 24, 2023 at 04:58
> *To: *Andy Goryachev <andy.goryachev at oracle.com>
> <mailto:andy.goryachev at oracle.com>, openjfx-dev at openjdk.org
> <openjfx-dev at openjdk.org> <mailto:openjfx-dev at openjdk.org>
> *Subject: *Re: [External] : Re: Proof of concept pull request
> for Behavior API (PR 1265)
>
> On 23/10/2023 23:57, Andy Goryachev wrote:
>
> You'd create a new class, `MyBehavior`,
>
> By “customizing” I also mean at run time. Creating new
> classes wouldn’t work.
>
> This would also work at runtime, as the class you create can
> be instantiated with parameters that control its key binding
> behavior. Even though the standard Behaviors should probably
> be singletons (so they can be reused and composed) or have
> public well documented constructors, a custom behavior created
> by the user has no such re-usability restrictions.
>
> coupling
>
> I don’t think it is our choice - it is up to the skin
> designed. If they add a node that needs to take input, or
> if the behavior is drastically different, it is almost
> impossible to create a common interface. So skin and
> behaviors are coupled, besides we have to design for the
> worst case (of a totally different skin). The division
> between S and B comes mostly from the division between V
> and C in MVC. From a distance, the user does not see it
> at all - all they see is a control.
>
> JavaFX is not doing MVC.
>
> In MVC, the 3 components are not entangled; Model refers View,
> Controller refers View and Model, View refers nothing; in
> JavaFX the View (Skin) creates the Controller (Behavior); the
> View especially normally can be created without any
> dependencies, and can be tested as such; with Skins being
> tightly coupled to both Behaviors and Controls, that doesn't
> even come close.
>
> For it to be MVC you'd need to:
>
> - Remove reference from Skin to Control
> - Do not let Skins create Behaviors
> - Instantation order should be, create a Skin first (with no
> Control reference), then create the Control (with Skin as
> parameter or setter), then create a Behavior (with Control as
> parameter, and one or more Views (Skins))
>
> What JavaFX is exactly, I don't know. It doesn't follow MVC
> (even though it claims to) because in the current setup the
> Skin is both V and C; that's not MVC. At most it is MS (Model
> Skin), and so there is no reason to expose anything beyond the
> Skin then, as that would just be pretending to be something
> that it is not.
>
> This suggest another metric at judging the usefulness of a
> design - how easy it is to understand and perform 80% of
> most common tasks.
>
> Now that I explained how key remappings would work, I don't
> see how this would disqualify the alternative proposal.
>
>
>
> There are more interesting ideas at the end of the message
> I am replying to - fxml, css, global changes - these go
> far beyond the simple input map improvement. I did
> mention this already, but neither open source community,
> nor my employer might have the resources to make such
> drastic changes.
>
> I didn't mention FXML, but yes, I gave some other things to
> think about. As for how drastic any of those are, that
> remains to be seen. Certainly the global changes would not be
> that hard at all. The CSS proposal would need some research
> if there is some will to go there; it assumes that the
> information needed can be transported in a reasonable manner
> to the key binding system using the existing CSS infrastructure.
>
>
>
> So we have to be realistic, I think. We are travelling to
> a different planet in a small spaceship and we only have
> so much material and oxygen to play with. A simple
> improvement that helps 80% of use cases might be better
> than a major redesign (I still think the event proposal
> involves major redesign).
>
> I think that if that's the case that we'd better focus on
> making it possible for 3rd parties to deliver these features,
> and do the simplest thing that would allow them to do so. That
> would be prioritized event handlers (so a 3rd party can always
> intercept before the Skin/Behavior gets to it) + a flag to
> skip system event handlers (ala consumed) to allow bubbling up.
>
> On top of that any key remapping or behavior change system can
> be constructed already.
>
> --John
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20231101/ce7b0d04/attachment-0001.htm>
More information about the openjfx-dev
mailing list