Industry Commentary
Apache Trinidad - A World Cup Skinning Experience?
A global style sheet that only has to be set in one place for the entire application
Sep. 24, 2006 05:00 PM
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:
- org.apache.myfaces.trinidad.desktop: the skin will automatically be used when the application is rendered on a desktop.
- org.apache.myfaces.trinidad.pda: the skin will be used when rendered on a PDA.
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.
About Jonas JacobiJonas Jacobi is co-founder and chief executive officer of Kaazing Corporation. A native of Sweden, Jacobi has worked in the software industry for more than 15 years with a mission to simplify application development. Prior to founding Kaazing, he worked for Oracle for eight years as a Java EE evangelist and product manager responsible for the product management of JavaServer Faces, Oracle ADF Faces, and Oracle ADF Faces Rich Client in the Oracle JDeveloper team. As co-founder and CEO of Kaazing, Jonas sets the company's business and product strategy and oversees all aspects of Kaazing's operations and mission to become the world-wide leader in real-time software. He is co-author of the best-selling book, "Pro JSF and Ajax: Building Rich Internet Components," (Apress).
About John FallowsJohn Fallows is a pioneer in the field of rich and highly interactive user interfaces and co-founder of Kaazing Corporation. He recently worked as Architect at Brane Corporation, a startup company based in Redwood City, California. Originally from Northern Ireland, Mr. Fallows graduated from Cambridge University in the United Kingdom and has worked in the software industry for more than ten years. Prior to joining Brane, Mr. Fallows was a Consulting Member of Technical Staff for Server Technologies at Oracle Corporation. During his last 5 years at Oracle, Mr. Fallows focused on designing, developing, and evolving Oracle ADF Faces to fully integrate Ajax technologies. Mr. Fallows has written several articles for leading IT magazines such as Java Developer's Journal, AjaxWorld Magazine, and JavaMagazine (DE), and is a popular speaker at international conferences. Mr. Fallows is co-author of the recently published book Pro JSF and Ajax: Building Rich Internet Components, (Apress). In his role as chief technology officer, Mr. Fallows formulates the Kaazing Corporation's vision of creating the best real-time Web framework based on the Java standard. He defines the architecture of the Kaazing product suite and oversees its development.