<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>I've updated the proof of concept PR, and it has a number of
      changes to allow more reuse of the behaviors handlers and key
      bindings.  This has resulted in the Behavior installation process
      to become a bit more complex, but the actual use and the API's are
      still relatively simple.  For example, SpinnerBehavior's
      configuration method now looks like this:</p>
    <div style="background-color:#ffffff;padding:0px 0px 0px 2px;">
      <div style="color:#000000;background-color:#ffffff;font-family:"Consolas";font-size:11pt;white-space:pre;"><p style="margin:0;"><span style="color:#000000;">    </span><span style="color:#646464;">@Override</span></p><p style="margin:0;"><span style="color:#000000;">    </span><span style="color:#0000a0;font-weight:bold;">public</span><span style="color:#000000;"> StateFactory<Spinner<?>> configure(BehaviorInstaller<Spinner<?>> </span><span style="color:#6a3e3e;background-color:#f0d8a8;">installer</span><span style="color:#000000;">) {</span></p><p style="margin:0;"><span style="color:#000000;">        </span><span style="color:#6a3e3e;background-color:#d4d4d4;">installer</span><span style="color:#000000;">.setKeyHandler(</span><span style="background-color:#ffffff;padding:0px 0px 0px 2px;"><span style="color:#000000;background-color:#ffffff;font-family:"Consolas";font-size:11pt;white-space:pre;"><span style="color:#000000;"></span><span style="color:#0000c0;background-color:#d4d4d4;font-style:italic;font-weight:bold;">KEY_HANDLER</span></span></span><span style="color:#000000;">);</span></p><p style="margin:0;">
</p><p style="margin:0;"><span style="color:#000000;">        </span><span style="color:#6a3e3e;background-color:#d4d4d4;">installer</span><span style="color:#000000;">.registerEventHandler(MouseEvent.</span><span style="color:#0000c0;font-style:italic;font-weight:bold;">MOUSE_PRESSED</span><span style="color:#000000;">, State::mousePressed);</span></p><p style="margin:0;"><span style="color:#000000;">        </span><span style="color:#6a3e3e;background-color:#d4d4d4;">installer</span><span style="color:#000000;">.registerEventHandler(MouseEvent.</span><span style="color:#0000c0;font-style:italic;font-weight:bold;">MOUSE_RELEASED</span><span style="color:#000000;">, State::mouseReleased);</span></p><p style="margin:0;"><span style="color:#000000;">        </span><span style="color:#6a3e3e;background-color:#d4d4d4;">installer</span><span style="color:#000000;">.registerEventHandler(AccessibleActionEvent.</span><span style="color:#0000c0;font-style:italic;font-weight:bold;">TRIGGERED</span><span style="color:#000000;">, State::accessibleActionTriggered);</span></p><p style="margin:0;"><span style="color:#000000;">        </span><span style="color:#6a3e3e;background-color:#d4d4d4;">installer</span><span style="color:#000000;">.registerPropertyListener(Node::sceneProperty, State::sceneChanged);</span></p><p style="margin:0;">
</p><p style="margin:0;"><span style="color:#000000;">        </span><span style="color:#7f0055;font-weight:bold;">return</span><span style="color:#000000;"> State::</span><span style="color:#0000a0;font-weight:bold;">new</span><span style="color:#000000;">;</span></p><p style="margin:0;"><span style="color:#000000;">    }</span></p></div>
    </div>
    <p>Changes:<br>
      - Renamed BehaviorContext to BehaviorInstaller to better reflect
      its purpose<br>
      - Behaviors now configure the BehaviorInstaller, and provide a
      factory for their State<br>
         - This simplifies all the internal methods of Behaviors, no
      need for a Control parameter everywhere anymore; State has a
      Control reference!<br>
         - Because state and control are now provided at the same time,
      the handlers can all be static and reusable<br>
      - Controls create a BehaviorInstaller, ask a Behavior to configure
      it, then ask the installer to install the handlers on the control,
      resulting in a Subscription to undo all changes later<br>
         - This process, although a bit complex, ensures that Behaviors
      are strictly limited in what changes they can apply to the control<br>
         - The process also externalizes the Behavior's state, allowing
      its handlers, listeners and key bindings to be reused accross
      controls<br>
      - Introduce a KeyHandler class, and a non-public helper
      SimpleKeyBinder; these can be a precursor for an InputMap system<br>
         - KeyHandler is fully static (or can be) to allow key binding
      reuse<br>
         - Control can later be made responsible for handling InputMap
      style overrides<br>
    </p>
    <p>Note: earlier it was said that behaviors can be stateless, and
      this is certainly true for the main Behavior type (which can be
      "set" on as many controls as you'd like).  However, even Behaviors
      without "state" still need the Control reference as a piece of
      state in order to do anything at all.  So, no installed behaviors
      are actually stateless, there is always at a minimum a control
      reference.  To better reflect this, the State classes for the two
      proof of concept behaviors now are constructed with a Control (to
      keep all the related state together), allowing for easy access to
      the control for all its methods.</p>
    <p>The PR is here: <a class="moz-txt-link-freetext" href="https://github.com/openjdk/jfx/pull/1265">https://github.com/openjdk/jfx/pull/1265</a><br>
    </p>
    <p>--John<br>
    </p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 30/11/2023 23:28, John Hendrikx
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:2c5318b7-178e-b834-aa6a-2d63f56699da@gmail.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <p>Thanks for having a look!<br>
      </p>
      <div class="moz-cite-prefix">On 30/11/2023 19:47, Andy Goryachev
        wrote:<br>
      </div>
      <blockquote type="cite"
cite="mid:DM5PR1001MB2172E7CED4ED6FD04AE0AA5FE582A@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: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;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}span.EmailStyle19
        {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"">I think BehaviorContext looks suspiciously
              like a (skin) input map, so I would rather see that.  <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"">Invention of State class is a way to work
              around the stateless behavior which, though it adds (in my
              opinion) very little, might still be a feature that app
              developers want to exploit - at least in terms of saving
              on per-instance key maps.  So any alternative proposal
              should also support a stateless behavior.</span></p>
        </div>
      </blockquote>
      <p>I'm unsure what you are trying to say here.</p>
      <p>The State class is internal, and can be anything, and take any
        form.  If you only need to add a single EventHandler, you can
        also make that a class instead of a Lambda and have the state
        there. The State class, which can be named anything, is just a
        convenient way to share state amongst multiple handlers without
        having to construct each of them with special parameters, or
        having to put the state in the main class's fields (which would
        make it not reusable).<br>
      </p>
      <p>I do however see that I did not take reusability of the keymaps
        into account in this version, that will need to be adjusted -- I
        was more focused on keeping Behaviors isolated for now, not
        needing a Control until installed, and having 0 references
        between Skins and Behaviors.</p>
      <p>I was hoping for more comments on how the seperation between
        Skin and Behavior is done in this PR.  I will attempt to adjust
        TextInputControl soon (and I will try a few subclasses of
        ButtonBehavior, to see how they can be built "on top" of another
        behavior) -- so far I've not found any real problems with this
        approach.<br>
      </p>
      <p>--John<br>
      </p>
      <blockquote type="cite"
cite="mid:DM5PR1001MB2172E7CED4ED6FD04AE0AA5FE582A@DM5PR1001MB2172.namprd10.prod.outlook.com">
        <div class="WordSection1">
          <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><o:p></o:p></span></p>
        </div>
      </blockquote>
      <blockquote type="cite"
cite="mid:DM5PR1001MB2172E7CED4ED6FD04AE0AA5FE582A@DM5PR1001MB2172.namprd10.prod.outlook.com">
        <div class="WordSection1">
          <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">openjfx-dev <a
                      class="moz-txt-link-rfc2396E"
                      href="mailto:openjfx-dev-retn@openjdk.org"
                      moz-do-not-send="true"><openjfx-dev-retn@openjdk.org></a>
                    on behalf of John Hendrikx <a
                      class="moz-txt-link-rfc2396E"
                      href="mailto:john.hendrikx@gmail.com"
                      moz-do-not-send="true"><john.hendrikx@gmail.com></a><br>
                    <b>Date: </b>Wednesday, November 29, 2023 at 14:54<br>
                    <b>To: </b><a class="moz-txt-link-abbreviated
                      moz-txt-link-freetext"
                      href="mailto:openjfx-dev@openjdk.org"
                      moz-do-not-send="true">openjfx-dev@openjdk.org</a>
                    <a class="moz-txt-link-rfc2396E"
                      href="mailto:openjfx-dev@openjdk.org"
                      moz-do-not-send="true"><openjfx-dev@openjdk.org></a><br>
                    <b>Subject: </b>Behavior API proof of concept PR<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal" style="margin-bottom:12.0pt"><span
                    style="font-size:11.0pt">For those still interested,
                    I've updated <br>
                    <a href="https://github.com/openjdk/jfx/pull/1265"
                      moz-do-not-send="true"
                      class="moz-txt-link-freetext">https://github.com/openjdk/jfx/pull/1265</a>
                    with a replaced ButtonBehavior <br>
                    and SpinnerBehavior, using concepts laid out in <br>
                    <a
                      href="https://gist.github.com/hjohn/c7b1bf9d4a4770b1b3ae854b20fbaa94"
                      moz-do-not-send="true"
                      class="moz-txt-link-freetext">https://gist.github.com/hjohn/c7b1bf9d4a4770b1b3ae854b20fbaa94</a><br>
                    <br>
                    Any feedback is welcome, I think it's making
                    progress, and the changes <br>
                    required seem quite doable.<br>
                    <br>
                    The ability for Behaviors to intercept any event
                    from its Control or its <br>
                    (named) children makes Behaviors a lot more powerful
                    than earlier <br>
                    proposals, allowing for completely new interactions
                    without requiring <br>
                    Skin changes.<br>
                    <br>
                    --John<o:p></o:p></span></p>
              </div>
            </div>
          </div>
        </div>
      </blockquote>
    </blockquote>
  </body>
</html>