<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    Yes, but a RuntimeException only appears in the javadoc, and not in
    the method signature (only checked exceptions show up in the method
    signature).<br>
    <br>
    -- Kevin<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 7/22/2022 2:39 PM, Andy Goryachev
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:BL0PR10MB29486E7A6987A0D0C2B659FEE5909@BL0PR10MB2948.namprd10.prod.outlook.com">
      
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
        {font-family:"Apple Color Emoji";
        panose-1:0 0 0 0 0 0 0 0 0 0;}@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:"Courier New \,serif";
        panose-1:2 7 3 9 2 2 5 2 4 4;}@font-face
        {font-family:"Courier New \,serif ";
        panose-1:2 7 3 9 2 2 5 2 4 4;}@font-face
        {font-family:"Courier New \,serif\;color\:black";
        panose-1:2 7 3 9 2 2 5 2 4 4;}@font-face
        {font-family:"Iosevka Fixed SS16";
        panose-1:2 0 5 9 3 0 0 0 0 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0in;
        margin-right:0in;
        margin-bottom:0in;
        margin-left:.5in;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}span.EmailStyle20
        {mso-style-type:personal-reply;
        font-family:"Courier New",serif;
        color:windowtext;}p.p1, li.p1, div.p1
        {mso-style-name:p1;
        margin:0in;
        font-size:9.0pt;
        font-family:"Iosevka Fixed SS16";}span.s1
        {mso-style-name:s1;
        color:#646464;}span.s2
        {mso-style-name:s2;
        color:#4E8F00;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}div.WordSection1
        {page:WordSection1;}ol
        {margin-bottom:0in;}ul
        {margin-bottom:0in;}</style>
      <div class="WordSection1">
        <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
            New",serif">Thank you, Phil and Kevin.<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
            New",serif"><o:p> </o:p></span></p>
        <p class="p1"><span class="s1">@Override<o:p></o:p></span></p>
        <p class="p1"><span class="s2">public</span> <span class="s2">final</span>
          <span class="s2">
            void</span> setSkin(Skin<?> value) throws
          IllegalArgumentException {<o:p></o:p></p>
        <p class="p1"><o:p> </o:p></p>
        <p class="p1"><o:p> </o:p></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
            New",serif">-andy<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
            New",serif"><o:p> </o:p></span></p>
        <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">Kevin
              Rushforth <a class="moz-txt-link-rfc2396E" href="mailto:kevin.rushforth@oracle.com"><kevin.rushforth@oracle.com></a><br>
              <b>Date: </b>Friday, 2022/07/22 at 14:20<br>
              <b>To: </b>Andy Goryachev
              <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a>, <a class="moz-txt-link-abbreviated" href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a>
              <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
              <b>Subject: </b>Re: [External] : Aw: Proposal: Add
              Skin.install() method<o:p></o:p></span></p>
        </div>
        <p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt">No, sorry. Error doesn't
            communicate the right thing. This is exactly is what
            RuntimeException is intended to be used for. It's no
            different from passing an out of range numerical value or a
            null to a method that doesn't take null. In all similar
            cases, the method will document the exception cases with
            '@throws' javadoc tags, and the developer can then
            understand that they passed something bad to the method.
            FWIW, I've never seen any Java API throw Error in this
            manner.<br>
            <br>
            -- Kevin<br>
            <br>
            <o:p></o:p></span></p>
        <div>
          <p class="MsoNormal"><span style="font-size:11.0pt">On
              7/22/2022 2:02 PM, Andy Goryachev wrote:<o:p></o:p></span></p>
        </div>
        <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif"">I do mean java.lang.Error.</span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif"">The goal is to prevent an incorrect code
              from being shipped to the end user.  There are no tools at
              the API level to enforce the 1:1 relationship, so it
              cannot be checked at compile time.  </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif"">The next best thing is to fail during the
              development, thus an Error.  It should be an error and not
              a RuntimeException because it communicates a design error,
              and not a run time, i.e. a legitimate run time condition. 
              It is also not an IllegalArgumentException because there
              should be no scenario when this could happen.</span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif"">In other words, the condition should get
              fixed by a redesign rather than by handling/ignoring an
              exception.  As stated in the Error javadoc</span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:8.5pt;font-family:"Arial",sans-serif;color:black;background:#ECEBEC">An </span><span style="font-size:8.5pt;font-family:"Courier New
              \,serif\;color\:black"">Error</span><span style="font-size:8.5pt;font-family:"Arial",sans-serif;color:black;background:#ECEBEC"> is
              a subclass of </span><span style="font-size:8.5pt;font-family:"Courier New
              \,serif\;color\:black"">Throwable</span><span style="font-size:8.5pt;font-family:"Arial",sans-serif;color:black;background:#ECEBEC"> that
              indicates
              <span style="background:yellow;mso-highlight:yellow">serious
                problems that a reasonable application should not try to
                catch</span>. Most such errors are abnormal conditions.
              The </span><span style="font-size:8.5pt;font-family:"Courier New
              \,serif\;color\:black"">ThreadDeath</span><span style="font-size:8.5pt;font-family:"Arial",sans-serif;color:black;background:#ECEBEC"> error,
              though a "normal" condition, is also a subclass of </span><span style="font-size:8.5pt;font-family:"Courier New
              \,serif\;color\:black"">Error</span><span style="font-size:8.5pt;font-family:"Arial",sans-serif;color:black;background:#ECEBEC"> because
              most applications should not try to catch it.</span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif"">if this idea seems to radical, I am ok with
              making it an IllegalArgumentException.</span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif"">-andy</span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
              \,serif""> </span><o:p></o:p></p>
          <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">Kevin
                Rushforth <a href="mailto:kevin.rushforth@oracle.com" moz-do-not-send="true">
                  <kevin.rushforth@oracle.com></a><br>
                <b>Date: </b>Friday, 2022/07/22 at 13:42<br>
                <b>To: </b>Andy Goryachev <a href="mailto:andy.goryachev@oracle.com" moz-do-not-send="true"><andy.goryachev@oracle.com></a>,
                <a href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true" class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
                <a href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true">
                  <openjfx-dev@openjdk.org></a><br>
                <b>Subject: </b>Re: [External] : Aw: Proposal: Add
                Skin.install() method</span><o:p></o:p></p>
          </div>
          <p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt">I don't know if you really meant
              Error, as in java.lang.Error, but it would need to be a
              subclass of RuntimeException. IllegalArgumentException
              seems the natural choice (a case could possibly be made
              for IllegalStateException). Throwing an Error is not the
              right thing for a library to do in response to an
              application passing in an illegal or unexpected argument
              to a method or constructor. It is for truly exceptional
              things that a programmer cannot anticipate (like running
              out of memory).<br>
              <br>
              -- Kevin<br>
              <br>
              <br>
            </span><o:p></o:p></p>
          <div>
            <p class="MsoNormal"><span style="font-size:11.0pt">On
                7/22/2022 12:37 PM, Andy Goryachev wrote:</span><o:p></o:p></p>
          </div>
          <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
            <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                \,serif "">I would rather throw an Error in
                Skinnable.setSkin() when mismatch is detected.  This is
                a design error that should be caught early in
                development rather than a run time exception.</span><o:p></o:p></p>
            <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                \,serif ""> </span><o:p></o:p></p>
            <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                \,serif "">-andy</span><o:p></o:p></p>
            <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                \,serif ""> </span><o:p></o:p></p>
            <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                \,serif ""> </span><o:p></o:p></p>
            <div style="border:none;border-top:solid #B5C4DF
              1.0pt;padding:3.0pt 0in 0in 0in">
              <p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
                  </span></b><span style="font-size:12.0pt;color:black">openjfx-dev
                  <a href="mailto:openjfx-dev-retn@openjdk.org" moz-do-not-send="true">
                    <openjfx-dev-retn@openjdk.org></a> on behalf
                  of Kevin Rushforth <a href="mailto:kevin.rushforth@oracle.com" moz-do-not-send="true">
                    <kevin.rushforth@oracle.com></a><br>
                  <b>Date: </b>Friday, 2022/07/22 at 12:33<br>
                  <b>To: </b><a href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true" class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
                  <a href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true">
                    <openjfx-dev@openjdk.org></a><br>
                  <b>Subject: </b>Re: [External] : Aw: Proposal: Add
                  Skin.install() method</span><o:p></o:p></p>
            </div>
            <p class="MsoNormal"><span style="font-size:11.0pt">I would
                not be in favor of adding a no-arg constructor to
                SkinBase, for the reasons Andy gave. Additionally, there
                would be no way to avoid braking the contract of
                Skin::getSkinnable which says:<br>
                <br>
                "This value will only ever go from a non-null to null
                value when the Skin is removed from the Skinnable, and
                only as a consequence of a call to dispose()."<br>
                <br>
                <br>
                <br>
                <br>
              </span><o:p></o:p></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif "">At the very minimum, we should explain
                  in Skin javadoc that creating a skin for one control
                  and setting it in the other is a no-no.  Or, perhaps
                  we should explicitly check for this condition in
                  setSkin().</span><o:p></o:p></p>
            </blockquote>
            <p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt"><br>
                I agree completely. At a minimum this enhancement should
                change the docs for setSkin to say that a skin created
                for one control should not (must not?) be used in
                another control. And unless there is a legitimate use
                case I haven't thought of, I think we could consider an
                explicit check, and either throw an Exception (this
                seems the best choice, unless there are compatibility
                concerns), or else log a warning and treat it as a
                no-op.<br>
                <br>
                -- Kevin<br>
                <br>
                <br>
                <br>
              </span><o:p></o:p></p>
            <div>
              <p class="MsoNormal"><span style="font-size:11.0pt">On
                  7/22/2022 9:13 AM, Andy Goryachev wrote:</span><o:p></o:p></p>
            </div>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif "">You do bring a good point!  I don't
                  know the rationale behind passing control pointer to
                  the Skin constructor. 
                </span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif "">I think Swing got it right, clearly
                  separating</span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif ""> </span><o:p></o:p></p>
              <ol style="margin-top:0in" type="1" start="1">
                <li class="MsoListParagraph" style="margin-left:0in;mso-list:l1 level1 lfo3"><span style="font-size:11.0pt;font-family:"Courier
                    New \,serif "">instantiation (using either a
                    no-arg constructor, or any other constructor that
                    does not require component pointer)</span><o:p></o:p></li>
                <li class="MsoListParagraph" style="margin-left:0in;mso-list:l1 level1 lfo3"><span style="font-size:11.0pt;font-family:"Courier
                    New \,serif "">configuration (optional step,
                    possibly widely separated in time and space)</span><o:p></o:p></li>
                <li class="MsoListParagraph" style="margin-left:0in;mso-list:l1 level1 lfo3"><span style="font-size:11.0pt;font-family:"Courier
                    New \,serif "">uninstallation of the old skin</span><o:p></o:p></li>
                <li class="MsoListParagraph" style="margin-left:0in;mso-list:l1 level1 lfo3"><span style="font-size:11.0pt;font-family:"Courier
                    New \,serif "">installation of the new skin</span><o:p></o:p></li>
              </ol>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif "">What you are proposing - moving to a
                  default constructor makes the most sense.  It comes
                  with a high price though - everyone with a custom skin
                  implementation would need to change their code.  </span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif "">At the very minimum, we should explain
                  in Skin javadoc that creating a skin for one control
                  and setting it in the other is a no-no.  Or, perhaps
                  we should explicitly check for this condition in
                  setSkin().</span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif "">Thank you</span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif "">-andy</span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New
                  \,serif ""> </span><o:p></o:p></p>
              <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">Marius Hanl <a href="mailto:mariushanl@web.de" moz-do-not-send="true">
                      <mariushanl@web.de></a><br>
                    <b>Date: </b>Friday, 2022/07/22 at 05:06<br>
                    <b>To: </b><a href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true" class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
                    <a href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true">
                      <openjfx-dev@openjdk.org></a>, Andy
                    Goryachev <a href="mailto:andy.goryachev@oracle.com" moz-do-not-send="true">
                      <andy.goryachev@oracle.com></a><br>
                    <b>Subject: </b>[External] : Aw: Proposal: Add
                    Skin.install() method</span><o:p></o:p></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:11.0pt">I
                    had a similar idea in the past and like the idea.<br>
                    Ideally, setting/switching a skin is a one step
                    process. Currently you can construct a skin for a
                    control and set it after to a different control.<br>
                    <br>
                    Your approach sounds good, if you can set a skin by
                    creating a new skin (with a default constructor) and
                    then the setSkin() method will actually trigger the
                    install process on the control (this), this will
                    work and solve the problem above. But for backward
                    compatibilty we still need to keep the skin
                    constructor with the control as parameter and think
                    about deprecating it.<br>
                    <br>
                    -- Marius</span><o:p></o:p></p>
              </div>
              <div>
                <p class="MsoNormal"><span style="font-size:11.0pt">Am
                    20.07.22, 23:40 schrieb Andy Goryachev
                    <a href="mailto:andy.goryachev@oracle.com" moz-do-not-send="true"><andy.goryachev@oracle.com></a>:</span><o:p></o:p></p>
                <blockquote style="border:none;border-left:solid #CCCCCC
                  1.0pt;padding:0in 0in 0in
6.0pt;margin-left:4.8pt;margin-top:4.8pt;margin-right:0in;margin-bottom:5.0pt">
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Hi,</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">I'd like to propose an API
                      change in Skin interface (details below).  Your
                      feedback will be greatly appreciated!</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Thank you,</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">-andy</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Summary</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">-------</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Introduce a new Skin.install()
                      method with an empty default implementation. 
                      Modify Control.setSkin(Skin) implementation to
                      invoke install() on the new skin after the old
                      skin has been removed with dispose().</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Problem</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">-------</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Presently, switching skins is
                      a two-step process: first, a new skin is
                      constructed against the target Control instance,
                      and is attached (i.s. listeners added, child nodes
                      added) to that instance in the constructor.  Then,
                      Control.setSkin() is invoked with a new skin - and
                      inside, the old skin is detached via its dispose()
                      method.  </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">This creates two problems:</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> 1. if the new skin instance
                      is discarded before setSkin(), it remains
                      attached, leaving the control in a weird state
                      with two skins attached, causing memory leaks and
                      performance degradation.</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> 2. if, in addition to adding
                      listeners and child nodes, the skin sets a
                      property, such as an event listener, or a handler,
                      it overwrites the current value irreversibly.  As
                      a result, either the old skin would not be able to
                      cleanly remove itself, or the new skin would not
                      be able to set the new values, as it does not know
                      whether it should overwrite or keep a handler
                      installed earlier (possibly by design). 
                      Unsurprisingly, this also might cause memory
                      leaks.</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">We can see the damage caused
                      by looking at
                      <a href="https://bugs.openjdk.org/browse/JDK-8241364" moz-do-not-send="true">JDK-8241364</a> </span><span style="font-size:11.0pt;font-family:"Apple
                      Color Emoji"">☂</span><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">
                      <i>Cleanup skin implementations to allow switching</i>,
                      which refers a number of bugs:</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8245145 Spinner: throws
                      IllegalArgumentException when replacing skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8245303 InputMap: memory
                      leak due to incomplete cleanup on remove mapping</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8268877
                      TextInputControlSkin: incorrect inputMethod event
                      handler after switching skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8236840 Memory leak when
                      switching ButtonSkin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8240506
                      TextFieldSkin/Behavior: misbehavior on switching
                      skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8242621 TabPane: Memory
                      leak when switching skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8244657
                      ChoiceBox/ToolBarSkin: misbehavior on switching
                      skin
                    </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8245282 Button/Combo
                      Behavior: memory leak on dispose</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8246195
                      ListViewSkin/Behavior: misbehavior on switching
                      skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8246202 ChoiceBoxSkin:
                      misbehavior on switching skin, part 2</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8246745 ListCell/Skin:
                      misbehavior on switching skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8247576 Labeled/SkinBase:
                      misbehavior on switching skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8253634 TreeCell/Skin:
                      misbehavior on switching skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8256821
                      TreeViewSkin/Behavior: misbehavior on switching
                      skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8269081 Tree/ListViewSkin:
                      must remove flow on dispose</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8273071 SeparatorSkin:
                      must remove child on dispose</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8274061
                      Tree-/TableRowSkin: misbehavior on switching skin</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8244419 TextAreaSkin:
                      throws UnsupportedOperation on dispose</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">JDK-8244531 Tests: add support
                      to identify recurring issues with controls et al</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Solution</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">--------</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">This problem does not exist in
                      e.g. Swing because the steps of instantiation,
                      uninstalling the old ComponentUI ("skin"), and
                      installing a new skin are cleanly separated. 
                      ComponentUI constructor does not alter the
                      component itself,
                      ComponentUI.uninstallUI(JComponent) cleanly
                      removes the old skin,
                      ComponentUI.installUI(JComponent) installs the new
                      skin.  We should follow the same model in javafx.</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Specifically, I'd like to
                      propose the following changes:</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> 1. Add Skin.install() with a
                      default no-op implementation.</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> 2. Clarify skin
                      creation-attachment-detachment sequence in Skin
                      and Skin.install() javadoc</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> 3. Modify
                      Control.setSkin(Skin) method (== invalidate
                      listener in skin property) to call
                      oldSkin.dispose() followed by newSkin.install()</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> 4. Many existing skins that
                      do not set properties in the corresponding control
                      may remain unchanged.  The skins that do, such as
                      TextInputControlSkin (JDK-8268877), must be
                      refactored to utilize the new install() method.  I
                      think the refactoring would simply move all the
                      code that accesses its control instance away from
                      the constructor to install().</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">Impact Analysis</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">-------------</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">The changes should be fairly
                      trivial.  Only a subset of skins needs to be
                      refactored, and the refactoring itself is trivial.
                       </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">The new API is backwards
                      compatible with the existing code, the
                      customer-developed skins can remain unchanged
                      (thanks to default implementation).  In case where
                      customers could benefit from the new API, the
                      change is trivial.</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif "">The change will require CSR as
                      it modifies a public API.</span><o:p></o:p></p>
                  <p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier
                      New \,serif ""> </span><o:p></o:p></p>
                </blockquote>
              </div>
            </blockquote>
            <p class="MsoNormal"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
          </blockquote>
          <p class="MsoNormal"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
        </blockquote>
        <p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
      </div>
    </blockquote>
    <br>
  </body>
</html>