<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 24/09/2024 23:58, Andy Goryachev
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:BL3PR10MB61855645DC9827B4A60A302FE5682@BL3PR10MB6185.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: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;}@font-face
        {font-family:Optima-Regular;
        panose-1:2 0 5 3 6 0 0 2 0 4;}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.apple-converted-space
        {mso-style-name:apple-converted-space;}span.outlook-search-highlight
        {mso-style-name:outlook-search-highlight;}span.EmailStyle21
        {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
            Martin:<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 for a very thoughtful and constructive response!  It
            will take me some time to digest, but I do want to mention
            some thoughts I had while listening to the discussion
            earlier.<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.
            TraversalEvent<o:p></o:p></span></p>
        <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">You
            are right, it appears there might be a few or no use cases
            for this event as far as app code is concerned.  Looking at
            the code, it was a replacement for internal
            TraversalEngine.TraverseListener utilized by several skins. 
            It might be possible to remove it and instead rely on
            listening to Scene.focusOwnerProperty, at the expense of
            complicating the skins.  Is this a good idea?  Will removing
            the event make it more difficult to write a custom
            component/skin?</span></p>
      </div>
    </blockquote>
    I think it is worth looking into this.  API to make things "easier"
    to implement now will bite you later (see CSS and its binary CSS
    load/save API that didn't really needed to be public...)<br>
    <blockquote type="cite"
cite="mid:BL3PR10MB61855645DC9827B4A60A302FE5682@BL3PR10MB6185.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"">2.
            The fact that some policies depend on the state of the
            control basically negates the idea of standard set of
            policies encoded in an enum.</span></p>
      </div>
    </blockquote>
    <p>I really think exposing policies is a bit overkill, and should be
      considered later if at all.  Controls just want to be able to use
      the standard traversal mechanism, which will not be such a pain to
      get once  <a class="moz-txt-link-freetext" href="https://bugs.openjdk.org/browse/JDK-8340852">https://bugs.openjdk.org/browse/JDK-8340852</a> is fixed (as
      you can just let it bubble up).  Controls that really want
      something different to happen can take the extra steps of adding
      KeyEvent handlers, consuming those only when they don't want the
      standard navigation from Scene.</p>
    <p>I don't think it should be a goal to have all the complex
      navigation cases possible with FX controls be possible with a new
      API.  You can already do whatever navigation you want by finding
      the Node you need and focusing it.  The problem has always been
      how to get the **default** navigation for your custom control
      (which will cover the vast majority of cases already) -- this was
      hard because events wouldn't bubble up to Scene properly, which
      necessitated installing your own Key handlers, which then
      necessitates having access to the standard focus changing code...
      It is a cascade of problems for which we're now building a
      "workaround", which IMHO is not really needed once the cause of
      this problem is fixed.<br>
    </p>
    <blockquote type="cite"
cite="mid:BL3PR10MB61855645DC9827B4A60A302FE5682@BL3PR10MB6185.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"">3.
            Controls may need to intercept traversal keys and fire off
            the traversal, for example, TAB on a read-only TextArea
            should traverse, but should insert the tab character into
            the editable TextArea.  (I would imagine this can be also
            implemented by not consuming events if they effect no change
            in the control, but that is a different story).</span></p>
      </div>
    </blockquote>
    <p>That's really how it should be.  Controls should preferably
      always delegate so there is no navigation code all over the place.</p>
    <p>--John<br>
    </p>
    <blockquote type="cite"
cite="mid:BL3PR10MB61855645DC9827B4A60A302FE5682@BL3PR10MB6185.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"">4.
            It might be possible for controls like ToggleButton to set
            its own traversal policy instead intercepting KeyEvents
            (which is the current way of dealing with conditional
            traversal).  I would imagine this being done as a separate
            enhancement though.<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"">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">Martin Fox
                    <a class="moz-txt-link-rfc2396E" href="mailto:martin@martinfox.com"><martin@martinfox.com></a><br>
                    <b>Date: </b>Tuesday, September 24, 2024 at 13:30<br>
                    <b>To: </b>Andy Goryachev
                    <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a><br>
                    <b>Cc: </b>OpenJFX <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
                    <b>Subject: </b>Re: [External] : Re: Proposal:
                    Focus Traversal API<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">Andy,<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">Glad
                    to finally see a proposal for opening up traversal.
                    Long overdue.<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">There’s
                    a case in the current control set that this API
                    doesn’t cover. ToggleButtons intercept the arrow
                    keys so they can implement a cyclic traversal policy
                    among buttons in the ToggleGroup. They don’t assume
                    that their Parent will do this for them. To
                    reproduce this behavior this API would have to be
                    extended so it can first ask the focusOwner where to
                    traverse to before moving on to the Parent. (And
                    looking at the code I think there’s yet another bug
                    where events are consumed when they should not be.
                    Sigh).<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">The
                    proposal doesn’t provide any use cases for the
                    TraversalEvent. It also doesn’t specify the initial
                    target of the event or how it should be handled. I
                    had to look in the sources to see what it’s being
                    used for and that (a) it’s being fired at the new
                    focus owner and (b) it’s a bad idea to consume it.
                    It looks more like information you want to broadcast
                    to a set of listeners rather than a message to be
                    acted on. If nothing else the bounds should be
                    removed from this event since that’s a very specific
                    piece of info that only the ScrollPaneSkin wants. I
                    haven’t mapped out the details but I’m pretty sure
                    it can figure out the bounds itself.<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">This
                    proposal should give some quick background on how
                    traversal key events are handled, specifically that
                    controls should let the key events bubble up to the
                    Scene to invoke traversal. And if the traversal keys
                    are always going to be consumed by the Scene that
                    should also be mentioned.<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">There’s
                    been a few comments suggesting the traversal key
                    events should not be consumed if the focusOwner
                    doesn’t change. Unfortunately that would break
                    Popups which have an, um, interesting event
                    architecture. And I don’t want to introduce yet
                    another instance where events need to be consumed
                    under specific conditions or things break down (I’m
                    currently tracking down bugs where ESCAPE is
                    consumed when it shouldn’t be or not consumed when
                    it should be). We should figure out what these
                    clients need and ensure it’s delivered to them in a
                    reliable way. Perhaps when traversal ends we could
                    fire an event at the Scene with all the details?<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">The
                    sample code is problematic since we really don’t
                    want controls to kick off traversal themselves
                    unless they absolutely have to. That caveat should
                    probably precede the code. If you must provide some
                    sample code please make sure it checks the modifier
                    state on the KeyEvent. (There really should be a
                    central API for mapping a KeyEvent to a
                    TraversalDirection but that would be a different
                    proposal.)<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">If
                    we provide pre-packaged traversal policies we’ll
                    need to provide multiple variants of CYCLIC. A menu
                    bar cycles horizontally with the arrow keys and Tab
                    but not vertically. According to the w3c a toggle
                    button group should cycle with all the arrow keys
                    but not with the Tab key. And there’s probably one
                    or two more combinations in the current control set
                    and w3c accessibility guidelines.<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt">Martin<o:p></o:p></span></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:12.0pt"><br>
                    <br>
                    <o:p></o:p></span></p>
                <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
                  <div>
                    <p class="MsoNormal"><span style="font-size:12.0pt">On
                        Sep 24, 2024, at 11:57</span><span
style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><span
                        style="font-size:12.0pt">AM, Andy Goryachev
                        <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a> wrote:<o:p></o:p></span></p>
                  </div>
                  <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
                  <div>
                    <div>
                      <div>
                        <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">I
                            fully agree with Martin here.</span><o:p></o:p></p>
                      </div>
                      <div>
                        <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                      </div>
                      <div>
                        <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</span><o:p></o:p></p>
                      </div>
                      <div>
                        <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                      </div>
                      <div id="mail-editor-reference-message-container">
                        <div>
                          <div>
                            <div
style="border:none;border-top:solid windowtext 1.0pt;padding:3.0pt 0in 0in 0in;border-color:currentcolor currentcolor">
                              <p class="MsoNormal"
                                style="margin-bottom:12.0pt"><b><span
                                    style="font-size:12.0pt">From:<span
                                      class="apple-converted-space"> </span></span></b><span
                                  style="font-size:12.0pt">Martin Fox
                                  <a class="moz-txt-link-rfc2396E" href="mailto:martin@martinfox.com"><martin@martinfox.com></a><br>
                                  <b>Date:<span
                                      class="apple-converted-space"> </span></b>Wednesday,
                                  September 18, 2024 at 11:49<br>
                                  <b>To:<span
                                      class="apple-converted-space"> </span></b>John
                                  Hendrikx
                                  <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
                                  <b>Cc:<span
                                      class="apple-converted-space"> </span></b>Andy
                                  Goryachev
                                  <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a>,
                                  OpenJFX
                                  <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
                                  <b>Subject:<span
                                      class="apple-converted-space"> </span></b>Re:
                                  [External] : Re: Proposal: Focus
                                  Traversal API</span><o:p></o:p></p>
                            </div>
                            <div>
                              <p class="MsoNormal"><span
                                  style="font-size:12.0pt">John,</span><o:p></o:p></p>
                            </div>
                            <div>
                              <div>
                                <p class="MsoNormal"><span
                                    style="font-size:12.0pt"> </span><o:p></o:p></p>
                              </div>
                            </div>
                            <div>
                              <div>
                                <p class="MsoNormal"><span
                                    style="font-size:12.0pt">Sorry I
                                    didn’t respond to this thread
                                    earlier. I’ve been looking at the
                                    code and bug database trying to work
                                    backward to a problem statement. The
                                    bug reports cited in the PR are
                                    light on details so I’m trying to
                                    come up with a more concrete set of
                                    use cases to consider.</span><o:p></o:p></p>
                              </div>
                            </div>
                            <div>
                              <div>
                                <p class="MsoNormal"><span
                                    style="font-size:12.0pt"> </span><o:p></o:p></p>
                              </div>
                            </div>
                            <div>
                              <div>
                                <p class="MsoNormal"><span
                                    style="font-size:12.0pt">Currently
                                    I’m failing to see the benefit of a
                                    traversal event model.</span><o:p></o:p></p>
                              </div>
                              <div>
                                <div>
                                  <p class="MsoNormal"><span
                                      style="font-size:12.0pt"> </span><o:p></o:p></p>
                                </div>
                              </div>
                              <div>
                                <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                  <div>
                                    <div
id="mail-editor-reference-message-container">
                                      <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                        <div
id="mail-editor-reference-message-container">
                                          <p><span
style="font-size:10.5pt;font-family:Optima-Regular">- User can decide to
                                              act on **any** key, even
                                              navigation keys, without
                                              the system interfering by
                                              consuming keys early,
                                              unexpectedly or even
                                              consuming these keys
                                              without doing anything
                                              (sometimes keys get
                                              consumed that don't
                                              actually change
                                              focus...). <o:p></o:p></span></p>
                                        </div>
                                      </blockquote>
                                    </div>
                                  </div>
                                </blockquote>
                                <div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:12.0pt">It
                                        doesn’t really matter whether
                                        the control is capturing the key
                                        event and invoking the traversal
                                        engine directly or firing off a
                                        TraversalEvent. The problem is
                                        that the control is processing
                                        the key event in the first
                                        place. You’re talking about
                                        something that happens before
                                        traversal is even initiated.</span><o:p></o:p></p>
                                  </div>
                                </div>
                                <div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:12.0pt"> </span><o:p></o:p></p>
                                  </div>
                                </div>
                                <div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:12.0pt">It’s
                                        unfortunate that the code
                                        snippet in the proposal shows a
                                        control doing a direct mapping
                                        from KeyCodes to traversal
                                        calls. That’s not how the
                                        current system is intended to
                                        work. There’s already a
                                        dispatcher at the Scene level
                                        that processes KeyEvents and
                                        invokes the traversal machinery
                                        so controls should just let the
                                        traversal keys bubble up. There
                                        are exceptions to this
                                        throughout the code which I
                                        would like to get a better
                                        handle on since I can’t tell if
                                        they’re bugs or truly necessary
                                        exceptions.</span><o:p></o:p></p>
                                  </div>
                                </div>
                                <div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:12.0pt"> </span><o:p></o:p></p>
                                  </div>
                                </div>
                                <div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:12.0pt">Once
                                        the system has determined that
                                        it’s time for traversal it needs
                                        to map from a KeyEvent to a
                                        direction and type. I can see
                                        where providing a centralized
                                        API for doing this could be of
                                        benefit but I’m not sure that
                                        has anything to do with this PR
                                        or the concept of
                                        TraversalEvents. This is also a
                                        decision made before traversal
                                        is initiated.</span><o:p></o:p></p>
                                  </div>
                                </div>
                                <div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:12.0pt"> </span><o:p></o:p></p>
                                  </div>
                                </div>
                                <div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:12.0pt">You
                                        give some examples of
                                        customizing traversal in various
                                        ways. From what I can tell all
                                        of them can be accomplished
                                        using this PR with maybe one
                                        exception that I’ll get to when
                                        I respond to Andy’s proposal. In
                                        other cases I can’t tell if a
                                        TraversalEvent would provide a
                                        cleaner implementation because I
                                        don’t understand how they would
                                        work. For example, one could
                                        imagine a system where a
                                        TraversalEvent is fired by the
                                        Scene and expected to bubble
                                        back up to the Scene which will
                                        then utilize the existing
                                        centralized engines to actually
                                        perform the traversal. But one
                                        could also imagine a system
                                        where the Scene fires a
                                        TraversalEvent and the nodes act
                                        on them directly as it bubbles
                                        up. I’m not sure what you have
                                        in mind. It would be nice to see
                                        some examples of how a
                                        TraversalEvent would move
                                        through the system in various
                                        scenarios particularly when
                                        traversing laterally.</span><o:p></o:p></p>
                                  </div>
                                </div>
                                <div>
                                  <div>
                                    <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Martin<o:p></o:p></span></p>
                                  </div>
                                </div>
                                <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                  <div>
                                    <div>
                                      <p class="MsoNormal"><span
                                          style="font-size:12.0pt">On
                                          Sep 17, 2024, at 11:05</span><span
style="font-size:12.0pt;font-family:"Arial",sans-serif"> </span><span
                                          style="font-size:12.0pt">PM,
                                          John Hendrikx
                                          <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a>
                                          wrote:</span><o:p></o:p></p>
                                    </div>
                                  </div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:12.0pt"> </span><o:p></o:p></p>
                                  </div>
                                  <div>
                                    <p
style="font-variant-caps:normal;text-align:start;word-spacing:0px"><span
style="font-size:10.5pt;font-family:Optima-Regular">Andy,<o:p></o:p></span></p>
                                    <p
style="font-variant-caps:normal;text-align:start;word-spacing:0px"><span
style="font-size:10.5pt;font-family:Optima-Regular">As you're not
                                        responding to any of the
                                        suggestions or any of my
                                        questions, but are only
                                        re-iterating points that I
                                        believe are not going to be a
                                        benefit to the long term
                                        viability of FX, I see no point
                                        in continuing the discussion
                                        further.<o:p></o:p></span></p>
                                    <p
style="font-variant-caps:normal;text-align:start;word-spacing:0px"><span
style="font-size:10.5pt;font-family:Optima-Regular">--John<o:p></o:p></span></p>
                                    <div>
                                      <div>
                                        <p class="MsoNormal"><span
style="font-size:10.5pt;font-family:Optima-Regular">On 18/09/2024 01:09,
                                            Andy Goryachev wrote:</span><o:p></o:p></p>
                                      </div>
                                    </div>
                                    <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt;font-variant-caps:normal;text-align:start;word-spacing:0px">
                                      <div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Dear
                                                John:</span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">You
                                                do bring a lot of good
                                                points, no doubt.  And I
                                                do agree with a lot of
                                                the suggestion, but I
                                                still want to emphasize
                                                two points:</span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">1.
                                                The backward
                                                compatibility should not
                                                be dismissed that
                                                easily.  There is a
                                                number of existing
                                                applications out there
                                                and we do not want to
                                                break them.  Whether the
                                                behavior is specified or
                                                not is irrelevant, we do
                                                not want to cause mayhem
                                                from the customers and
                                                developers alike whose
                                                keyboard navigation
                                                suddenly changed.</span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">2. I
                                                question the cost
                                                benefit analysis of the
                                                redesign idea.  While I
                                                agree with you that it
                                                might help with some
                                                unusual cases, the
                                                overall benefit is
                                                rather limited.  The
                                                benefit of the proposed
                                                solution is, in my
                                                opinion, far greater: it
                                                allows for custom
                                                traversal policies (a
                                                feature that has been
                                                requested multiple
                                                times) and enables focus
                                                traversal from custom
                                                components, something of
                                                a lesser value, but
                                                still important. 
                                                Exposing the existing
                                                APIs is a relatively
                                                cheap solution that will
                                                give us two features at
                                                nearly zero cost.  On
                                                the other hand, I doubt
                                                that our team, or
                                                yourself, are willing
                                                commit substantial
                                                development effort to
                                                redesign the thing to
                                                use events.  Which
                                                brings me to the choice
                                                I mentioned earlier:
                                                realistically, we have a
                                                choice of providing two
                                                requested features soon,
                                                or never.</span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">I
                                                would also encourage
                                                other members of the
                                                development community to
                                                voice their opinion on
                                                the subject, perhaps
                                                there is something else
                                                we can do to move
                                                forward.</span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Thank
                                                you</span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div>
                                          <div>
                                            <p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                          </div>
                                        </div>
                                        <div
id="mail-editor-reference-message-container">
                                          <div>
                                            <div>
                                              <div
style="border:none;border-top:solid windowtext 1.0pt;padding:3.0pt 0in 0in 0in;border-color:currentcolor">
                                                <p class="MsoNormal"
style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt">From:<span
class="apple-converted-space"> </span></span></b><span
style="font-size:12.0pt">John Hendrikx<span
class="apple-converted-space"> </span><a
href="mailto:john.hendrikx@gmail.com" moz-do-not-send="true"><span
style="color:#467886"><john.hendrikx@gmail.com></span></a><br>
                                                    <b>Date:<span
class="apple-converted-space"> </span></b>Saturday, September 14, 2024
                                                    at 09:41<br>
                                                    <b>To:<span
class="apple-converted-space"> </span></b>Andy Goryachev<span
class="apple-converted-space"> </span><a
href="mailto:andy.goryachev@oracle.com" moz-do-not-send="true"><span
style="color:#467886"><andy.goryachev@oracle.com></span></a>,<span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true"><span
style="color:#467886">openjfx-dev@openjdk.org</span></a><span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true"><span
style="color:#467886"><openjfx-dev@openjdk.org></span></a><br>
                                                    <b>Subject:<span
class="apple-converted-space"> </span></b>[External] : Re: Proposal:
                                                    Focus Traversal API</span><o:p></o:p></p>
                                              </div>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Hi Andy,<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">First let me say
                                                  that when it comes to
                                                  designing an API, you
                                                  really need to take
                                                  the time to think the
                                                  solution through.  The
                                                  current internal
                                                  solution was probably
                                                  kept internal for
                                                  exactly that reason,
                                                  insufficient time to
                                                  work out the kinks and
                                                  look into
                                                  alternatives.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">An API is almost
                                                  impossible to change
                                                  later, so the general
                                                  rule is that if you're
                                                  not sure about an API,
                                                  then its better to
                                                  have no API.  This is
                                                  why I think it is
                                                  important that we
                                                  first look for what
                                                  the API should look
                                                  like, then worry about
                                                  how this can be fitted
                                                  onto JavaFX.  Making
                                                  concessions related to
                                                  the current
                                                  implementation before
                                                  having a clear idea of
                                                  how the API should
                                                  preferably work is not
                                                  part of that.  You
                                                  start making
                                                  concessions only when
                                                  it turns out the
                                                  preferred design would
                                                  encounter unresolvable
                                                  problems in the
                                                  current
                                                  implementation.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Since I think there
                                                  is very little public
                                                  API related to focus
                                                  traversal, nor is
                                                  there any
                                                  specification of how
                                                  it currently works, I
                                                  think we have a lot of
                                                  room to maneuver. 
                                                  This is why I think we
                                                  should first reach a
                                                  consensus on the API,
                                                  then look how it can
                                                  be fitted on top of
                                                  FX.  Sometimes a well
                                                  thought out API also
                                                  is a natural fit, and
                                                  may be easier to
                                                  migrate to than you
                                                  think.<o:p></o:p></span></p>
                                              <div>
                                                <div>
                                                  <div>
                                                    <p class="MsoNormal"><span
style="font-size:12.0pt">On 14/09/2024 00:17, Andy Goryachev wrote:</span><o:p></o:p></p>
                                                  </div>
                                                </div>
                                              </div>
                                              <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                                <div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Dear
                                                          John,
                                                          Everyone:</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Thank
                                                          you for a
                                                          thoughtful
                                                          response! 
                                                          Some of the
                                                          ideas you
                                                          described
                                                          definitely
                                                          deserve
                                                          further
                                                          consideration. 
                                                          If I were to
                                                          summarize:</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">1.
                                                          move the focus
                                                          traversal
                                                          logic away
                                                          from the
                                                          components and
                                                          into the Scene</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">2.
                                                          re-implement
                                                          focus
                                                          traversal
                                                          through
                                                          TraversalEvents
                                                          rather than
                                                          responding
                                                          directly to
                                                          KeyEvents</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">3.
                                                          (more)
                                                          standard
                                                          policies</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">4.
                                                          using CSS</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">(there
                                                          is of course
                                                          more topics in
                                                          your response,
                                                          but let me
                                                          start with the
                                                          4 above)</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">#1</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">I
                                                          generally like
                                                          this idea.  In
                                                          some sense it
                                                          is already how
                                                          things work
                                                          internally,
                                                          but without
                                                          the ability to
                                                          customize that
                                                          (i.e. by
                                                          introducing
                                                          custom
                                                          traversal
                                                          keys, or
                                                          removing
                                                          existing
                                                          ones).  The
                                                          downside is
                                                          substantial:
                                                          not only we'd
                                                          need to
                                                          re-design the
                                                          whole of the
                                                          focus
                                                          traversal, but
                                                          also rework
                                                          the existing
                                                          control's
                                                          behaviors. 
                                                          Did I mention
                                                          the risk of
                                                          regression,
                                                          given the
                                                          absence of
                                                          comprehensive
                                                          behavioral
                                                          tests?</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                </div>
                                              </blockquote>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">There's two things
                                                  here.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">1. There is no need
                                                  to re-design the whole
                                                  focus traversal.  The
                                                  old internal system
                                                  can be gradually
                                                  replaced (it works by
                                                  directly consuming
                                                  KeyEvents after all).<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">2. Regression.  When
                                                  nothing is specified,
                                                  and the fact that
                                                  controls **ought** to
                                                  work like other common
                                                  controls in different
                                                  UI toolkits, is it a
                                                  regression when focus
                                                  traversal works the
                                                  same as those other
                                                  platforms, even if it
                                                  may be a regression
                                                  from the point of view
                                                  of FX?  For example, a
                                                  Spinner will currently
                                                  react to any mouse
                                                  key, where as other
                                                  common toolkits only
                                                  react to the left
                                                  mouse button.  Is it a
                                                  regression if FX is
                                                  adjusted to also only
                                                  react to the left
                                                  mouse button?  It's
                                                  not specified
                                                  anywhere.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I think we have
                                                  sufficient space to
                                                  maneuver here as long
                                                  as we are not making
                                                  focus traversal
                                                  completely different
                                                  from how it commonly
                                                  works in UI's.<o:p></o:p></span></p>
                                              <div>
                                                <p class="MsoNormal"
