Apache Trinidad - A World Cup Skinning Experience?

One of the 2006 Soccer World Cup highlights must surely be the Trinidad and Tobago versus Sweden game. The underdogs Trinidad and Tobago managed to push off the onslaught from the Swedish team. The game ended 0-0, which was for the people of Trinidad and Tobago a divine experience - their teams very first World Cup point!

So, you are, of course, asking yourself: What are these guys talking about? The question you should ask yourself is: Is Trinidad and Tobago going to be a success in the Java EE world as well? With the addition of project Trinidad to the Apache MyFaces community, the MyFaces project can now offer a rich and powerful component solution Trinidad and Tobago (and not to forget the original Tomahawk library). Project Tobago is a donation from Atanion GmbH (www.atanion.com) and, as a project, it recently graduated from the Apache Incubator.

Project Trinidad, the largest component library of the three, is a donation from Oracle. This donation is a subset of Oracle's well-known ADF Faces component library to the Apache Software Foundation (http://incubator.apache.org/adffaces/).

What is Apache Trinidad? Apache Trinidad is the most comprehensive free JSF component library on the planet. This library contains 12 helper objects such as converters and validators, and a staggering 93 components ranging from simple input components to complete page components with built-in menu model support. In addition, Apache Trinidad provides a set of extended services such as dialog framework and skinning framework.

This is the second article in a series of articles where we will be deep diving into various aspects of Oracle's donation - Apache Trinidad - and give developers insight into its functionality and how to use and extend Apache Trinidad. In our first article we covered the HTML Ajax RenderKit provided with project Apache Trinidad (http://jdj.sys-con.com/read/232061.htm), and in this second article we are going to cover the skinning feature provided by this JSF component library.

Project Trinidad's Skinning Framework
Project Trinidad lets you change the appearance, or look and feel, of an application without having to rewrite the code that implements the application's user interface. Trinidad currently provides two parent skins, Simple and Minimal, which you can extend to provide custom skins for your applications. The Minimal skin provides some formatting and the Simple skin contains almost no special formatting. By default, a custom skin inherits the appearance of its parent look and feel. When you wish to modify the appearance of a component, you simply provide custom style definitions and custom icons.

About the Trinidad Skins
A skin in project Trinidad is a global style sheet that only needs to be set in one place for the entire application. Instead of having to style each component, or having to insert a style sheet on each page, you can create one skin for the entire application. Every component will automatically use the styles as described by the skin. Any changes to the skin will be picked up at runtime; no change to the code is needed. Skins are based on the Cascading Style Sheet specification, and are using CSS 3.0 syntax.

In addition to using a CSS file to determine the styles, skins also use a resource bundle to determine the text. For example, the words "Previous" and "Next" in the navigation bar of the Project Trinidad's table component are determined using the skin's resource bundle. All the included skins use the same resource bundle. In this article, we are not going to cover the use of resource bundles.

Creating a Custom Skin
You create a custom skin by extending the Simple skin and overriding the provided selectors. There are three different levels of selectors: Global, Button, and Component.

  1. .AFButtonStartIcon:alias
  2. .AFButtonEndIcon:alias
  3. .AFButtonTopBackgroundIcon:alias
  4. .AFButtonBottomBackgroundIcon:alias
When these four icons are specified, Project Trinidad combines the images specified by these icons into a single button image. (Note: These icons must be specified using either context-image or resource-image icons. Text-based icons are not allowed.)

To Create a Custom Skin
In most cases you will probably not customize the skin of every component available in project Trinidad's component library (there are after all 84 UI components). By reviewing your application using, for example, the Simple skin, you can determine what components to customize.

Note: At the moment the application developer can only extend, and inherit from, the Simple skin, but there is progress in the Apache Trinidad community to improve this, so that a skin can inherit from any custom skin. A skin consists of the following artifacts:

Modifying the Trinidad Skin CSS
We are going to use an application that mimics the Apache MyFaces Website, so that we can illustrate how the skinning feature works and compare with the original (see Figure 1).

