<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix">On 27/11/2023 23:02, Andy Goryachev
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:DM5PR1001MB217263FF08CAB0A8BD8155C5E5BDA@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
        {font-family:"Iosevka Fixed SS16";
        panose-1:2 0 5 9 3 0 0 0 0 4;}@font-face
        {font-family:"Times New Roman \(Body CS\)";
        panose-1:2 11 6 4 2 2 2 2 2 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Iosevka Fixed SS16";
        color:windowtext;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}div.WordSection1
        {page:WordSection1;}</style>
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Dear John:<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Thank you for further development of this idea,
            especially defining the separation between Control, Skin,
            and Behavior.<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"">Do I read correctly that semantic events are
            currently off the table?  Or, at least, either an
            implementation detail or some future enhancement?</span></p>
      </div>
    </blockquote>
    <p>I think for a first public Behavior API semantic events are not a
      requirement.  They were earlier a requirement because we
      envisioned Skins generating semantic events to communicate with
      Behaviors (in order to cut the Skin <-> Behavior
      dependency), but as that has been solved differently, these events
      are not in a first iteration.</p>
    <p>Semantic events would still have value I think as an indirection
      between KeyBinding and its function (see document), unless we go
      the FunctionTag route here.<br>
    </p>
    <blockquote type="cite"
cite="mid:DM5PR1001MB217263FF08CAB0A8BD8155C5E5BDA@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">I also have a few comments in regards to the
            strict rules e.g. “C. never modifies its own publicly
            writable properties” and the reasoning behind those, but
            that deserves a separate email.</span></p>
      </div>
    </blockquote>
    <p>Perhaps I worded this too strict.  The idea is simply that
      Controls should not make unexpected changes to their writable
      properties as the user must appear to be in control at all times.
      So changing a writable property in response to some (user)
      triggered action (like calling "Button#arm" results in the armed
      property changing) is fine.  <br>
    </p>
    <blockquote type="cite"
cite="mid:DM5PR1001MB217263FF08CAB0A8BD8155C5E5BDA@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">For now, I just want to note that
            BehaviorContext looks suspiciously like an InputMap (a
            skin/behavior InputMap), </span></p>
      </div>
    </blockquote>
    <p>But it isn't an InputMap, I explained clearly what its purpose
      is, to isolate the changes that Behaviors makes so Control can
      remain in control, not only for when the event handlers are called
      (and at what priority) but also at uninstallation time.  Behaviors
      being a public API means that users can start doing crazy things,
      and it would serve us to as much as possible restrict those crazy
      things to a confined space, hence BehaviorContext offering limited
      options to interact with the Control during Behavior installation.</p>
    <p>This is pretty standard practice when designing user facing
      API's: don't offer the user options they should not be using, as
      you'll regret it later when users inevitably don't follow the
      rules that you set out.  Also remember that the Behavior
      implementor may be a different developer than the developer using
      a Control.  The developer using the Control should have some
      confidence that the act of installing a 3rd party Behavior will
      not adversely affect the Control, and that confidence can be
      severely boosted if the Behavior has limited access.<br>
    </p>
    <p>It indeed also happens to be a good place to offer KeyBinding
      based methods so Behaviors are easy to construct (and again so
      Control can track changes) does not make that an input map; it may
      *delegate* to some internal (or perhaps later public) input map
      though.</p>
    <p>I've done a concession here to the API to allow for KeyBindings
      so that Behaviors can clearly separate a generic KEY_PRESSED
      handler (which you could never remap to do anything else) from
      things that might be remappable later.<br>
    </p>
    <blockquote type="cite"
cite="mid:DM5PR1001MB217263FF08CAB0A8BD8155C5E5BDA@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">and the fact that you invent a State class
            indicates that, at least in this example, we are dealing
            with a stateful behavior.  In other words, why not have a
            BehaviorBase?</span><br>
        </p>
      </div>
    </blockquote>
    <span style="font-size:11.0pt;font-family:"Iosevka Fixed
      SS16""><o:p> </o:p></span>
    <blockquote type="cite"