style="margin-bottom:12.0pt"><span style="font-size:12.0pt">Can there be
                                                    regressions versus
                                                    the current
                                                    (unspecified)
                                                    implementation? 
                                                    Sure, there can be. 
                                                    Is that necessarily
                                                    bad?  That depends. 
                                                    If the new focus
                                                    traversal works like
                                                    it does on all other
                                                    toolkits, then no,
                                                    it is more of a bug
                                                    fix.  Did we break
                                                    something with the
                                                    new implementation? 
                                                    That's always
                                                    possible, but will
                                                    then be fixed as
                                                    soon as it is
                                                    reported.</span><o:p></o:p></p>
                                              </div>
                                              <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                                <div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">#2</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">This
                                                          may or may not
                                                          be an integral
                                                          part of #1. 
                                                          Potentially,
                                                          it allows for
                                                          injection of
                                                          events by the
                                                          application
                                                          code, as well
                                                          as simplifies
                                                          creation of
                                                          complex custom
                                                          controls.  The
                                                          latter becomes
                                                          possible with
                                                          the original
                                                          proposal, so
                                                          net benefit is
                                                          limited to the
                                                          first part, I
                                                          think.</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                </div>
                                              </blockquote>
                                              <div>
                                                <p class="MsoNormal"
style="margin-bottom:12.0pt"><span style="font-size:12.0pt">I think
                                                    TraversalEvents are
                                                    quite central to
                                                    making this an API
                                                    that will really
                                                    stand the test of
                                                    time.  It leverages
                                                    the existing event
                                                    system, giving you
                                                    all the power that
                                                    comes with it.  You
                                                    did not answer my
                                                    question about the
                                                    TraversalEvents in
                                                    your design.  Why
                                                    are the Events when
                                                    they can't be
                                                    triggered, filtered
                                                    or consumed?</span><o:p></o:p></p>
                                              </div>
                                              <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                                <div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">#3</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">One
                                                          obvious
                                                          possibility is
                                                          to enable
                                                          creation of a
                                                          simple policy
                                                          based on a
                                                          list of
                                                          Nodes.  I must
                                                          mention one
                                                          use case that
                                                          is impossible
                                                          to cover with
                                                          pre-defined
                                                          policy is one
                                                          where
                                                          navigation
                                                          depends on
                                                          some state. 
                                                          Such a policy
                                                          must be
                                                          implemented
                                                          programmatically. 
                                                          I think one
                                                          property
                                                          should be
                                                          sufficient - I
                                                          am strongly
                                                          against adding
                                                          two properties
                                                          here.</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                </div>
                                              </blockquote>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Programmatic escapes
                                                  can always be achieved
                                                  by responding directly
                                                  to a TraversalEvent. 
                                                  I think however this
                                                  should be a rare case,
                                                  and standard policies
                                                  should really cover
                                                  almost all use cases. 
                                                  It may be a gap that
                                                  should be
                                                  investigated, and the
                                                  API adjusted for
                                                  (usually the
                                                  "exceptions" are well
                                                  worth looking into to
                                                  see if with a tweak
                                                  they can't become
                                                  "standard").  As for
                                                  being "strongly
                                                  against" having two
                                                  properties -- that's
                                                  an odd stance to take
                                                  without motivating
                                                  it.  It could also be
                                                  rolled into "one"
                                                  where the Policy is a
                                                  record with the two
                                                  values, but I think
                                                  we're getting ahead of
                                                  ourselves here.  First
                                                  the API, then the
                                                  implementation.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I do think however
                                                  there is great value
                                                  in having the Logical
                                                  and Directional
                                                  navigation split. 
                                                  Often you'll only want
                                                  to replace one of
                                                  these with a custom
                                                  policy (or a different
                                                  standard policy), so
                                                  that the other
                                                  navigation method can
                                                  be used to escape the
                                                  control.  For example,
                                                  a Toolbar could be
                                                  tabbed in an out of
                                                  (using Logical
                                                  navigation) while the
                                                  Directional navigation
                                                  is cyclic (and thus
                                                  can't be used to
                                                  escape the control's
                                                  context).<o:p></o:p></span></p>
                                              <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                                <div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">#4</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">The
                                                          idea of using
                                                          CSS to specify
                                                          traversal
                                                          policy seems
                                                          wrong to me:
                                                          the CSS
                                                          defines the
                                                          presentation
                                                          aspects
                                                          (styles)
                                                          rather than
                                                          behavioral
                                                          ones.  I know
                                                          it is possible
                                                          to set custom
                                                          skins and the
                                                          corresponding
                                                          behavior via
                                                          CSS, and we
                                                          know why
                                                          (skins define
                                                          the
                                                          appearance),
                                                          but we should
                                                          not go beyond
                                                          that, in my
                                                          opinion.</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                </div>
                                              </blockquote>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I see no problem
                                                  styling such
                                                  properties.  They're
                                                  FX properties, and it
                                                  would be very
                                                  convenient to style
                                                  them to globally alter
                                                  how focus works,
                                                  instead of having to
                                                  rely on, say, Builders
                                                  or Factories for
                                                  controls where
                                                  traversal policies can
                                                  be applied.  There are
                                                  also already
                                                  properties that don't
                                                  only influence the
                                                  look of controls. 
                                                  "-fx-skin" being the
                                                  most obvious one, but
                                                  there is also
                                                  "-fx-focus-traversable",
