Andy,

I should have been clearer on why I wrote this up. I think once you’ve 
identified the minimum API surface that’s probably all you should implement.

More important to me is whether reducing the API to a bunch of function tags 
and two API calls does everything that needs to be done. For example, that 
reduction means you can’t enumerate the list of function tags a control 
supports or the full set of key bindings. Is that an issue? Is there a use case 
for these enumerations?

> 3) Provide an API that asks a control to map an Event to a FunctionTag. This 
> enables blocking existing mappings; if a user wants to block the default 
> mappings for, say, COPY they can simply discard/consume any events that the 
> control would map to COPY.
>  
> Supported via InputMap.registerFunction(FunctionTag, Runnable).  Just do 
> registerFunction(COPY, () -> { }). 

Sorry I didn’t make myself clear. Say I want Ctrl-J to be Copy instead of 
whatever it’s default binding is. The flow would be:

        if the event is Ctrl-J
                ask the control to perform the COPY operation
        else if the control maps this event to COPY
                discard the event (it’s the default binding)
 
> They are not.  There is no SELECT_ALL in Button control, for example.  Where 
> the hierarchy exists, so does the hierarchy of tags, for example 
> TextInputControl.SELECT_ALL which is applicable/used in TextField and 
> TextArea.  But we can’t extend it to TableView, for example, as there is no 
> common ancestor - unless we invent one (an interface).

Any control will need to ensure that it ignore tags it doesn’t understand. Who 
cares if Ctrl-A maps to SELECT_ALL for a button? It will just ignore it.

But I do get your point. If we ask a Control to map an event to an operation we 
should ensure that the control actually supports that operation. So we don’t 
need multiple SELECT_ALL tags, just a verification step so we don’t return 
bogus tags.

