Developing and Using ADF Faces Skins

Created by Jonas Jacobi, Oracle Corporation
January, 2006

Introduction to the The ADF Faces Skinning Feature

ADF Faces 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. ADF Faces provides two parent skins, Simple and Minimal, which you can extend to provide custom skins for your applications. 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, custom icons.

This HowTo demonstrates how to create a simple ADF Faces skin, that replaces the default Oracle skin, with Oracle JDeveloper 10.1.3. For more information and HowTos, please, refer to the JDeveloper HowTo documents on Oracle Technology Network (OTN). For this simple application we are using only using ADF Faces components, and no business logic.

Tasks

This article covers the following tasks:

  • Create a new Style sheet (CSS 3.0 syntax) that overrides the simple theme style sheet.
  • Create a new ADF Faces skin configuration file - adf-faces-skins.xml
  • Adding images where needed
  • Change text on specific components
  • Set the new ADF Faces skin in the adf-faces-config.xml file

Prerequisites

There are no specific editor requirements to follow this HowTo and build this new ADF Faces Skin, but for educational purposes we are going to use the Oracle JDeveloper 10.1.3 EA1 release - optionally you may need an image editor if you want to edit and replace images provided by this HowTo. You also need to download the sample WAR file - adffaces_skin.war - that contains a newer version of ADF Faces needed for this How To, and a simple JSF page with some ADF Faces components that we will use to illustrate the effect of the new skin.

ADF Faces Default Skins

ADF Faces provides three main skins that are provided for you to use "as is" in your applications - Oracle (oracle), Minimal (minimal), and Simple (simple). The default skin for your application is set to "oracle", which conform to Oracle's UI standards (Browser Look and Feel - BLAF) for applications. The Minimal skin provides some formatting and the Simple skin contains almost no special formatting.

About Skins

A skin in ADF Faces 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 code is needed. Skins are based on the Cascading Style Sheet specification, and is 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 ADF Faces table component, is determined using the skin�s resource bundle. All the included skins use the same resource bundle.

Creating a Custom Skin

You create a custom skin by extending the Simple skin and overriding the provided selectors. There are three different types of selectors - Global, Button, and Component-level selectors.

  • Global Style selectors are selectors that affect more than one component. If the selector name ends in the :alias pseudo-class, then the selector is most likely included in other component-specific selectors. Defining properties for a selector that ends in :alias will most likely affect the skin for more than one component.
     
  • Component-level selectors are selectors that can be used to skin a particular ADF Faces component. The selectors defined below are specified by the component they affect. Let's say you want to skin the af:chooseDate component. One of the selectors is af|chooseDate::title. The ::title pseudo-element indicates that this is the title portion of the af:chooseDate component. If you want to skin the title of the af:chooseDate component, you would set css properties on the af|chooseDate::title selector in your ADF Faces skin .css file.

    You may see selector names that end in :alias in the component-level section. These are meant to provide short-cuts to skin more than one component that share a certain style or icon, or to skin more than one piece of a component. For example, the .AFMenuBarItem:alias style defines skin properties that are shared by all af:menuBar items. This is included by the af|menuBar::enabled and af|menuBar::selected style classes. Therefore, if you change the .AFMenuBarItem:alias style, you will affect the af|menuBar::enabled and af|menuBar::selected style selectors.
     
  • ADF Faces does not currently support component-level selectors for buttons. For example, you cannot customize a goButton differently from a commandButton. Skinning supports two very different button implementations. By default, standard browser buttons are used. However, the skinning also supports dynamic generation of image-based buttons. In order to enable image-based buttons, the following four button icon must be specified:

    1. .AFButtonStartIcon:alias
    2. .AFButtonEndIcon:alias
    3. .AFButtonTopBackgroundIcon:alias
    4. .AFButtonBottomBackgroundIcon:alias

    When these four icons are specified, ADF Faces 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 the ADF Faces 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 application developer can only extend the Simple skin.