"-fx-context-menu-enabled", "-fx-block-increment", "-fx-unit-increment",
                                                  "-fx-pannable",
                                                  "-fx-initial-delay",
                                                  "-fx-repeat-delay",
                                                  "-fx-collapsible",
                                                  "-fx-show-delay",
                                                  "-fx-show-duration",
                                                  "-fx-hide-delay", and
                                                  probably more.  Aside
                                                  from "-fx-skin" none
                                                  of these properties
                                                  have a visual impact,
                                                  but instead alter
                                                  behavior.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Note: I'm not saying
                                                  this needs to be there
                                                  immediately.  I just
                                                  want to make sure
                                                  we're not closing off
                                                  this direction, as
                                                  again, it would be a
                                                  huge hassle to do this
                                                  programmatically.  In
                                                  "code" the only things
                                                  I usually do on my
                                                  controls are the
                                                  following:<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">- I define the
                                                  container hierarchy
                                                  (VBox, HBox, which
                                                  children go where)<br>
                                                  - I set a style name<br>
                                                  - I set anything that
                                                  unfortunately cannot
                                                  be CSS styled (things
                                                  like ALWAYS,
                                                  SOMETIMES, NEVER grow
                                                  policies, Grid sizes,
                                                  etc, things that are
                                                  clearly "visual" but
                                                  still can't be
                                                  styled).<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">All the rest I don't
                                                  touch, or want to
                                                  touch.  Having to
                                                  select a traversal
                                                  policy for every
                                                  control of type X I
                                                  create is just
                                                  cumbersome and
                                                  unnecessary.  There
                                                  will be a call then to
                                                  set this "globally",
                                                  and then there will be
                                                  the question, do we
                                                  make something custom
                                                  with many limitations
                                                  because it doesn't fit
                                                  our conceptions of
                                                  what (FX) CSS is for
                                                  (ie, not style, but
                                                  only *visual* style)
                                                  or do we just expose
                                                  these properties as
                                                  Styleable leveraging
                                                  an existing powerful
                                                  system with almost
                                                  zero effort?<o:p></o:p></span></p>
                                              <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                                <div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">--</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">There
                                                          is one more
                                                          aspect of the
                                                          problem that I
                                                          think we
                                                          should
                                                          consider.  The
                                                          current
                                                          proposal does
                                                          not change the
                                                          implementation
                                                          in any
                                                          material way,
                                                          nor does it
                                                          change the
                                                          behavior, thus
                                                          can be done
                                                          quickly.  The
                                                          benefit
                                                          everyone gets
                                                          from it is
                                                          ability to
                                                          trigger focus
                                                          traversal and
                                                          to control it
                                                          via custom
                                                          policies.  Any
                                                          other solution
                                                          will require
                                                          resources and
                                                          the bandwidth
                                                          we currently
                                                          don't have,
                                                          which means
                                                          the<span
