Public Behavior API proposal

Michael Strauß michaelstrau2 at gmail.com
Tue Nov 7 07:09:44 UTC 2023


Hi John,

I like that you clearly define the terms Control, Skin and Behavior,
as well as their roles within the control architecture.

However, I don't see how your proposal scales to non-trivial controls,
and I agree with Andy that the Button example doesn't help (because a
Button lacks substructure and provides only a single interaction).

I'm missing your previous idea of using the event system for
higher-level semantic events, because I think they're required to make
this work. Here's how I see these parts working together:

1) A control is an opaque node in the scene graph, which defines the
API for a particular interactive element. It also defines the
interactions afforded by its implementation. For example, a Spinner
will usually consist of a text field and two buttons, but a skin might
choose to implement these components differently. The interactions
afforded by a control are exposed as semantic events:

    class SpinnerEvent extends Event {
        static EventType<SpinnerEvent> COMMIT_TEXT;
        static EventType<SpinnerEvent> START_INCREMENT;
        static EventType<SpinnerEvent> STOP_INCREMENT;
        static EventType<SpinnerEvent> START_DECREMENT;
        static EventType<SpinnerEvent> STOP_DECREMENT;
    }

2) Skins are responsible for generating semantic events, and sending
those events to the control. Since we don't need those events to have
a tunneling/bubbling behavior, we could have a flag on the event that
indicates a "direct event", one that is dispatched directly to its
target.

3) Behaviors listen for semantic events on the control, and convert
these events into state changes of the control. This part would
probably be quite similar to some of the things that have already been
proposed.

In this way, controls, skins, and behaviors would end up as loosely
coupled parts. In particular, I don't see the value in making
behaviors public API if they are so tightly coupled to skins that they
end up as being basically implementation details.

Andy:
> Imagine a specific skin that has a Node that accepts a user input.  A scroll bar, a button, or a region with a some function.  Unless this element is proclaimed as must-have for any skin and codified via some new public API (MySkin.getSomeElement()), it is specific to that particular skin and that particular behavior.

I think that's a very important observation. A skin can't just be
anything it wants to be, it must be suitable for its control. So we
need a place where we define the API and the interactions afforded by
that control. In my opinion, this place is the Control. Its
functionality is exposed via properties and methods, and its
interactions are specified using semantic events.

Now skins are free to be implemented in any imaginable way, provided
that they interact with the control using semantic events. This gives
us very straightforward restrictions:
* A skin can never add interactions that the control didn't specify.
* If additional interactions are required, the control must be
subclassed and the interactions must be specified by the control.
Additionally, the behavior must be extended to account for the
additional interactions.




On Mon, Nov 6, 2023 at 4:50 AM John Hendrikx <john.hendrikx at gmail.com> wrote:
>
> As promised,  a public Behavior API proposal.
>
> Summary:
>
> Introduce a new Behavior interface that can be set on a control to replace its current behavior. The new behavior can be fully custom or composed (or later subclassed) from a default behavior. Some default behaviors will be provided as part of this proposal, but not all.
>
> See here: https://gist.github.com/hjohn/293f3b0ec98562547d49832a2ce56fe7
>
> --John


More information about the openjfx-dev mailing list