If you have not downloaded Oracle JDeveloper 10.1.3 EA 1 release, yet, it is now time to do so. Unzip and launch JDeveloper.

  1. In JDeveloper, create a new Application workspace and name it - ADFFaces_skin_sample. Cancel the dialog asking to create a new project.
  2. Right click on the new Application workspace and create a new "Project from WAR file" and click OK.



     
  3. Enter view as the new name for this project and click Next.
  4. In the dialog for selecting a WAR file, select the adffaces_skin.war file you just downloaded. Click FINISH to close the dialog.
  5. Before we can view the sample page in the visual editor we first have to make sure that the ADF Faces libraries shipped with the WAR file is executed in the Visual Editor. Double click on the view project node to open the Project Properties dialog.
  6. In the Project Properties dialog select the JSP Tag Libraries and make sure that the "Execute Tags in JSP Visual Editor" option is checked on both ADF Faces libraries.



     
  7. IMPORTANT: You also need to add the JSF Core and JSF HTML tag libraries as shown in the above figure.
  8. Close the dialog by click OK.
  9. Locate the sample.jspx and open it in the visual editor.
  10. Acquaint yourself with the page to understand what is there in form of ADF Faces components.
  11. Make sure that you also look at the files provided for this skin sample application.

Figure 1. Screenshot of the sample.jspx page as shown in JDeveloper 10.1.3

A skin consists of the following artifacts:

  • A CSS file that defines the actual look of the components
  • A configuration file - adf-faces-skins.xml - that lists all skins available for this application (not including Oracle, Minimal, and Simple). This file has to be located in your applications WEB-INF directory
  • An entry in the ADF Faces configuration file - adf-faces-config.xml
  • Any other resources need to create the actual look of the componets - additional CSS files, Images etc...

Modifying the ADF Faces Skin CSS

The sample application already contains a pre-canned CSS file that we are going to use and extend in order to create the look and feel we need for our components. To this file you can add any selectors that you wish to override to your CSS file, 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 sample application also contains an adf-faces-skins-doc.xml file. This file contains information about all style classes and selctors that are provided by ADF Faces and that you can override. The file is located in the skins directory.

Figure 2. The adf-faces-skins-doc.xml file located in the skins directory

Changing the Color Schema 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 like this without changes:

and with some very minor changes to the following alias classes:

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

you can change the look and feel by changing the style classes controlling the base colors of the Simple skin:

Adding a Skin to an ADF Faces Component

The components that we are going to provide a skin for are - af:selectOneShuttle, af:selectManyShuttle, and af:selectInputDate. We are going to start with the af:selectInputDate component. At the moment the af:selectInputDate component looks like this with the Oracle Look and Feel:

but we would like to change to look like this:

To able to do this we need to add the component selector for the af:selectInputDate component. By adding the following code sample to the myComponent.css file we can change the icon of the Calendar launch button.

  1. Open the myCompanySkin.css file by double clicking on it. This will bring up the JDeveloper CSS editor.
  2. Search for the section at the top of the myCompany.css file that starts with the following:

    /** Section where to add styles/selectors used in the ADF Faces Skin Sample **/ /** ======================================================================= **/
     
  3. Add the following selectInputDate style class code snippet to just below the comment

    /** selectInputDate launch icon **/

    af|selectInputDate::launch-icon {
      content:url(/skins/mycompany/skin_images/timedate_ena.png);
    }
    af|selectInputDate::launch-icon:rtl {
      content:url(/skins/mycompany/skin_images/timedate_ena.png);
    }
     
  4. Save your changes.
     

Next we are going to look at the ADF Faces shuttle control. There are two shuttle controls available in ADF Faces - af:selectOneShuttle and af:selectOneShuttle. You can adjust the skin for each one of them or create one skin for both. This component is slightly more complex than the af:selectInputDate component with more controls and attributes that can be adjusted. The default look and feel for these to controls is this:

and we are going to change it to:

  1. In the myCompany.css file add the following code snippet just below the selectInputDate styles

    /** Shuttle icons selectOne, selectMany, and selectOrder shuttles**/
    .AFShuttleMoveIcon:alias {content:url(/skins/mycompany/skin_images/move.png); width: 16px; height: 16px;}
    .AFShuttleMoveAllIcon:alias {content:url(/skins/mycompany/skin_images/moveAll.png); width: 16px; height: 16px;}
    .AFShuttleRemoveIcon:alias {content:url(/skins/mycompany/skin_images/remove.png); width: 16px; height: 16px;}
    .AFShuttleRemoveAllIcon:alias {content:url(/skins/mycompany/skin_images/removeAll.png); width: 16px; height: 16px;}

    /** Icons unique to the selectOrderShuttle for re-ordering user selections **/
    af|selectOrderShuttle::reorder-top-icon {
    content:url(/skins/mycompany/skin_images/reordertop_enabled.png);
    width: 16px;
    height: 16px;
    }
    af|selectOrderShuttle::reorder-up-icon {
    content:url(/skins/mycompany/skin_images/reorderup_enabled.png);
    width: 16px;
    height: 16px;
    }
    af|selectOrderShuttle::reorder-down-icon {
    content:url(/skins/mycompany/skin_images/reorderdown_enabled.png);
    width: 16px;
    height: 16px;
    }
    af|selectOrderShuttle::reorder-bottom-icon {
    content:url(/skins/mycompany/skin_images/reorderbottom_enabled.png);
    width: 16px;
    height: 16px;}
     
  2. Save your work.

