On Jan 24, 2014, at 4:02 PM, John Hendrikx <hj...@xs4all.nl> wrote:

> I've got an update on this.
> 
> I've rewritten the code now to make use of multiple skins, and doing some 
> trickery with Factories to make them easily switchable.
> 
> The main reason I've rewritten them is because I think I will not be able to 
> provide CSS properties that are accessible if they are not specifically 
> defined on a Skin class (or Control class) -- but that may be lack of 
> understanding how CSS properties are discovered (I don't see how they could 
> get discovered if they're defined on a "delegated skin").

A control returns the CssMetaData of its skin (provided the skin extends from 
SkinBase).  Also, if a node is in the scene-graph, then CSS will "discover" it.
 
> 
> Anyway, the solution works, but I found some odd issues, for which I filed 
> two JIRA's:
> 
> https://javafx-jira.kenai.com/browse/RT-35528
> https://javafx-jira.kenai.com/browse/RT-35529
> 
> One deals with anonymously created Skins (my Skins have protected methods 
> that can be easily overriden to customize the appearance).  Unfortunately, 
> JavaFX doesn't like it when a Skin is an anonymous inner class with one or 
> more methods overriden with small customizations.  The setting of the Skin 
> itself works, it just complains about it later when a CSS pass occurs (I 
> think).

> 
> The second issue deals with something odd that I noticed when a Skin is 
> specified in CSS (with -fx-skin) and when I later override it with setSkin(). 
>  JavaFX seems to reset it back to the skin defined by CSS when a CSS pass 
> occurs.  I'm not aware of any other properties that behave like that.
> 
> All in all, it works, but it feels somewhat fragile.
> 
> --John
> 
> On 7/01/2014 17:04, Richard Bair wrote:
>> Could you write a single skin that delegates to one or more reusable skins?
>> 
>> On Jan 7, 2014, at 7:26 AM, John Hendrikx<hj...@xs4all.nl>  wrote:
>> 
>>> On 7/01/2014 14:50, Tomas Mikula wrote:
>>>> Interesting ideas. I'm wondering, do you switch skins often enough that 
>>>> you are worried about performance (and thus care about reusability of 
>>>> skins)? Because I don't see how reusability of skins saves you lines of 
>>>> code - whether the code is in the constructor or in the initialize() 
>>>> method, it is there somewhere. In my opinion, reusing objects is more 
>>>> complicated than creating fresh instances and the only justification for 
>>>> it is performance.
>>> To address your last point first, if you already are required to write a 
>>> proper dispose method, then fresh instances should be just as easy/hard to 
>>> write as reusable ones.  Everything is already in place, just rename the 
>>> constructor.  Of course, if you did not write a proper dispose method, then 
>>> your object will stick around or cause other trouble.  With fresh instances 
>>> you won't notice this so readily -- in JavaFX for example, the problem of 
>>> having objects that are no longer actively reachable through the 
>>> SceneGraph, but are still participating in Event handling (because they 
>>> registered non-weak listeners) can be a nice source of surprises.  With 
>>> reusable objects, you'll notice the bugs in your cleanup code likely the 
>>> first time you reuse it.
>>> 
>>> Anyway, for me, making Skins reusable makes them easier to use with 
>>> bindings, and it ofcourse saves creating a factory.  I see the "skin" of an 
>>> object as the same as say its background color.  There is no reason 
>>> (anymore I think) that one should be treated so differently from the other.
>>> 
>>>   private final Skin someExistingSkin = new SkinA();
>>>   private final Skin someExistingSkin2 = new SkinB();
>>> 
>>>   void changeToSquareLook() {
>>>      myControl.setSkin(someExistingSkin);
>>>   }
>>> 
>>>   void changeToRoundLook() {
>>>      myControl.setSkin(someExistingSkin2);
>>>   }
>>> 
>>> vs.
>>> 
>>>  private final SkinFactory skinFactory = new SkinFactory() {
>>>     public Skin createSkin(Control control) {
>>>         return new SkinA(control);
>>>     }
>>>  };
>>> 
>>>  private final SkinFactory skinFactory2 = new SkinFactory() {
>>>     public Skin createSkin(Control control) {
>>>         return new SkinB(control);
>>>     }
>>>  };
>>> 
>>>  void changeToSquareLook() {
>>>     myControl.setSkin(skinFactory.createSkin(myControl));
>>>  }
>>> 
>>>   void changeToRoundLook() {
>>>     myControl.setSkin(skinFactory2.createSkin(myControl));
>>>   }
>>> 
>>> It's not really about performance, but ease of use.  The binding case 
>>> requires a ChangeListener instead of just bind().
>>> 
>>>> I agree with you on the problem of separation of skin initialization from 
>>>> setSkin(). Another way to address this could be deprecating the original 
>>>> setSkin() method and introducing
>>>> 
>>>>    setSkin(SkinProvider<C>  skinProvider);
>>>> 
>>>> where SkinProvider is a SAM interface and thus the above method could be 
>>>> called like this:
>>>> 
>>>>    setSkin(control ->  new MySkin(control));
>>>> 
>>>> I know this defeats reusability of skins altogether, so you (and others) 
>>>> may disagree.
>>> Maybe if there was a "skinProviderProperty"... then I could bind to that 
>>> atleast.  Still introduces lots of factories (or functions).
>>> 
>>> --John
>>> 
> 

Reply via email to