class="apple-converted-space"> </span><i>probability</i><span
class="apple-converted-space"> </span>of it being added to FX is
                                                          virtually
                                                          zero.  Let me
                                                          emphasize, I
                                                          am not against
                                                          attempting to
                                                          discuss or
                                                          implement the
                                                          best possible
                                                          solution, but
                                                          we should be
                                                          aware of the
                                                          limitations of
                                                          the reality we
                                                          live in.</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                </div>
                                              </blockquote>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">"Quickly" and API's
                                                  are incompatible with
                                                  each other.  There is
                                                  nothing worse than
                                                  exposing an API
                                                  quickly, which then
                                                  becomes a burden on
                                                  the system -- I think
                                                  the current CSS API is
                                                  a prime example of
                                                  where "quickly" has
                                                  gone wrong, costing us
                                                  tremendous amounts of
                                                  effort to make even
                                                  minor changes to it.  <o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I urge you to ignore
                                                  the current
                                                  implementation, think
                                                  thoroughly how (in an
                                                  ideal world) you would
                                                  want such an API to
                                                  work (from a user
                                                  perspective, not from
                                                  an implementor's
                                                  perspective) and only
                                                  then see how this
                                                  could be made to fit
                                                  into JavaFX.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">This is exactly what
                                                  I did.  I did not look
                                                  at the implementation,
                                                  although I'm aware of
                                                  some of it.  I looked
                                                  at how I as a user of
                                                  FX am building
                                                  applications, the
                                                  struggles I have with
                                                  it currently, (with
                                                  controls for example
                                                  "eating" KeyEvents),
                                                  and how I would like
                                                  to be able to adjust
                                                  focus traversal.  Do I
                                                  want to respond to
                                                  "KeyCode.LEFT" or do I
                                                  want to respond to
                                                  "TraversalEvent.LEFT"? 
                                                  Do I also need to
                                                  respond to
                                                  "KeyCode.NUM_PAD_LEFT"? 
                                                  These things should be
                                                  abstracted, and
                                                  preferably I should
                                                  just be able to choose
                                                  from common navigation
                                                  standards.  And when I
                                                  do want to change such
                                                  a standard, in 99% of
                                                  the cases that will be
                                                  the case for all
                                                  similar controls in my
                                                  application.  How do I
                                                  do such things
                                                  currently if I want to
                                                  change something for
                                                  all controls in my
                                                  application?  I use
                                                  CSS.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Also I think this
                                                  can be implemented
                                                  gradually.  Here's a
                                                  potential plan:<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">1. Have Scene listen
                                                  to unused KeyEvents
                                                  and translate them to
                                                  TraversalEvents<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Benefit: gives
                                                  custom controls a way
                                                  to respond to keyboard
                                                  based navigation in a
                                                  platform agnostic way;
                                                  this probably already
                                                  removes the biggest
                                                  roadblock for custom
                                                  controls...<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Public API: Limited
                                                  to a new Event<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">2. Start converting
                                                  existing controls to
                                                  listen to
                                                  TraversalEvent instead
                                                  of KeyEvent<br>
                                                  <br>
                                                  This hits a lot of
                                                  controls, but should
                                                  be relatively easy to
                                                  do, and it can be all
                                                  kept internal for
                                                  now.  It can be done
                                                  in a few batches.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Benefit: for each
                                                  control converted,
                                                  user can now
                                                  programmatically
                                                  trigger focus changes,
                                                  and by overriding
                                                  things at Scene level
                                                  can completely change
                                                  navigation keys<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Public API: none<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">3. Implement a
                                                  number of standard
                                                  policies internally
                                                  (OPEN, CONFINED,
                                                  CYCLIC, IGNORED)<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Convert any controls
                                                  that could use these
                                                  as their default,
                                                  removing any custom
                                                  logic if it happens to
                                                  match one of the
                                                  defaults.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Benefit: less code
                                                  to maintain and debug,
                                                  gives us experience
                                                  with which policies
                                                  make sense and where
                                                  the gaps are<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Public API: none<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Order: It is
                                                  possible to do this
                                                  before 2, and so some
                                                  of the control
                                                  conversions could just
                                                  consist of removing
                                                  their custom logic,
                                                  and selecting a
                                                  standard policy.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">4. Expose policy
                                                  property/properties on
                                                  Parent<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Any controls that
                                                  are not using a custom
                                                  policy anymore (of
                                                  type IGNORED) can now
                                                  be user adjusted.  We
                                                  don't have to
                                                  guarantee that each
                                                  policy makes sense for
                                                  each control. Changing
                                                  a default IGNORED
                                                  policy to a standard
                                                  one will change the
                                                  behavior (as intended)
                                                  but it need not be a
                                                  "complete" behavior
                                                  that users like.  This
                                                  is not FX's problem,
                                                  and can be improved
                                                  upon later.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Benefit: users can
                                                  now change policies on
                                                  any existing control,
                                                  even ones with a
                                                  custom policy; many of
                                                  the controls may
                                                  support a switch
                                                  between OPEN, CONFINED
                                                  and CYCLIC out of the
                                                  box.<o:p></o:p></span></p>
                                              <div>
                                                <div>
                                                  <p class="MsoNormal"><span
