FX Experience Has Gone Read-Only

I've been maintaining FX Experience for a really long time now, and I love hearing from people who enjoy my weekly links roundup. One thing I've noticed recently is that maintaining two sites (FX Experience and JonathanGiles.net) takes more time than ideal, and splits the audience up. Therefore, FX Experience will become read-only for new blog posts, but weekly posts will continue to be published on JonathanGiles.net. If you follow @FXExperience on Twitter, I suggest you also follow @JonathanGiles. This is not the end - just a consolidation of my online presence to make my life a little easier!

tl;dr: Follow me on Twitter and check for the latest news on JonathanGiles.net.

While Jasper is on vacation I thought I’d take a moment and outline the multi-level architectural approach we’ve taken with skinning Controls, and give some rough outline as to when the different levels will be fully supported in JavaFX.

There are basically three different levels of support for skinning in JavaFX.

Levels of Skinning

Levels of Skinning

At the most basic level, which is also the most powerful and flexible, you have the ability to completely replace the Skin for any Control. The Skin is responsible for the entire visual appearance and, ultimately, the visual interaction for a Control. There are not explicit “ButtonSkin” or “RadioButtonSkin” or “ListViewSkin” types that must be extended. There are simply Skins. So for example, you could completely replace the Skin for a Button using your own implementation that, for instance, simply used an image for the button.

While it is the most powerful mechanism for skinning a Control, it is also the most tedious as there are many details to pay attention to, such as overriding the functions to provide meaningful preferred size information for the Control with this Skin, wiring everything up to the model information in the Control, and handling all the mouse input and preferably forwarding the input on to a Behavior (which you also must providing in JavaFX 1.2 since the skin and behavior implementations for our default look, Caspian, have not been made public in this release).

The next level up restricts a bit what you can do, but also makes it a lot easier to style. This is to use the JavaFX Production Suite to produce skins for your Controls. As of the time of this writing, this support is still in prototype form (Martin Brehovsky demo’d this at JavaOne and it is definitely something I’d like to see released this year, but we’ll see how the schedules work out). The basic idea is pretty simple: the tool would provide its own basic Skin base classes. Vector or Image artwork produced by Illustrator or Photoshop and exported via the Production Suite could then get wired up on top of these Skin base classes to form a complete Skin for a Control.

There are several great things about this approach. First, visual designers can create nice graphics and use these directly. We lowly developer types don’t have to worry about taking a designer’s design and replicating it in code (which is good, ’cause mostly we’re lousy at it). Also, it opens up the opportunity to allow your company to contract out to designers and have them produce skins. It also allows designers to create suites of prebuilt custom skins fairly easily and sell these “themes” for the basic controls. Creating custom skins for custom controls is likewise also not terribly difficult for a designer.

However, as mentioned above, this isn’t released yet, so for the moment you would have to manually wire up the output of an FXD file to the skins. This is actually not very difficult, and could be achieved in a matter of an hour or so by somebody skilled at writing skins.

The third approach is to use CSS for styling the Controls. This is by far the most accessible method and, hopefully, will accommodate the 60-80% use case of simply wanting to style the prebuilt skins. In the 1.2 release, styling Controls with CSS is only just supported. In the next release we’ll both document and declare “stable” the attributes which can be styled from CSS. We’re pretty excited about the range of options we’re going to support, because our hope is that we’ll be able to address the vast majority of uses with just simple CSS.

And remember in JavaFX, CSS attributes can be specified in stylesheets, or directly on Nodes in the scenegraph by specifying the “style” property, much like in HTML. This makes it really easy to style a specific Control (which is a Node in the scenegraph) directly, or indirectly in a stylesheet.

In CSS you can easily specify attributes for a Control when it is in different states. For example, you can specify the a Button should have a base color of “red”, and a Button which has the mouse over it (hover) is “blue”. This is done by specifying the base and/or accent Color in CSS like this:

Button {
    style: "base: red"
    text: "Red Button"
}

There are a whole host of additional attributes which we’d like to expose in the next release, such as cornerRadius, padding, margins, shadowFill, textFill, and so forth (actually, I think we have committed to textFill already, I’ll let Jasper verify). One idea we’ve been kicking around is that of having a TexturePaint where, from CSS, you could specify an image file and also a set of insets and then we’d do the 9-square resizing technique for you. This would make it trivial then to build skins from CSS based on either Colors, Gradients, or Images. If we then expose some information for animations so you could control simple animation transitions from CSS too, then CSS becomes a very compelling proposition.

I hope this outline helps understand a bit better where we are now, and where we’re headed in the next release. Today, the best supported option is to create completely custom Skins. The second best option is to do some basic styling from CSS. In a few months time we plan to release complete CSS customizability which will give probably 80% use case coverage. We should also have basic support in the Production Suite to produce skins for Controls (though there may be some hand coding involved, we’ll try to make it pretty trivial).