cite="mid:DM5PR1001MB217263FF08CAB0A8BD8155C5E5BDA@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">So the only case where we might have a stateless
            behavior and thus save a few bytes by using a singleton key
            map is where the control either has no state, or the state
            is fully encapsulated within control’s properties.  I agree
            we should support those (rare?) cases should developers want
            it.</span></p>
      </div>
    </blockquote>
    <p>I think you sort of answered yourself here. However there is IMHO
      a far more compelling reason:<br>
    </p>
    <p>Ease of use. Behaviors can be constants like Colors and Borders.
      There are no checks and balances that need to be done when calling
      Control#setBehavior() -- it just always works, just like setting a
      color would (no ColorAlreadyInUseException :)).  <br>
    </p>
    <p>A Behavior does not get "used up" when installed, instead it is
      "applied", like a Color.  The only reason for the complicated
      construction / install procedure of Skins (and a BehaviorBase
      solution) is an internal one: some state needed to be tracked, and
      unfortunately this internal reason has leaked to be part of public
      API.  From the outside it could and should have worked like a
      Color or Paint, fully reusable.</p>
    <p>The intent never was to save a few bytes (at least not in this
      part).  Of course I did recognize pretty early on that the current
      internal Behavior implementation is wasteful (duplicating about 25
      kB in KeyBindings and mutable InputMaps per TextField instance
      which are exactly the same), and that the Control reference can be
      gleaned from the callbacks (so callbacks can also be fully
      deduplicated).  This last part I haven't yet fully incorporated,
      as it is a balance to strike between ease of use (getting a
      Control reference passed to the Behavior directly for easy access)
      and saving memory (making the callback reusable by extracting the
      Control from the Event).  Given that most handlers will be
      KeyBindings, which are lighter weight, it may not be worth it to
      deduplicate the few extra handlers that deal with the mouse or
      need special key handling.</p>
    <blockquote type="cite"
cite="mid:DM5PR1001MB217263FF08CAB0A8BD8155C5E5BDA@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">What I am getting at here is that if we provide
            an InputMap and a SkinInputMap instead, then we can have the
            freedom to implement stateful and stateless behaviors as
            well as provide key mapping functionality as well as the
            prioritization of event handlers (if registered via the
            input maps).</span></p>
      </div>
    </blockquote>
    <p>I don't quite understand how you would want to do this, and also,
      isn't a SkinInputMap a contradiction?  Skins are about visuals,
      input is about behavior.</p>
    <p>The way I see it currently:</p>
    <p>1. InputMaps would make sense to live at Control level; the user
      can examine it, and make overrides.  The API is limited enough to
      allow these InputMaps to be deduplicated.  I would not expose it
      as a MapProperty or anything like that, or offer any kind of
      bindings/listeners/interceptors, certainly not initially.</p>
    <p>2. Behaviors provide standard mappings.  Going through
      BehaviorContext leaves all options open for Control to incorporate
      this into a "final" input map, taking user overrides into
      account.  By not allowing direct modification of the input map by
      Behaviors, Controls can also ensure they know exactly what the
      Behavior did so it can be cleanly uninstalled.<br>
    </p>
    <p>3. Event handler priority (or my alternative) should not be up to
      Behaviors. A Behavior always has the lowest priority, so that a
      user handler can always override what a behavior is doing. 
      BehaviorContext indirection enforces this, as the Control decides
      how to "install" those handlers, and well behaved controls will
      install them with the lowest priority, and in such a way that they
      never conflict with what the user wants to do.</p>
    <p>4. About event handler priorities as API: There is no real point
      in allowing users to install event handlers with a lower priority
      than Behavior handlers, as such handlers would have no use cases
      (they either always work or never work depending on the behavior,
      if you want it to always work, just install it at a higher
      priority, if you want it to never work... well, don't install
      it).  This is also the reason why I prefer not using handler
      priorities as part of the API -- I think it just complicates
      things for the user, and there is no compelling reason for it to
      ever work other than "Users first, Behaviors last".</p>
    <p>Using handler priorities to solve "internal" ordering of handlers
      is not needed (we've lived without it so far); internal problems
      can be solved by installing handlers in the correct order, or not
      installing two different handlers for the same event in the first
      place.<br>
    </p>
    --John<span style="font-size:11.0pt"><br>
      <o:p></o:p></span>
    <blockquote type="cite"
cite="mid:DM5PR1001MB217263FF08CAB0A8BD8155C5E5BDA@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <div id="mail-editor-reference-message-container">
          <div>
            <div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>