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 >>> >