Michael:

Thank you for a very thoughtful analysis!  These are very good questions; allow 
me to clarify.

1. It seems that the behavior implementation is still hard-coded into
the skin implementation. For example, TextFieldSkin uses
TextFieldBehavior; it doesn't seem like I can have a TextFieldSkin
that uses my custom behavior. Do you plan on changing that?

There are many facets to this question.  Yes, in my opinion, we should make all 
the behaviors public similarly to Swing, though it does represent a substantial 
amount of work.  I’d say it is still a possibility, albeit a distant one.

The next best thing is this proposal, which makes it possible to redefine the 
behavior by re-registering some if not all of the functions declared by the 
control.  Another possibility would be to create a new skin with a custom 
behavior (though it might be a bit too much for an app developer).

One good thing about this proposal is that it should offer immediate benefits 
to the application developers in many cases by giving the ability to redefine a 
small subset of control’s functionality without the need to go deep into 
implementation (and without making the behavior public).

2. The InputMap can have a lot of mappings that are set on each
individual control. However, in almost all cases, the input mappings
are semantically equivalent for all instances of a control. Wouldn't
it make sense to associate input mappings with the control class,
instead of the control instance? Aside from more closely conveying the
semantics of a "default mapping", this should also cut down on the
number of object instances we need to keep around. Of course, it
should still be possible to override a default mapping with a
per-instance mapping.

This is an interesting idea, we might explore it further – there is nothing in 
the proposed APIs that preclude us from doing this optimization, even though 
the actual savings in terms of memory may not be that noticeable: unlike Node, 
a typical number of Controls in the scene graphs is not that great.  But still, 
worth exploring.  Thank you!

3. Why are FunctionTags defined on the control class, yet they don't
seem to match the functionality offered by the control class? For
example, there's TextInputControl.DELETE_NEXT_WORD, but there's no
corresponding functionality in TextInputControl. The functionality is
actually implemented in TextInputControlBehavior. But if the
implementation is only available in this particular behavior, why is
the FunctionTag defined on the control class?

The function tags belong to the control class so that the user can redefine 
them.

And thank you for pointing out the situation with DELETE_NEXT_WORD.  You are 
right - the actual control class should declare a public method for each tag, 
so the functionality is available programmatically at the control level.  It’s 
not currently done in this PR in order to minimize the amount of changes, and I 
expect we’ll do it in a separate enhancement.

4. I'm missing a clear delineation between controls and their
behaviors. For example, there's TextInputControl.selectNextWord(), but
no TextInputControl.deleteNextWord(). The latter is implemented in
TextInputControlBehavior. Why is selectNextWord() implemented in the
control, but deleteNextWord() in the behavior? This is just one
example of lots of peculiarities.

I tried to address this in the proposal, perhaps I did not emphasized it 
strongly enough.  As with your previous comment, a concrete control class 
should declare a public method for each function tag, which simply executes 
that function tag.  In essence, there should be 1:1:1 correspondence between 
function tags, public method in the control class, and a public method in the 
corresponding behavior.  The latter is not available directly because right now 
the actual behavior is not public, but it is available programmatically via 
getDefaultFunction().

I’d expect there will be subsequent enhancements to add these methods to each 
control, once we all agree with the proposed design and finalize the APIs.

5. More generally, we should start by clearly defining concepts. Up
until now, behaviors were just an implementation detail, so this
wasn't necessary. But what is a behavior? What is the relationship
between a control, its skin and behavior? How would a control author
decide what needs to be put into the control class, and what needs to
be put into the behavior class (cf. selectNextWord/deleteNextWord)?

Good point.  Perhaps the best place to explain this is in FunctionTag Javadoc?

Any function that the skin, or the application developer, or the end user might 
want to redefine, or set a key binding for, or unbind – should have a 
corresponding function tag.  I’d expect there should be a public method in the 
control that executes the tag, but it is not a strict requirement.