style="font-size:12.0pt">Public API: new properties on Parent</span><o:p></o:p></p>
                                                </div>
                                              </div>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">5. Perhaps expose
                                                  some helpful tools to
                                                  calculate the "next"
                                                  Node for a given
                                                  traversal option.<br>
                                                  <br>
                                                  This can be done at
                                                  any stage, and can be
                                                  considered completely
                                                  separate.  It is IMHO
                                                  a relatively
                                                  low priority need.<br>
                                                  <br>
                                                  Benefit: less work for
                                                  control implementors
                                                  (although they could
                                                  just "copy" said code)<br>
                                                  <br>
                                                  Public API: Maybe some
                                                  methods in Node, or
                                                  some kind of static
                                                  helper.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">6. CSS styleable
                                                  properties<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">If we really want to
                                                  give power to our
                                                  users, and impress
                                                  them with a flexible
                                                  focus traversal API,
                                                  then make these
                                                  properties styleable.<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Benefit: allow users
                                                  to pick any control,
                                                  and set is policy
                                                  globally or within a
                                                  subset of controls
                                                  (ie. dialogs, popups,
                                                  etc).<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Public API: Nothing
                                                  in Java, but document
                                                  as CSS properties<o:p></o:p></span></p>
                                              <p><span
style="font-size:10.5pt;font-family:Optima-Regular">--John<o:p></o:p></span></p>
                                              <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                                <div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Thank
                                                          you,</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div>
                                                    <div>
                                                      <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
                                                    </div>
                                                  </div>
                                                  <div
id="mail-editor-reference-message-container">
                                                    <div>
                                                      <div>
                                                        <div
style="border:none;border-top:solid windowtext 1.0pt;padding:3.0pt 0in 0in 0in;border-color:currentcolor">
                                                          <p
class="MsoNormal" style="margin-bottom:12.0pt"><b><span
style="font-size:12.0pt">From:<span class="apple-converted-space"> </span></span></b><span
style="font-size:12.0pt">openjfx-dev<span class="apple-converted-space"> </span><a
href="mailto:openjfx-dev-retn@openjdk.org" moz-do-not-send="true"><span
style="color:#467886"><openjfx-dev-retn@openjdk.org></span></a><span
class="apple-converted-space"> </span>on behalf of John Hendrikx<span
class="apple-converted-space"> </span><a
href="mailto:john.hendrikx@gmail.com" moz-do-not-send="true"><span
style="color:#467886"><john.hendrikx@gmail.com></span></a><br>
                                                          <b>Date:<span
class="apple-converted-space"> </span></b>Wednesday, September 11, 2024
                                                          at 19:05<br>
                                                          <b>To:<span
class="apple-converted-space"> </span></b><a
href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true"><span
style="color:#467886">openjfx-dev@openjdk.org</span></a><span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true"><span
style="color:#467886"><openjfx-dev@openjdk.org></span></a><br>
                                                          <b>Subject:<span
class="apple-converted-space"> </span></b>Re: Proposal: Focus Traversal
                                                          API</span><o:p></o:p></p>
                                                        </div>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Hi Andy / List,<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I've given this some
                                                          thought
                                                          first, without
                                                          looking too
                                                          much at the
                                                          proposal.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">In my view, focus
                                                          traversal
                                                          should be
                                                          implemented
                                                          using events,
                                                          and FX should
                                                          provide
                                                          standard
                                                          handling of
                                                          these events
                                                          controlled
                                                          with
                                                          properties
                                                          (potentially
                                                          even CSS
                                                          stylable for
                                                          easy mass
                                                          changing of
                                                          the default
                                                          navigation
                                                          policy).<br>
                                                          <br>
                                                          ## KeyEvent
                                                          and
                                                          TraversalEvent
                                                          separation<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I think the cleanest
                                                          implementation
                                                          would be to
                                                          implement a
                                                          KeyEvent
                                                          listener on
                                                          Scene that
                                                          takes any
                                                          unused
                                                          KeyEvents,
                                                          checks if
                                                          they're
                                                          considered
                                                          navigation
                                                          keys, and
                                                          converts these
                                                          keys to a new
                                                          type of event,
                                                          the
                                                          TraversalEvent.
                                                          The
                                                          TraversalEvent
                                                          is then fired
                                                          at the
                                                          original
                                                          target. The
                                                          TraversalEvent
                                                          is structured
                                                          into
                                                          Directional
                                                          and Logical
                                                          sub types, and
                                                          has leaf types