The hard part of providing a skin is not the actual creation of the Trinidad artifacts; it is creating the actual graphics and styles to be used by the application that is tedious. In this case we already have the above page as a foundation for the look and feel, which contains the styles and images needed. In the skin CSS file you can add any selectors that you wish to override, and set the properties as needed. You can set any properties as supported by the CSS specification. You can also create your own alias classes.

The application we have built is a standard JSF application using the Apache Trinidad's components with the Minimal skin (see Figure 2).

Changing the Color Scheme of a Skin
The easiest part of changing the look of your application is to change the base classes of a skin to use other colors. For example, the Simple skin looks Figure 3 without changes, and with some very minor changes to the following alias classes:

.AFDarkForeground:alias {color:#900000;}
.AFDarkBackground:alias {background-color:#333333;}

you can change the look and feel by changing the style classes controlling the base colors of the Simple skin (see Figure 4).

Adding a Skin to a Apache Trinidad Component
The components that we are going to provide a skin for are - tr:panelHeader, tr:panelSideBar, tr:navigationPane, and tr:inputDate. We are going to start with the tr:inputDate component. At the moment the tr:inputDate component looks like this with the Minimal Look and Feel:

Image 1

but we would like to change to look like this:

Image 2

To able to do this we need to add the component selector for the tr:inputDate component. By adding the following code to the skin CSS file (in this case we have named the file trinidadSkin.css), we can change the icon of the calendar launch button. Add the following af|selectInputDate style class code snippet to CSS file (note that in CSS the order of the style classes listed in the CSS file is important).

/** inputDate launch icon **/

af|inputDate::launch-icon {
    content:url(/skins/trinidad/skin_images/timedate_ena.png);
    width: 16px;
    height: 16px;
}
af|inputDate::launch-icon:rtl {
    content:url(/skins/trinidad/skin_images/timedate_ena.png);
    width: 16px;
    height: 16px;
}


Notice that the Apache Trinidad skinning feature provides bi-directional support, causing the duplication of the style class name with an additional :rtl suffix to provide "right to left" style information in the second style class. It is also important that you add width and height to any style using images/icons, since some browsers, such as Internet Explorer, might have problems displaying the actual icons. Next we are going to look at the Apache Trinidad's tr:navigationPane control. This component is slightly more complex than the tr:inputDate component with more controls and attributes that can be adjusted. The default look and feel for this to control is shown in Figure 5.

We are going to add Listing 1 just below the inputDate styles in our trinidadSkin.css file.

By using the alias class - AFTabBarItem:alias - we can add a set of styles to the skin that are generic to all navigationPane controls. We have also added styles that are unique to all navigationPane link controls by using the component-specific selector.

We are not going to bore you with too much repetitive code, so to finish off the CSS bit of our new skin we are going to look at how you can apply a slightly different style to a nested component compared to how it would look outside its parent component. In this sample we have a panelHeader component that has the following skin setting:

/** panelHeader **/
/** ----------- **/
af|panelHeader
{
    padding: 4px 4px 4px 6px;
    background-color: #DDDDDD;
    border: 1px solid #999999;
    vertical-align: middle;
}

af|panelHeader::level-one
{
    color: #900000;
    font-weight:bold;
    font-size: x-large;
}

af|panelHeader::level-two
{
    color: #333333;
    background-color: #EEEEEE;
    border: 1px solid #AAAAAA;
    font-weight:bold;
    font-size: large;
}

At runtime this will translate to H1, H2 equivalents, which will look like the Welcome note and the release announcement.

This is fine as long as you don't use this panelHeader component anywhere else, say nested within a panelSideBar component. In that case the styles will be too overwhelming, but there is a very simple standard CSS solution:

af|panelSideBar af|panelHeader
{
    font-size: smaller;
    border-left: 0px;
    border-right: 0px;
    border-top: 0px;
    border-bottom: 1px solid #AAAAAA;
    background-color: #F0F0F0;
    padding-top: 2px;
    padding-left: 9px;
    color: #49635a;
}

In this code sample we have defined that any panelHeader within a panelSideBar should have a different style.

Setup of a Custom Skin
Let's now have a look at how to set up your application to use an Apache Trinidad custom skin. First of all, we need the CSS file, stored somewhere at the root of our Web application. In our sample application, it's stored in the /skin/trinidad directory. We should also make sure that we have access to all resources needed for the skin, such as images and other CSS files. For our application, these are stored in the /skin/trinidad/images directory.

Second, we need to make sure that our Apache Trinidad application is aware of the custom skin. This is done by adding a configuration file to the WEB-INF directory called trinidad-skins.xml (the name of the file is a leftover from the Oracle donation and will soon be renamed to comply with the Apache Trinidad's naming conventions). The content of our trinidad-skins.xml file looks like Listing 2.

Register a Custom Skin
The <id> element in the trinidad-skins.xml can be used to reference a skin in an EL expression. For example, if you want to have different skins for different locals, you can create an EL expression that will select the correct skin based on its ID.

The <family> element configures an application to use a particular family of skins. This allows you to group skins together for an application, based on the render kit used.

The <render-kit-id> determines which render-kit to use for the skin. You can enter one of the following:

The <style-sheet-name> element defines the path to the custom CSS file.

Configuring an Application to Use a Custom Skin
When you have created a skin and are ready to use it, you need to make your application aware of it by defining which skin to use in the trinidad-config.xml file. You set an element in the trinidad-config.xml file that determines which skin to use, and, if necessary, under what conditions.

<?xml version="1.0" encoding="windows-1252"?>
< trinidad-config xmlns="http://myfaces.apache.org/trinidad">

<skin-family>#{sessionScope.skinFamily == null ? "minimal" : sessionScope.skinFamily }</skin-family>

<debug-output>true</debug-output>

</ trinidad-config>
If you only have one skin for your application, you only need to replace the <skin-family> value with the family name for the skin(s) you wish to use.

<skin-family>trinidad</skin-family>

To conditionally set the skin-family value, you can enter an EL expression that can be evaluated to determine the skin to display. For example, if you want to use the German skin if the user's browser is set to the German locale, and use the English skin otherwise, you could have the following entry in the adf-faces-config.xml file.

<skin-family>#{facesContext.viewRoot.locale.language=='de' ? 'german' : 'english'}</skin-family>

In our sample application, we are going to use a selectOneChoice component to switch skins at runtime. For this we need to define the following in the trinidad-config.xml file with:

<skin-family>#{sessionScope.skinFamily == null ? "minimal" : sessionScope.skinFamily }</skin-family>

The actual component that will perform the actual switching at runtime looks like this:

<tr:selectOneChoice label="Select Skin" value="#{sessionScope.skinFamily}" onchange="form.submit();">
   <tr:selectItem label="Simple" value="simple"/>
   <tr:selectItem label="Minimal" value="minimal"/>
   <tr:selectItem label="Trinidad" value="trinidad"/>
   <tr:selectItem label="MyCompany" value="mycompany"/>
</tr:selectOneChoice>

The onchange event handler will perform a form POST whenever a skin is selected in the selectOneChoice component. Alternatively, you can add a commandButton to the page that will re-submit the page. Every time there is a POST, the EL expression will be evaluated, and if there is a new value, redraw the page with the new skin. 

Summary
Creating Apache Trinidad skins are easy and using them even easier. An application developer can set a skin based on any criteria using EL expression and JSF backing beans (not shown in this article). This allows application developers to have different skins per user, page, application, and so on, without impacting the actual application logic! We should also take a note that Apache Trinidad is still in incubation as an Apache podling, thus skinning artifacts, such as style selectors discussed in this article, might change in future builds.

© 2008 SYS-CON Media