By using the alias class of the shuttle controls we can add a set of icons to the skin that are generic to all shuttle controls. We have also added icons that are unique to the selectOrderShuttle control by using the component specific selector. It is important that you add width and height to any style using images/icons, since some browser might have problems displaying the actual icons, for example Internet Explorer.

Note: There is a bug in ADF Faces that will break the image/icons in case you add "" around the actual URI, for example

url("/skins/mycompany/skin_images/reorderdown_enabled.png")

This will cause the icons to not show up at rendering. The fix is to remove the "".

The sample skin contains more styles than what we will be able to cover in this HowTo. There are three other components covered in the actual CSS file - af:table, af:showOneTab, and af:menuTabs - that are worth looking at.

Setup of a Custom Skin

Let's now have a look at how to setup your application to use an ADF Faces custom skin.

First of all we need the CSS file, stored somewhere at the root of your web application. In the sample application it stored in the /skin/myCompany director. We should also make sure that we have access to all resources need for the skin, for example images and other CSS files. In the sample application these are stored in the /skin/myCompany/images directory.

Secondly, we need to make sure that our ADF Faces application is aware of the custom skin. This is done by adding a configuration file to the WEB-INF directory called adf-faces-skins.xml.

Register a Custom Skin

The <id> element is used to reference your 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:

  • oracle.adf.desktop: the skin will automatically be used when the application is rendered on a desktop.
  • oracle.adf.pda: the skin will be used when rendered on a PDA.

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

  1. In JDeveloper, right click on the WEB-INF folder of the sample project and create a new XML document and name it - adf-faces-skins.xml
  2. Replace the generated code with the following:

    <?xml version="1.0" encoding="ISO-8859-1"?>

    <skins xmlns="http://xmlns.oracle.com/adf/view/faces/skin">
      <skin>
        <id>mycompany.desktop</id>
        <family>mycompany</family>
        <render-kit-id>oracle.adf.desktop</render-kit-id>
        <style-sheet-name>skins/mycompany/myCompanySkin.css</style-sheet-name>
      </skin>
    </skins>

     
  3. Save your work.

Configuring an Application to Use a Custom Skin

You set an element in the adf-faces-config.xml file that determines which skin to use, and if necessary, under what conditions. To configure an application to use a skin:

  1. Open the adf-faces-config.xml file.
  2. Replace the <skin-family> value with the family name for the skin(s) you wish to use.
  3. To conditionally set the value, 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>
  4. In the sample application we are going to use selectOneChoice component to switch skins at runtime, so we need to replace the following <skin-family>oracle</skin-family> in the adf-faces-config.xml file with:

    <skin-family>#{sessionScope.skinFamily}</skin-family>
     
  5. Save your work.

Let's now add the actual component that will perform the actual swithcing at runtime

  1. Open the sample.jspx file in the source code editor.
  2. Locate the following comment in the source:

    <!-- ================================================================ -->
    <!-- Add the sample selectOneChoice component here. -->
     
  3. Now add the following code snippet:

    <f:facet name="menuGlobal">
      <af:selectOneChoice label="Select Skin" value="#{sessionScope.skinFamily}" onchange="form.submit();">
        <af:selectItem label="Simple" value="simple"/>
        <af:selectItem label="Minimal" value="minimal"/>
        <af:selectItem label="Oracle" value="oracle"/>
        <af:selectItem label="MyCompany" value="mycompany"/>
      </af:selectOneChoice>
    </f:facet>

    The onchange event handler will perform a form POST when ever a skin is selected in the selectOneChoice component. Alternative 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.
     
  4. Save your work and run the sample.jspx page. Use the switcher to select a skin!

Summary

Creating ADF Faces 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 sample). This allows application developers to have different skins per user, page, application, and so on, without impacting the actual application logic!

false ,,,,,,,,,,,,,,,