UP/DOWN/LEFT/RIGHT and NEXT/PREVIOUS.  Scene is the logical place to
                                                          handle this as
                                                          without a
                                                          Scene there is
                                                          no focus
                                                          owner, and so
                                                          there is no
                                                          point in doing
                                                          focus
                                                          traversal.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">This separation of
                                                          KeyEvents into
TraversalEvents achieves the following:<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">- User can decide to
                                                          act on **any**
                                                          key, even
                                                          navigation
                                                          keys, without
                                                          the system
                                                          interfering by
                                                          consuming keys
                                                          early,
                                                          unexpectedly
                                                          or even
                                                          consuming
                                                          these keys
                                                          without doing
                                                          anything
                                                          (sometimes
                                                          keys get
                                                          consumed that
                                                          don't actually
                                                          change
                                                          focus...). 
                                                          The navigation
                                                          keys have many
                                                          possible dual
                                                          purposes, and
                                                          robbing the
                                                          user of the
                                                          opportunity to
                                                          use them due
                                                          to an
                                                          overzealous
                                                          component
                                                          interpreting
                                                          them as
                                                          traversal keys
                                                          is very
                                                          annoying. 
                                                          Dual purposes
                                                          include for
                                                          example cursor
                                                          control in
                                                          TextField/TextArea,
                                                          Scrollbars,
                                                          etc.  The user
                                                          should have
                                                          the same
                                                          control here
                                                          as these FX
                                                          controls have.<br>
                                                          <br>
                                                          - Scene is
                                                          interpreting
                                                          the KeyEvents,
                                                          and this
                                                          interpretation
                                                          is now
                                                          controllable. 
                                                          If I want a
                                                          Toolbar (or
                                                          the whole
                                                          application)
                                                          to react to
                                                          WASD
                                                          navigation
                                                          keys, then
                                                          installing a
                                                          KeyEvent
                                                          handler at
                                                          Scene level or
                                                          at any
                                                          intermediate
                                                          Parent level
                                                          that converts
                                                          WASD to
                                                          UP/LEFT/DOWN/RIGHT
                                                          Traversal
                                                          events would
                                                          affect this
                                                          change easily.<br>
                                                          <br>
                                                          - The
                                                          separation
                                                          also allows to
                                                          block Focus
                                                          Traversal
                                                          only, without
                                                          blocking the
                                                          actual Keys
                                                          involved.  If
                                                          I want to stop
                                                          a Toolbar from
                                                          reacting to
                                                          LEFT/RIGHT,
                                                          but I need
                                                          those keys
                                                          higher up in
                                                          the hierarchy,
                                                          then I'm
                                                          screwed.  With
                                                          the
                                                          separation,
                                                          the key events
                                                          are
                                                          unaffected,
                                                          and I can
                                                          block Toolbars
                                                          from reacting
                                                          specifically
                                                          to traversal
                                                          events only.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">## Traversal Policy
                                                          Properties on
                                                          Parent<br>
                                                          <br>
                                                          I think FX
                                                          should provide
                                                          several
                                                          policies out
                                                          of the box,
                                                          based on
                                                          common
                                                          navigation
                                                          patterns.  The
                                                          goal here is
                                                          to have
                                                          policies in
                                                          place that
                                                          cover all use
                                                          cases in
                                                          current FX
                                                          provided
                                                          controls. 
                                                          This will
                                                          provide a good
                                                          base that will
                                                          cover probably
                                                          all realistic
                                                          work loads
                                                          that custom
                                                          controls may
                                                          have. The goal
                                                          is not to
                                                          support every
                                                          esoteric form
                                                          of navigation,
                                                          instead an
                                                          escape hatch
                                                          will be
                                                          provided in
                                                          the form of
                                                          disabling the
                                                          standard
                                                          navigation.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">In order to achieve
                                                          this, I think
                                                          Parent should
                                                          get two new
                                                          properties,
                                                          which control
                                                          how it will
                                                          react to
                                                          Directional
                                                          and Logical
                                                          navigation. 
                                                          These will
                                                          have default
                                                          values that
                                                          allow
                                                          navigation to
                                                          flow from Node
                                                          to Node within
                                                          a Parent and
                                                          from Parent to
                                                          its Parent
                                                          when
                                                          navigation
                                                          options in a
                                                          chosen
                                                          direction are
                                                          exhausted
                                                          within a
                                                          Parent. 
                                                          Custom
                                                          controls like
                                                          Combo boxes,
                                                          Toolbars,
                                                          Button groups,
                                                          etc, can
                                                          change the
                                                          default
                                                          provided by a
                                                          Parent
                                                          (similar to
                                                          how some
                                                          controls
                                                          change the
                                                          mouse
                                                          transparent
                                                          flag default).<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">These two properties
                                                          should cover
                                                          all realistic
                                                          needs, and
                                                          IMHO should be
                                                          considered to
                                                          be CSS
                                                          stylable in
                                                          the future to
                                                          allow easy
                                                          changing of
                                                          default
                                                          policies of
                                                          controls (ie.
                                                          want all
                                                          Toolbars to
                                                          react
                                                          differently to
                                                          navigation
                                                          keys, then
                                                          just style the
                                                          appropriate
                                                          property for
                                                          all toolbars
                                                          in one go).<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Parent will use
                                                          these
                                                          properties to
                                                          install an
                                                          event handler
                                                          that reacts to
