<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    Hi Andy,<br>
    <br>
    I think this updated proposal is a good one. It provides the minimum
    API to allow applications to do what they cannot do today, without
    locking us into the API needed to directly support traversal
    policies or defining new traversal events. Those could be added in a
    future release, if there is sufficient demand once this is done.<br>
    <br>
    Minor typos:<br>
    <br>
    In the list of goals:<br>
    <br>
    > to introduc a public API for a focus traversal policy<br>
    <br>
    "introduce"<br>
    <br>
    In your example:<br>
    <br>
    >                 from.traverse(from, TraversalDirection.NEXT);<br>
    <br>
    remove the "from" argument.<br>
    <br>
    -- Kevin<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 10/22/2024 3:25 PM, Andy Goryachev
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:DS0PR10MB62008793BA084CDD074CD4EDE54C2@DS0PR10MB6200.namprd10.prod.outlook.com">
      
      <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:Aptos;
        panose-1:2 11 0 4 2 2 2 2 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;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Aptos",sans-serif;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}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"">Updated
            the API and the JEP per feedback comments:<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""><a href="https://github.com/andy-goryachev-oracle/Test/blob/main/doc/FocusTraversal/FocusTraversal-v3.md" moz-do-not-send="true" class="moz-txt-link-freetext">https://github.com/andy-goryachev-oracle/Test/blob/main/doc/FocusTraversal/FocusTraversal-v3.md</a><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""><a href="https://github.com/openjdk/jfx/pull/1604" moz-do-not-send="true" class="moz-txt-link-freetext">https://github.com/openjdk/jfx/pull/1604</a><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"">Thanks,<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>
        <div id="mail-editor-reference-message-container">
          <div>
            <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">Andy Goryachev
                    <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a><br>
                    <b>Date: </b>Tuesday, October 22, 2024 at 12:22<br>
                    <b>To: </b>John Hendrikx
                    <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.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: Proposal: Focus Traversal API<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Thank
                    you.</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
                    completely disagree with the idea of adding a single
                    method to Node and introducing 6 way enum, for the
                    reasons provided earlier.</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"">Having
                    said that, I am more interested in moving forward. 
                    If everyone feels more comfortable with Node + enum
                    combo, I'll make the change.</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"">Thank
                    you for a lively discussion.</span><o:p></o:p></p>
                <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</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""> </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>
                <div id="mail-editor-reference-message-container">
                  <div>
                    <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"><openjfx-dev-retn@openjdk.org></a> on
                            behalf of John Hendrikx
                            <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
                            <b>Date: </b>Monday, October 21, 2024 at
                            23:46<br>
                            <b>To: </b><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: Proposal: Focus
                            Traversal API</span><o:p></o:p></p>
                      </div>
                      <div>
                        <p class="MsoNormal"><span style="font-size:11.0pt">I already like this
                            suggestion very much, as it is simple,
                            concise and
                            <br>
                            located exactly where you'd expect it (near
                            `requestFocus`).  It offers <br>
                            the navigation options that FX offers in a
                            programmatic way and doesn't <br>
                            need to cater to other methods, only what FX
                            offers.<br>
                            <br>
                            I also have an alternative approach that
                            could be considered.  The user <br>
                            model would be something like this:<br>
                            <br>