The relationship between the skin and control is a more subtle one.  For 
example, selectNextWord may not need a skin (it can operate directly on the 
data model, using a BreakIterator), but TextArea.LINE_END needs the skin to 
determine where the text layout wrapped the line.  A null skin is also 
technically possible (though it makes no sense).  My point is that, given this 
dependency on the skin, the behavior is typically instantiated by the skin, but 
it does not have to be.  Nothing prevents us from initializing the behavior in 
the control, and designing this behavior to get the skin when needed.  However, 
this design might have a price of adding some public APIs to the concrete skins.

This proposal does not require making behaviors public, does not mandate 
additional public APIs in skins, so we are free to change it later if deemed 
necessary.

Hope this discussion spurs more discussion.  My goal is to make FX more 
extensible and easier to use, and your feedback and comments are very important.

Thank you!

-andy





From: Michael Strauß <michaelstr...@gmail.com>
Date: Friday, October 6, 2023 at 07:13
To: Andy Goryachev <andy.goryac...@oracle.com>
Cc: openjfx-dev@openjdk.org <openjfx-dev@openjdk.org>
Subject: [External] : Re: [Request for Comments] Behavior / InputMap
Hi Andy,

I think the opaqueness of JavaFX controls is one of the greatest
shortcomings of the framework, so I welcome an enhancement.

Some thoughts:

1. It seems that the behavior implementation is still hard-coded into
the skin implementation. For example, TextFieldSkin uses
TextFieldBehavior; it doesn't seem like I can have a TextFieldSkin
that uses my custom behavior. Do you plan on changing that?

2. The InputMap can have a lot of mappings that are set on each
individual control. However, in almost all cases, the input mappings
are semantically equivalent for all instances of a control. Wouldn't
it make sense to associate input mappings with the control class,
instead of the control instance? Aside from more closely conveying the
semantics of a "default mapping", this should also cut down on the
number of object instances we need to keep around. Of course, it
should still be possible to override a default mapping with a
per-instance mapping.

3. Why are FunctionTags defined on the control class, yet they don't
seem to match the functionality offered by the control class? For
example, there's TextInputControl.DELETE_NEXT_WORD, but there's no
corresponding functionality in TextInputControl. The functionality is
actually implemented in TextInputControlBehavior. But if the
implementation is only available in this particular behavior, why is
the FunctionTag defined on the control class?

4. I'm missing a clear delineation between controls and their
behaviors. For example, there's TextInputControl.selectNextWord(), but
no TextInputControl.deleteNextWord(). The latter is implemented in
TextInputControlBehavior. Why is selectNextWord() implemented in the
control, but deleteNextWord() in the behavior? This is just one
example of lots of peculiarities.

5. More generally, we should start by clearly defining concepts. Up
until now, behaviors were just an implementation detail, so this
wasn't necessary. But what is a behavior? What is the relationship
between a control, its skin and behavior? How would a control author
decide what needs to be put into the control class, and what needs to
be put into the behavior class (cf. selectNextWord/deleteNextWord)?



On Sat, Sep 30, 2023 at 1:18 AM Andy Goryachev
<andy.goryac...@oracle.com> 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://urldefense.com/v3/__https://gist.github.com/andy-goryachev-oracle/294d8e4b3094fe16f8d55f6dd8b21c09__;!!ACWV5N9M2RV99hQ!LvBDJOf2E21l1kuyLzVGMuLC-fz3U_lgl_5RBWp9nwRKm2IsRgmKcm7bMHRKSh7bmVIfkHiUAE5F1E7tZIeGKujFuEb7$<https://urldefense.com/v3/__https:/gist.github.com/andy-goryachev-oracle/294d8e4b3094fe16f8d55f6dd8b21c09__;!!ACWV5N9M2RV99hQ!LvBDJOf2E21l1kuyLzVGMuLC-fz3U_lgl_5RBWp9nwRKm2IsRgmKcm7bMHRKSh7bmVIfkHiUAE5F1E7tZIeGKujFuEb7$>
>
>
>
> We are very much interested in your feedback.  Thank you in advance.
>
>
>
> -andy
>
>

Reply via email to