TraversalEvents (not KeyEvents).  This handler can be fully disabled, or
                                                          overridden
                                                          (using
                                                          setOnTraversalEvent).<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">-
                                                          logicalTraversalPolicy<br>
                                                          -
                                                          directionalTraversalPolicy<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">The properties can
                                                          be set with a
                                                          value from a
                                                          TraversalPolicy
                                                          enum.  I would
                                                          suggest the
                                                          following
                                                          options:<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">- OPEN<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">This policy should
                                                          be the default
                                                          policy for all
                                                          Parents.  It
                                                          will act and
                                                          consume a
                                                          given
                                                          TraversalEvent
                                                          only when
                                                          there is a
                                                          suitable
                                                          target within
                                                          its
                                                          hierarchy.  If
                                                          there is no
                                                          suitable
                                                          target, or the
                                                          target would
                                                          remain
                                                          unchanged, the
                                                          event is NOT
                                                          consumed and
                                                          left to bubble
                                                          up, allowing
                                                          its parent(s)
                                                          to act on it
                                                          instead.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">- CONFINED<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">This policy consumes
                                                          all
                                                          TraversalEvents,
                                                          regardless of
                                                          whether there
                                                          is something
                                                          to navigate to
                                                          or not.  This
                                                          policy is
                                                          suitable for
                                                          controls that
                                                          have some kind
                                                          of
                                                          substructure
                                                          that we don't
                                                          want to
                                                          accidentally
                                                          exit with
                                                          either
                                                          Directional or
                                                          Logical
                                                          navigation. 
                                                          In most cases,
                                                          you only want
                                                          to set one of
                                                          the properties
                                                          to CONFINED as
                                                          otherwise
                                                          there would be
                                                          no keyboard
                                                          supported way
                                                          to exit your
                                                          control.  This
                                                          is a suitable
                                                          policy for say
                                                          button groups,
                                                          toolbars,
                                                          comboboxes,
                                                          etc.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">- CYCLIC<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Similar to CONFINED
                                                          but instead of
                                                          stopping
                                                          navigation at
                                                          the controls
                                                          logical
                                                          boundaries,
                                                          the navigation
                                                          wraps around
                                                          to the logical
                                                          start.  For
                                                          example, when
                                                          were
                                                          positioned on
                                                          the right most
                                                          button in a
                                                          button group,
                                                          pressing RIGHT
                                                          again would
                                                          navigate to
                                                          the left most
                                                          button.<br>
                                                          <br>
                                                          - IGNORED<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">This is similar to
                                                          the
                                                          mouseTransparent
                                                          property, and
                                                          basically
                                                          leaves the
                                                          TraversalEvent
                                                          to bubble up. 
                                                          This policy
                                                          allows you to
                                                          completely
                                                          disable
                                                          directional
                                                          and/or logical
                                                          navigation for
                                                          a control. 
                                                          Useful if you
                                                          want to
                                                          install your
                                                          own handler
                                                          (the escape
                                                          hatch) but
                                                          still want to
                                                          keep either
                                                          the default
                                                          directional or
                                                          logical
                                                          navigation.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Possible other
                                                          options for
                                                          this enum
                                                          could include
                                                          a version that
                                                          consumes all
                                                          TraversalEvents
                                                          (BLOCK) but I
                                                          don't see a
                                                          use for it at
                                                          the moment. 
                                                          There may also
                                                          be variants of
                                                          CONFINED and
                                                          CYCLIC that
                                                          make an
                                                          exception for
                                                          cases where
                                                          there is only
                                                          a single
                                                          choice
                                                          available.  A
                                                          ButtonGroup
                                                          for example
                                                          may want to
                                                          react
                                                          differently
                                                          depending on
                                                          whether it has
                                                          0, 1 or more
                                                          buttons. 
                                                          Whether these
                                                          should be
                                                          enshrined with
                                                          a custom enum
                                                          value, or
                                                          perhaps a
                                                          flag, or just
                                                          left up to a
                                                          custom
                                                          implementation
                                                          is something
                                                          we'd need to
                                                          decide still.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">## Use Cases<o:p></o:p></span></p>
                                                        <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span style="font-size:12.0pt">1) User wants to change
                                                          the behavior
                                                          of a control
                                                          from its
                                                          default to
                                                          something else
                                                          (ie. a Control
                                                          that is CYCLIC
                                                          can be changed
                                                          to OPEN or
                                                          CONFINED)</span><o:p></o:p></p>
                                                          </div>
                                                        </div>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Just call the
                                                          setters with
                                                          the
                                                          appropriate
                                                          preferred
                                                          policy.  This
                                                          could be done
                                                          in CSS for
                                                          maximum
                                                          convenience to
                                                          enable a
                                                          global change
                                                          of all similar
                                                          controls.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">2) User wants to act
                                                          on Traversal
                                                          events that
                                                          the standard
                                                          policy leaves
                                                          to bubble up<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Just install a
                                                          Traversal
                                                          event handler
                                                          either on the
                                                          control or on
                                                          its parent
                                                          (depending on
                                                          their needs). 
                                                          A potential
                                                          action to an
                                                          unused
                                                          Traversal
                                                          event could be
                                                          to close a
                                                          Dialog/Toast
                                                          popup, or a
                                                          custom
                                                          behavior like
                                                          selecting the
                                                          first/last
                                                          item or
                                                          next/previous
                                                          row (ie. if I
                                                          press "RIGHT"
                                                          and there is
                                                          no further
                                                          right item, a
                                                          user could
                                                          decide to have
                                                          this select
                                                          the first item
                                                          again in the
                                                          current Row or
                                                          the first item
                                                          in the
                                                          **next** Row).<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">3) User wants to do
                                                          crazy custom
                                                          navigation<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Set both policies
                                                          to IGNORED,
                                                          then install
                                                          your own event
                                                          handler (or
                                                          use the
                                                          setOnTraversalHandler
                                                          to completely
                                                          override the
                                                          handler).  Now
                                                          react on the
                                                          Traversal
                                                          events,
                                                          consuming them
                                                          at will and
                                                          changing focus
                                                          to whatever
                                                          control you
                                                          desire.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">4) User wants to
                                                          change what
                                                          keys are
                                                          considered
                                                          navigation
                                                          keys<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Install event
                                                          handler on
                                                          Scene (or any
                                                          intermediate
                                                          Parent) for
                                                          KeyEvents,
                                                          interpret WASD
                                                          keys as
                                                          UP/LEFT/DOWN/RIGHT
                                                          and sent out a
                                                          corresponding
                                                          Traversal
                                                          event<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">5) User wants to use
                                                          keys that are
                                                          considered
                                                          navigation
                                                          keys for their
                                                          own purposes<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Just install a
                                                          KeyEvent
                                                          handler as
                                                          usual, without
                                                          having to
                                                          worry that
                                                          Skins/Controls
                                                          eat these
                                                          events before
                                                          you can get to
                                                          them<br>
                                                          <br>
                                                          6) User wants
                                                          to stop a
                                                          control from
                                                          reacting to
                                                          traversal
                                                          events,
                                                          without
                                                          filtering
                                                          navigation
                                                          keys
                                                          completely<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">With the separation
                                                          of unconsumed
                                                          KeyEvents into
TraversalEvents, a user can now block only the latter to achieve this
                                                          goal without
                                                          having to
                                                          blanket block
                                                          certain
                                                          KeyEvents.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">-----<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">About the Proposal:<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I think the Goals
                                                          are fine as
                                                          stated,
                                                          although I
                                                          think we
                                                          differ on what
                                                          the Traversal
                                                          events
                                                          signify.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I think CSS support
                                                          should be
                                                          considered a
                                                          possible
                                                          future goal. 
                                                          The proposal
                                                          should
                                                          therefore take
                                                          into account
                                                          that we may
                                                          want to offer
                                                          this in the
                                                          future.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Motivation looks
                                                          okay.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">> The focus
                                                          traversal is
                                                          provided by
                                                          the
                                                          FocusTraversal
                                                          class which
                                                          offers static
                                                          methods for
                                                          traversing
                                                          focus in
                                                          various
                                                          directions,
                                                          determined by
                                                          the
                                                          TraversalDirection
                                                          enum.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I think these
                                                          methods don't
                                                          need to be
                                                          exposed with a
                                                          good selection
                                                          of standard
                                                          TraversalPolicy
                                                          options. 
                                                          After all,
                                                          there are only
                                                          so many ways
                                                          that you can
                                                          do a sensible
                                                          navigation
                                                          action without
                                                          confusing the
                                                          user, and
                                                          therefore I
                                                          think these
                                                          policy options
                                                          will cover 99%
                                                          of the use
                                                          cases
                                                          already.  For
                                                          the left over
                                                          1% we could
                                                          **consider**
                                                          providing
                                                          these focus
                                                          traversal
                                                          functions as a
                                                          separate
                                                          public API,
                                                          but I would
                                                          have them
                                                          return the
                                                          Node they
                                                          would suggest,
                                                          and leave the
                                                          final decision
                                                          to call
                                                          requestFocus
                                                          up to the
                                                          caller. 
                                                          Initially
                                                          however I
                                                          think there is
                                                          already more
                                                          than enough
                                                          power for
                                                          custom
                                                          implementations
                                                          to listen to
                                                          Traversal
                                                          events and do
                                                          their own
                                                          custom
                                                          navigation. 
                                                          If it is not
                                                          similar to one
                                                          of the
                                                          standard
                                                          navigation
                                                          options, the
                                                          traverseUp/Down
                                                          functions
                                                          won't be of
                                                          much use then
                                                          anyway.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">About your typical
                                                          example:<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">   <span
class="apple-converted-space"> </span>Node from = ...<br>
                                                             <span