LogicalNavigation.NEXT.find(currentNode).ifPresent(Node::requestFocus);<br>
                            <br>
                            This is more wieldy, but does offer a
                            natural API that allows extension <br>
                            as `LogicalNavigation.NEXT` is an
                            implementation of an interface <br>
                            (provisional name Navigator):<br>
                            <br>
                                   interface Navigator {<br>
                                         Optional<Node> find(Node
                            node);  // finds a next node given <br>
                            a starting point<br>
                                   }<br>
                            <br>
                            Then implementations of these can be made
                            available as constants or <br>
                            enums, for example:<br>
                            <br>
                                   enum LogicalNavigation implements
                            Navigator {<br>
                                        
                            NEXT(InternalImplementation::next),<br>
                                         PREVIOUS( ... );<br>
                            <br>
                                         ...<br>
                                   }<br>
                            <br>
                            The above API offers a natural way to only
                            "predict" the focus, and only <br>
                            act on it if you want.<br>
                            <br>
                            --John<br>
                            <br>
                            On 21/10/2024 19:13, Michael Strauß wrote:<br>
                            > I think it is a good idea to do the
                            non-controversial part of this<br>
                            > feature first.<br>
                            ><br>
                            > With regards to the API, I would prefer
                            a single instance method on Node:<br>
                            ><br>
                            >      Node
                            moveFocus(FocusTraversalKind);<br>
                            ><br>
                            > Where FocusTraversalKind is an enum
                            with values UP, DOWN, LEFT, RIGHT,<br>
                            > NEXT, and PREVIOUS.<br>
                            > Note that it is not called
                            "TraversalDirection", because NEXT and<br>
                            > PREVIOUS are logical types of
                            navigation, not directional ones.<br>
                            > The return value is the node that will
                            receive focus as a result of<br>
                            > this method call.<br>
                            ><br>
                            > The name "moveFocus" pairs with
                            "requestFocus" (and we could also<br>
                            > potentially add "predictFocus" to get
                            the node that would receive<br>
                            > focus, without actully changing focus).<br>
                            ><br>
                            > Having a single instance method allows
                            for easier composition, as I<br>
                            > can now pass the FocusTraversalKind to
                            methods, which is a bit awkward<br>
                            > to do with method references.<br>
                            ><br>
                            > For example, I could write a method:<br>
                            ><br>
                            >      /*<br>
                            >       * Moves the focus if allowed.<br>
                            >       * Returns true if the focus
                            changed, false otherwise<br>
                            >       */<br>
                            >      boolean
                            moveFocusIfAllowedByBusinessLogic(Node node,<br>
                            > FocusTraversalKind kind) {<br>
                            >          return switch (kind) {<br>
                            >              case UP, DOWN -> false;<br>
                            >              default -> isAllowed()
                            && node.moveFocus(kind) != node;<br>
                            >          };<br>
                            >      }<br>
                            ><br>
                            > If I would instead pass a method
                            reference to<br>
                            > FocusTraversal::traverseNext into my
                            custom method, I'm very limited<br>
                            > in what I can do with it.<br>
                            > For example, I can't switch() on the
                            method reference, I can't change<br>
                            > it with custom logic, etc.<br>
                            ><br>
                            ><br>
                            > On Fri, Oct 18, 2024 at 10:25</span><span style="font-size:11.0pt;font-family:"Arial",sans-serif"> </span><span style="font-size:11.0pt">PM Andy Goryachev<br>
                            > <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a>
                            wrote:<br>
                            >> Dear fellow developers:<br>
                            >><br>
                            >><br>
                            >><br>
                            >> Thank you for providing a lively
                            discussion here in the mailing list, and in
                            the PR.<br>
                            >><br>
                            >><br>
                            >><br>
                            >> A surprisingly large number of
                            objection was voiced, among them in no
                            particular order (please correct me if I
                            missed anything):<br>
                            >><br>
                            >><br>
                            >><br>
                            >> - no need for the traversal policy
                            API, developers have all the tools they need<br>
                            >><br>
                            >> - rather than providing
                            Parent.traversalPolicy, the whole thing
                            should be delegated to Scene<br>
                            >><br>
                            >> - no need for custom traversal
                            policies, provide a number of standard
                            policies (e.g. cyclic/logical; or via enum
                            if possible)<br>
                            >><br>
                            >> - introducing a new category of
                            traversal events (later deemed unnecessary)<br>
                            >><br>
                            >> - adding two properties to Parent
                            for directional and logical traversal<br>
                            >><br>
                            >> - desire to be able to configure
                            traversal policy via CSS<br>
                            >><br>
                            >> - focus traversal methods should be
                            instance methods in the Node class<br>
                            >><br>
                            >><br>
                            >><br>
                            >> Also, the discussion reiterated
                            some of the design problems we have in
                            JavaFX, namely<br>
                            >><br>
                            >><br>
                            >><br>
                            >> - controls consuming key events
                            that effect no change in the control's state<br>
                            >><br>
                            >> - interference between controls'
                            key handling and Scene's accelerators<br>
                            >><br>
                            >> - undetermined priority of event
                            handlers registered by the skin and the
                            application<br>
                            >><br>
                            >><br>
                            >><br>
                            >> I still believe there is a value in
                            providing the traversal policy APIs, but
                            given the general sentiment in the feedback,
                            I think the right approach would be to scale
                            down the proposal to leave only the focus
                            traversal API [0], addressing a single use
                            case of the custom components [1].<br>
                            >><br>
                            >><br>
                            >><br>
                            >> I am sad to think that there will
                            be no support for custom traversal policies
                            in JavaFX in the foreseeable future, as it
                            seems highly unlikely that my company will
                            sponsor a major redesign of the focus
                            subsystem.  I hope there is a non-zero
                            chance of the open source community coming
                            together and designing an alternative that
                            satisfies everyone, so maybe not all is
                            lost.<br>
                            >><br>
                            >><br>
                            >><br>
                            >> Please let me know what you think
                            of the new proposal.<br>
                            >><br>
                            >><br>
                            >><br>
                            >> Thanks,<br>
                            >><br>
                            >> -andy<br>
                            >><br>
                            >><br>
                            >><br>
                            >><br>
                            >><br>
                            >> [0] <a href="https://github.com/andy-goryachev-oracle/Test/blob/main/doc/FocusTraversal/FocusTraversal-v2.md" moz-do-not-send="true" class="moz-txt-link-freetext">
https://github.com/andy-goryachev-oracle/Test/blob/main/doc/FocusTraversal/FocusTraversal-v2.md</a><br>
                            >><br>
                            >> [1] JDK-8091673 Public focus
                            traversal API for use in custom controls<br>
                            >><br>
                            >> [2] Draft PR <a href="https://github.com/openjdk/jfx/pull/1604" moz-do-not-send="true" class="moz-txt-link-freetext">https://github.com/openjdk/jfx/pull/1604</a></span><o:p></o:p></p>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>