>  
> What do you think?
>  
> Thank you
> -andy
>  
>  
>  
> From: Martin Fox <mar...@martinfox.com>
> Date: Monday, October 30, 2023 at 17:24
> To: Andy Goryachev <andy.goryac...@oracle.com>
> Cc: Kevin Rushforth <kevin.rushfo...@oracle.com>, openjfx-dev 
> <openjfx-dev@openjdk.org>
> Subject: [External] : Re: [Request for Comments] Behavior / InputMap
> 
> I was looking over the InputMap proposal with an eye toward paring it down to 
> the bare minimum.
>  
> From the perspective of a user who wants to manipulate a control without 
> subclassing it I think there are only a few essential components.
>  
> 1) Ensure the user gets events before the control does. That’s a topic for a 
> different thread.
>  
> 2) Provide an API that asks a control to perform the operation identified by 
> a FunctionTag. This is the only way to access operations like COPY and 
> MOVE_RIGHT that are implemented behind the scenes.
>  
> 3) Provide an API that asks a control to map an Event to a FunctionTag. This 
> enables blocking existing mappings; if a user wants to block the default 
> mappings for, say, COPY they can simply discard/consume any events that the 
> control would map to COPY.
>  
> If a user wants to subclass an existing control they could also use these 
> API’s to do full customization but only if they can guarantee that their 
> subclass will process events before the superclass. That, too, might be a 
> separate discussion.
>  
> I would like to discuss these API’s without getting too deep into 
> implementation details. With that said, I do have one implementation 
> suggestion: since most of the event => FunctionTag mappings are common 
> (SELECT_ALL is always Shortcut+A) there should be an internal shared object 
> containing the common mappings.
>  
> Martin
> 
> 
> On Oct 30, 2023, at 3:11 PM, Andy Goryachev <andy.goryac...@oracle.com> wrote:
>  
> Dear Kevin:
>  
> Thank you for providing a summary to our (lively) discussion.  Even though I 
> think I answered these concerns, I don’t mind to have another go at it.
>  
> Please find the updated proposal here (same link):
>  
> https://gist.github.com/andy-goryachev-oracle/294d8e4b3094fe16f8d55f6dd8b21c09
>  
> <https://urldefense.com/v3/__https:/gist.github.com/andy-goryachev-oracle/294d8e4b3094fe16f8d55f6dd8b21c09__;!!ACWV5N9M2RV99hQ!MAhFywXruyvFlvk6whGVWBb9fTI-f1D-16YuJbRGdJe52rX503CFBK8S6IamyzPVzQBcJZmg6c_Jh1CfsDxVFw$>
>  
> Let me first define what I mean by “behavior” in the context of this 
> proposal.  A behavior is a translation layer between input events - coming 
> either from the control, or from some nodes contained in the skin, or from 
> the platform itself - into some actions.  These translation mappings are 
> maintained by a new property in Control - the InputMap.  The InputMap has two 
> sides - one for the user application, and another - for the skins/behaviors.  
> Both are “public APIs” but the latter is represented as protected methods of 
> BehaviorBase class which forms a foundation of the behavior part of the skins 
> that want to use the InputMap paradigm.
>  
> Back to individual concerns.
>  
> * We should not make anything related to Behaviors public without a full 
> design of how Behaviors should work, what their responsibilities are, how 
> they interact with Skins
> 
> 
> And we don’t.  We recommend to use BehaviorBase, but it’s still possible to 
> use event handlers or any other home-grown mechanism to implement 
> skins/behaviors and suffer from the lack of functionality as a result.  If 
> BehaviorBase is not the right name, we can call it InputMapAccessorForSkinUse 
> any other name.
>  
> * This proposal doesn't solve the coupling of Skins and behaviors
>  
> The skins and behaviors are tightly coupled in some cases.  It is possible 
> that a simple control such as Button does not require tight coupling, but a 
> complex control such as TextArea does (see TextAreaSkin:1214).
>  
> With the InputMap, we now can separate user mappings from skin mappings and 
> handlers.  Changing a skin will unregister all of the handlers added by the 
> associated behavior, leaving the user mappings intact.
>  
> * Function tags are defined in control class, but don't match the 
> functionality of control class
> NOTE: this begs the question of whether there should always be a method on 
> control for each such function (even if the implementation just delegates to 
> the behavior
> 
> 
> May be it was not described extensively, but it is being suggested to have 
> one public method for each function tag, which does invoke the said tag.  
> This enabled indirection via InputMap which in turn allows the app- or skin- 
> developer to redefine the functionality (in effect, allowing for changing the 
> behavior without subclassing the behavior).
>  
> So, for example, SomeControl.copy() would invoke execute(TAG_COPY), which by 
> default would invoke SomeControlBehavior.copy().
>  
> This proposal did not make this change for the subset of controls - 
> intentionally - because it can be done later in a separate PR.
>  
> * An input map should not refer to the node and be stateless and sharable 
> among all (or some) instances of the same class; this would mean mapping 
> input events to Control::method rather than to instance::method or to some 
> arbitrary lambda
> NOTE: this would depend on the previous being resolved
>  
> I think we are confusing two things.  The InputMap allows for per-control 
> mapping, so it cannot be shareable or static.  Period.
>  
> Now, the other thing is a possible requirement to allow for changing the 
> mapping on per-control-type basis, to overwrite the behavior for each 
> instance of a particular control.  This I did not address because it’s an 
> implementation detail for that control type.  I did not want to add child 
> maps, but perhaps we could add another API to the skin/behavior side of 
> InputMap to allow for such a static map.
>  
> Personally, I don’t like the idea as it basically adds nothing: event 
> handlers still need to be added to each control and each Node in the skin (if 
> any) and there is an extra complexity added.  A better solution would be to 
> subclass the control class and add the mappings for each instance just like 
> we do today.
>  
> * Arbitrary key mapping seems out of scope for the core of JavaFX; this sort 
> of mapping could be done by the application if the event order problem was 
> solved, and if we had public API on control for all functions that are called 
> by the behavior.
>  
> Arbitrary (user) key bindings are enabled by the proposed InputMap.  Any 
> alternative proposal, in my opinion, should support this function out of the 
> box.
>  
> * Should Input map be immutable?
>  
> The value of InputMap is ability to change the mapping, so I don’t understand 
> where this requirement is coming from.  Perhaps an example or a use case 
> could be provided?
>  
> * Changes to the Behavior system should focus on replacing complete 
> behaviors, and being able to use these by default for a certain subset of 
> controls (like -fx-skin provide in CSS)
> 
> 
> As I mentioned earlier, the skin and its behavior might be tightly coupled.  
> So if a use case exists for changing the behavior, we already have a solution 
> - a custom skin.  May be a use case or an example of why we can’t do that 
> with the existing architecture would help here.
>  
> And finally, I would like to emphasize that even though the InputMap proposal 
> is fairly well developed and validated using a number of non-trivial controls 
> and some new controls (RichTextArea 
> https://github.com/andy-goryachev-oracle/jfx/pull/1 
> <https://urldefense.com/v3/__https:/github.com/andy-goryachev-oracle/jfx/pull/1__;!!ACWV5N9M2RV99hQ!MAhFywXruyvFlvk6whGVWBb9fTI-f1D-16YuJbRGdJe52rX503CFBK8S6IamyzPVzQBcJZmg6c_Jh1ACM9EGvA$>
>  ), I am not against modifying/enhancing it based on the community feedback.  
> I hope we can get to a good solution in a reasonable time frame, or we all 
> would have to learn react and program in javascript.
>  
> Cheers,
> -andy
>  
>  
>  
>  
>  
> From: openjfx-dev <openjfx-dev-r...@openjdk.org> on behalf of Kevin Rushforth 
> <kevin.rushfo...@oracle.com>
> Date: Friday, October 27, 2023 at 16:34
> To: openjfx-dev <openjfx-dev@openjdk.org>
> Subject: Re: [Request for Comments] Behavior / InputMap
> 
> I've mostly caught up on the (lively) discussion surrounding this feature 
> request.
> 
> It is clear that we do not yet have general agreement on the direction this 
> proposal should take, so let's continue to discuss the proposal, its 
> shortcomings, and any alternative approaches.
> 
> We should start by making sure that the motivation for doing this -- what 
> problem is being solved -- is well understood. Andy will rework the initial 
> sections of the proposal to make it more clear.
> 
> If I can summarize what I see are the main concerns that have been raised:
> 
> * We should not make anything related to Behaviors public without a full 
> design of how Behaviors should work, what their responsibilities are, how 
> they interact with Skins
> 
> * This proposal doesn't solve the coupling of Skins and behaviors
> 
> * Function tags are defined in control class, but don't match the 
> functionality of control class
> NOTE: this begs the question of whether there should always be a method on 
> control for each such function (even if the implementation just delegates to 
> the behavior
> 
> * An input map should not refer to the node and be stateless and sharable 
> among all (or some) instances of the same class; this would mean mapping 
> input events to Control::method rather than to instance::method or to some 
> arbitrary lambda
> NOTE: this would depend on the previous being resolved
> 
> * Arbitrary key mapping seems out of scope for the core of JavaFX; this sort 
> of mapping could be done by the application if the event order problem was 
> solved, and if we had public API on control for all functions that are called 
> by the behavior.
> 
> * Should Input map be immutable?
> 
> * Changes to the Behavior system should focus on replacing complete 
> behaviors, and being able to use these by default for a certain subset of 
> controls (like -fx-skin provide in CSS)
> 
> There are probably other concerns as well.
> 
> Finally, one of the comments made, which I completely agree with, is that API 
> design needs to come first. It needs to be fully fleshed out, and needs to be 
> forward-looking. We should only expose as public API what is needed to solve 
> the problem and no more.
> 
> Let's continue the discussion with this in mind.
> 
> -- Kevin
> 
> 
> 
> On 9/29/2023 3:44 PM, Andy Goryachev wrote:
> Dear fellow JavaFX developers:
>  
> For some time now, we’ve been working to identify missing features in JavaFX 
> that hinder application development.  We’ve been working on adding some of 
> the missing features (for which we’ll have a separate announcement), but I 
> feel that engaging wider community is a rather important part of the process.
>  
> I would like to share with you one such missing feature - ability to extend 
> behavior of the existing components (and make the task of creating new 
> components easier) by adding a public InputMap and BehaviorBase.  
>  
> Please find the actual proposal here
> https://gist.github.com/andy-goryachev-oracle/294d8e4b3094fe16f8d55f6dd8b21c09
>  
> <https://urldefense.com/v3/__https:/gist.github.com/andy-goryachev-oracle/294d8e4b3094fe16f8d55f6dd8b21c09__;!!ACWV5N9M2RV99hQ!MAhFywXruyvFlvk6whGVWBb9fTI-f1D-16YuJbRGdJe52rX503CFBK8S6IamyzPVzQBcJZmg6c_Jh1CfsDxVFw$>
>  
> We are very much interested in your feedback.  Thank you in advance.
>  
> -andy

Reply via email to