<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>The normal procedure I think is also to first provide a JEP for
      review, before starting on the implementation...</p>
    <p>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.<br>
    </p>
    <p>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.</p>
    <p>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.</p>
    <p>I'll reiterate my problems with your proposal:</p>
    <p>- Introduces a lot of API for what is essentially the
      configuration of internal event handlers<br>
      - 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<br>
      - 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<br>
      - Introduces the term "InputMap" in public API, which is just an
      implementation detail of the internal event handlers<br>
      - 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...</p>
    <p>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.<br>
    </p>
    <p></p>
    <p>My proposals in short:</p>
    <p>1.<br>
    </p>
    <p>- Fix the issues with Events being stolen before users can get a
      them<br>
          - Users should be able to have priority on Events, Michael
      Strauss already has a PR that fixes the issue in part<br>
          - Events should not be consumed when not used (navigation does
      this) as this precludes the user being able to change their
      meaning<br>
          - Even better would be if internal event handlers were
      isolated and did not mix themselves with user event handlers at
      all<br>
    </p>
    <p>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.</p>
    <p>- 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<br>
      <br>
      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. <br>
    </p>
    <p>2.</p>
    <p>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:</p>
    <p>- Introduce a Behavior interface with a single method "install"
      to be called by a Control<br>
      - 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.<br>
      - 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<br>
      - 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).<br>
      - 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.<br>
      - 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)<br>
    </p>
    <p>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).</p>
    <p>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.</p>
    <p>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).</p>
    <p>Thanks for reading.</p>
    <p>--John</p>
    <p><br>
    </p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 26/10/2023 00:59, Andy Goryachev
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:DM5PR1001MB2172AFC40B50A88979E1AAC5E5DEA@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
        {font-family:"Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
        {font-family:"Iosevka Fixed SS16";
        panose-1:2 0 5 9 3 0 0 0 0 4;}@font-face
        {font-family:"Times New Roman \(Body CS\)";
        panose-1:2 11 6 4 2 2 2 2 2 4;}@font-face
        {font-family:"\@Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}@font-face
        {font-family:"Iosevka Fixed SS16 ";
        panose-1:2 0 5 9 3 0 0 0 0 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}span.EmailStyle20
        {mso-style-type:personal-reply;
        font-family:"Iosevka Fixed SS16";
        color:windowtext;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}div.WordSection1
        {page:WordSection1;}</style>
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Dear John:<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">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:<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">1. Provide an overview of the proposal following
            a JEP outline:<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><b><span
              style="font-size:11.0pt;font-family:"Iosevka Fixed
              SS16"">Summary</span></b><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><b><span
              style="font-size:11.0pt;font-family:"Iosevka Fixed
              SS16"">Goals</span></b><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><b><span
              style="font-size:11.0pt;font-family:"Iosevka Fixed
              SS16"">Non-Goals</span></b><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><b><span
              style="font-size:11.0pt;font-family:"Iosevka Fixed
              SS16"">Motivation</span></b><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><b><span
              style="font-size:11.0pt;font-family:"Iosevka Fixed
              SS16"">Description</span></b><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><b><span
              style="font-size:11.0pt;font-family:"Iosevka Fixed
              SS16"">Alternatives</span></b><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><b><span
              style="font-size:11.0pt;font-family:"Iosevka Fixed
              SS16"">Risks and Assumptions</span></b><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><b><span
              style="font-size:11.0pt;font-family:"Iosevka Fixed
              SS16"">Dependencies</span></b><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">2. A draft PR that provides a proof of concept,
            using, in this case, a few complex controls like TextArea,
            TableView, ComboBox.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">3. Address the question raised earlier, perhaps
            by providing code examples (pseudo code is acceptable, I
            think).<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">More specifically, I’d like to know how the
            following concerns will be addressed by the new proposal:<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q1. Changing an existing key binding from one
            key combination to another.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q2. Remapping an existing key binding to a
            different function.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q3. Unmapping an existing key binding.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q4. Adding a new key binding mapped to a new
            function.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q5. (Q1...Q4) scenarios, at run time.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">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.
            <o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q7. Once the key binding has been modified, is
            it possible to invoke the default functionality?<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q8. How are the platform-specific key bindings
            created?<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q9. How are the skin-specific (see Q6) handlers
            removed when changing the skins?<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Q10. When a key press happens, does it cause a
            linear search or a map lookup?
            <o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Thank you<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">-andy<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <div id="mail-editor-reference-message-container">
          <div>
            <div style="border:none;border-top:solid #B5C4DF
              1.0pt;padding:3.0pt 0in 0in 0in">
              <p class="MsoNormal" style="margin-bottom:12.0pt"><b><span
                    style="font-size:12.0pt;color:black">From:
                  </span></b><span style="font-size:12.0pt;color:black">John
                  Hendrikx <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
                  <b>Date: </b>Tuesday, October 24, 2023 at 04:58<br>
                  <b>To: </b>Andy Goryachev
                  <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a>,
                  <a class="moz-txt-link-abbreviated" href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a>
                  <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
                  <b>Subject: </b>Re: [External] : Re: Proof of concept
                  pull request for Behavior API (PR 1265)<o:p></o:p></span></p>
            </div>
            <p><o:p> </o:p></p>
            <div>
              <p class="MsoNormal"><span style="font-size:11.0pt">On
                  23/10/2023 23:57, Andy Goryachev wrote:<o:p></o:p></span></p>
            </div>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><span
                  style="font-size:11.0pt">
                  <o:p></o:p></span></p>
              <p class="MsoNormal" style="margin-left:.5in">You'd create
                a new class, `MyBehavior`,<o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">By “customizing” I also mean at run
                  time.  Creating new classes wouldn’t work. 
                </span><o:p></o:p></p>
            </blockquote>
            <p>This would also work at runtime, as the class you create
              can <span style="background:yellow;mso-highlight:yellow">
                be instantiated with parameters that control its key
                binding behavior</span>.  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.<o:p></o:p></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal" style="margin-left:.5in"><span
                  style="background:yellow;mso-highlight:yellow">coupling</span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">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.</span><o:p></o:p></p>
            </blockquote>
            <p>JavaFX is not doing MVC.<o:p></o:p></p>
            <p class="MsoNormal"><span style="font-size:11.0pt">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.<o:p></o:p></span></p>
            <p>For it to be MVC you'd need to:<o:p></o:p></p>
            <p>- Remove reference from Skin to Control<br>
              - Do not let Skins create Behaviors<br>
              - 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))<o:p></o:p></p>
            <p>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.<o:p></o:p></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">This suggest another metric at
                  judging the usefulness of a design - how easy it is to
                  understand and perform 80% of most common tasks.</span><o:p></o:p></p>
            </blockquote>
            <p class="MsoNormal"><span style="font-size:11.0pt">Now that
                I explained how key remappings would work, I don't see
                how this would disqualify the alternative proposal.<br>
                <br>
                <o:p></o:p></span></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">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.</span><o:p></o:p></p>
            </blockquote>
            <p class="MsoNormal"><span style="font-size:11.0pt">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.<br>
                <br>
                <o:p></o:p></span></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">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).</span><o:p></o:p></p>
            </blockquote>
            <p>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.<o:p></o:p></p>
            <p>On top of that any key remapping or behavior change
              system can be constructed already.<o:p></o:p></p>
            <p>--John<o:p></o:p></p>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>