class="apple-converted-space"> </span>switch
                                                          (((KeyEvent)event).getCode())
                                                          {<br>
                                                             <span
class="apple-converted-space"> </span>case UP:<br>
                                                                 <span
class="apple-converted-space"> </span>FocusTraversal.traverse(from,
                                                          TraversalDirection.UP,
TraversalMethod.KEY);<br>
                                                                 <span
class="apple-converted-space"> </span>event.consume();<br>
                                                                 <span
class="apple-converted-space"> </span>break;<br>
                                                             <span
class="apple-converted-space"> </span>case DOWN:<br>
                                                                 <span
class="apple-converted-space"> </span>// or use the convenience method<br>
                                                                 <span
class="apple-converted-space"> </span>FocusTraversal.traverseDown(from);<br>
                                                                 <span
class="apple-converted-space"> </span>event.consume();<br>
                                                                 <span
class="apple-converted-space"> </span>break;<br>
                                                             <span
class="apple-converted-space"> </span>}<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I think this is not
                                                          a good way to
                                                          deal with
                                                          events.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">1) The event is
                                                          consumed
                                                          regardless of
                                                          the outcome of
                                                          traverse. 
                                                          What if focus
                                                          did not
                                                          change? 
                                                          Should the
                                                          event be
                                                          consumed?<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">2) This is consuming
                                                          KeyEvents
                                                          directly,
                                                          robbing the
                                                          user of the
                                                          opportunity to
                                                          act on keys
                                                          considered
                                                          "special" by
                                                          FX.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">3) This code is not
                                                          only consuming
                                                          KeyEvents
                                                          directly, but
                                                          also deciding
                                                          what keys are
                                                          navigation
                                                          keys.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">So I think this
                                                          example code
                                                          should be
                                                          different.
                                                          However, first
                                                          I expect that
                                                          in most cases,
                                                          configuring a
                                                          different
                                                          traversal
                                                          policy on your
                                                          Parent
                                                          subclass will
                                                          already be
                                                          sufficient in
                                                          almost all
                                                          cases
                                                          (especially if
                                                          we look at FX
                                                          current
                                                          controls and
                                                          see if the
                                                          suggested
                                                          policies would
                                                          cover those
                                                          use cases). 
                                                          So this code
                                                          will almost
                                                          never be
                                                          needed. 
                                                          However, in
                                                          the event that
                                                          you need
                                                          something even
                                                          more specific,
                                                          you may
                                                          consider
                                                          handling
                                                          Traversal
                                                          events
                                                          directly.  In
                                                          which case the
                                                          code should
                                                          IMHO look
                                                          something like
                                                          this:<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">   <span
class="apple-converted-space"> </span>Node from = ...<br>
                                                          <br>
                                                             <span
class="apple-converted-space"> </span>Node result =
                                                          switch(traversalEvent.getEventType())
                                                          {<br>
                                                               <span
class="apple-converted-space"> </span>case TraversalEvent.UP ->
                                                          FocusTraversals.findUp(from);<br>
                                                               <span
class="apple-converted-space"> </span>case TraversalEvent.DOWN ->
                                                          FocusTraversals.findDown(from);<br>
                                                               <span
class="apple-converted-space"> </span>// etc<br>
                                                            <span
class="apple-converted-space"> </span>}<br>
                                                          <br>
                                                             <span
class="apple-converted-space"> </span>if (result != null) {<br>
                                                                  <span
class="apple-converted-space"> </span>result.requestFocus();<br>
                                                                  <span
class="apple-converted-space"> </span>traversalEvent.consume();<br>
                                                             <span
class="apple-converted-space"> </span>}<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">Note that the above
                                                          code leaves
                                                          the final
                                                          decision to
                                                          call
                                                          requestFocus
                                                          up to the
                                                          caller.  It
                                                          also allows
                                                          the caller to
                                                          distinguish
                                                          between the
                                                          case where
                                                          there is no
                                                          suitable Node
                                                          in the
                                                          indicated
                                                          direction and
                                                          act
                                                          accordingly.  <o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">This allows it
                                                          to NOT consume
                                                          the event if
                                                          it prefers its
                                                          Parent to
                                                          handle it (if
                                                          the control
                                                          doesn't want
                                                          CYCLIC or
                                                          CONFINED style
                                                          navigation). 
                                                          It also allows
                                                          it to further
                                                          scrutinize the
                                                          suggested
                                                          Node, and if
                                                          it decides it
                                                          does not like
                                                          it (due to
                                                          some property
                                                          or CSS style
                                                          or whatever)
                                                          it may follow
                                                          up with
                                                          another
                                                          findXXX call
                                                          or some other
                                                          option to pick
                                                          the Node it
                                                          wants.  It
                                                          also allows
                                                          (in the case
                                                          of no Node
                                                          being found)
                                                          to pick its
                                                          own preferred
                                                          Node in those
                                                          cases.  In
                                                          other words,
                                                          it is just far
                                                          more flexible.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">I'm not sure yet
                                                          where to place
                                                          these static
                                                          helper methods
                                                          (if we decide
                                                          to expose them
                                                          at all
                                                          initially), or
                                                          even if they
                                                          should be
                                                          static.  Given
                                                          that its first
                                                          parameter is
                                                          always a Node,
                                                          a non-static
                                                          location for
                                                          them could
                                                          simply be on
                                                          Node itself,
                                                          in which case
                                                          the calling
                                                          convention
                                                          would become
                                                          "Node result 
                                                          =
                                                          from.findTraversableUp()"
                                                          (suggested
                                                          name only)<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">> Focus
                                                          traversals
                                                          generate a new
                                                          type of event,
                                                          encapsulated
                                                          by the class
                                                          TraversalEvent
                                                          which extends
javafx.event.Event, using the event type TraversalEvent.NODE_TRAVERSED.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">What is the point of
                                                          this event? 
                                                          If you want to
                                                          know that
                                                          focus changed,
                                                          you can add a
                                                          listener to
                                                          Scene.focusOwnerProperty. 
                                                          What does it
                                                          mean if I
                                                          filter this
                                                          event?  What
                                                          if I consume
                                                          it?  I don't
                                                          think this
                                                          should be an
                                                          event at all,
                                                          unless
                                                          implemented as
                                                          I suggested
                                                          above, where
                                                          consuming/filtering/bubbling
                                                          can be used to
                                                          control how
                                                          controls will
                                                          react to
                                                          navigation
                                                          events.<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular">--John<o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular"> <o:p></o:p></span></p>
                                                        <p><span
style="font-size:10.5pt;font-family:Optima-Regular"> <o:p></o:p></span></p>
                                                        <p
class="MsoNormal" style="margin-bottom:12.0pt"><span
style="font-size:12.0pt">On 03/09/2024 21:33, Andy Goryachev wrote:</span><o:p></o:p></p>
                                                        <blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
                                                          <div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121">Dear
                                                          fellow
                                                          developers:</span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"> </span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121">I'd
                                                          like to
                                                          propose the
                                                          public focus
                                                          traversal API:</span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"> </span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"><a
href="https://urldefense.com/v3/__https:/github.com/andy-goryachev-oracle/Test/blob/main/doc/FocusTraversal/FocusTraversal.md__;!!ACWV5N9M2RV99hQ!LnjDXwUbbEymf9b1gkZFia8vuewsVJy6_49It-IKw66U9mS78PjdIPotBpc7AXlSfY7N5xcRXsmcPQhOzavk4z9VkPv-$"
title="https://github.com/andy-goryachev-oracle/Test/blob/main/doc/FocusTraversal/FocusTraversal.md"
moz-do-not-send="true"><span style="color:#0078D7">https://github.com/andy-goryachev-oracle/Test/blob/main/doc/<span
class="outlook-search-highlight">Focus</span>Traversal/<span
class="outlook-search-highlight">Focus</span>Traversal.md</span></a></span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"> </span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121">Draft
                                                          PR:</span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"> </span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"><a
href="https://urldefense.com/v3/__https:/github.com/openjdk/jfx/pull/1555__;!!ACWV5N9M2RV99hQ!LnjDXwUbbEymf9b1gkZFia8vuewsVJy6_49It-IKw66U9mS78PjdIPotBpc7AXlSfY7N5xcRXsmcPQhOzavk49fH_P2p$"
moz-do-not-send="true"><span style="color:#467886">https://github.com/openjdk/jfx/pull/1555</span></a></span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"> </span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121">Your
                                                          comments and
                                                          suggestions
                                                          will be warmly
                                                          accepted and
                                                          appreciated.</span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"> </span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121">Thank
                                                          you</span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121"> </span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          <div>
                                                          <div>
                                                          <p
class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed SS16";color:#212121">-andy</span><o:p></o:p></p>
                                                          </div>
                                                          </div>
                                                          </div>
                                                        </blockquote>
                                                      </div>
                                                    </div>
                                                  </div>
                                                </div>
                                              </blockquote>
                                            </div>
                                          </div>
                                        </div>
                                      </div>
                                    </blockquote>
                                  </div>
                                </blockquote>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </blockquote>
              </div>
              <p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>