20 Customizing the Appearance Using Styles and Skins

This chapter describes how to change the appearance of your application by changing style properties using ADF Faces skins and component style attributes.

This chapter includes the following sections:

20.1 Introduction to Skins, Style Selectors, and Style Properties

JDeveloper supports two options for applying style information to your ADF Faces components:

  • Build a skin and a cascading style sheet (CSS) using defined style selectors and configure your ADF application to use the skin and style sheet.

  • Use style properties to override the style information from the skin CSS to set specific instances of component display.

ADF Faces components delegate the functionality of the component to a component class, and the display of the component to a renderer. By default, all tags for ADF Faces combine the associated component class with an HTML renderer, and are part of the HTML render kit. HTML render kits are included with ADF Faces for display on both desktop and PDA. You cannot customize ADF Faces renderers. However, you can customize how components display using skins.

If you do not wish to change ADF Faces components throughout the entire application, you can choose to change the styles for the instance of a component on a page. You can also programmatically set styles conditionally. For example, you may want to display text in red only under certain conditions. For more information, see Section 20.4, "Changing the Style Properties of a Component".

The File Explorer application allows you to select several skins from a dropdown list. It provides several CSS files to support skin selection. For more information, see Section 1.4.3, "Overview of the File Explorer Application".

It is beyond the scope of this guide to explain the concept of CSS. For extensive information on style sheets, including the official specification, visit the W3C web site at:

http://www.w3.org/

Note:

The 11g Release 2 (11.1.2.0.0) introduced the ADF Skin Editor. Using this standalone product, you can visually create and modify skins for ADF Faces applications built using this release (11.1.1.5.0). The ADF Skin Editor provides a range of features that simplify the process of creating a skin. For more information, including how to install the ADF Skin Editor, see the Release Downloads for Oracle ADF 11g page at http://www.oracle.com/technetwork/developer-tools/adf/downloads/index.html. For information about using the ADF Skin Editor, see the Oracle Fusion Middleware Skin Editor User's Guide for Oracle Application Development Framework.

20.1.1 ADF Faces Skins

A skin is a style sheet based on the CSS 3.0 syntax specified in one place for an entire application. Instead of providing a style sheet for each component, or inserting a style sheet on each page, you can create one skin for the entire application. Every component automatically uses the styles as described by the skin. You do not have to make design-time changes to JSF pages to change their appearance when you use a skin. The skin allows you to globally change the appearance of ADF Faces components.

Existing ADF Faces applications use the skin that the application was configured to use when the application was created. For example, if you created an application using Oracle ADF 11g (11.1.1.2.0), the application uses the fusion skin. Applications created with subsequent releases use skins that extend this skin. If you upgrade an application, the application continues to use the skin that it was configured to use when first created. You edit the trinidad-config.xml file, as described in Section 20.2.4, "How to Configure an Application to Use a Custom Skin," if you want your application to use another skin.

You can create your own custom skin by extending one of the skins provided by ADF Faces. For more information, see Section 20.2.1, "How to Add a Custom Skin to an Application." Create or edit the trinidad-skins.xml file, as described in Section 20.2.3, "How to Register a Custom Skin," in addition to editing the trinidad-config.xml file if you want your application to use a custom skin that you created.

ADF Faces provides the following skins for use in your applications:

  • simple: Contains only minimal formatting.

  • blafplus-medium: Provides a modest amount of styling. This style extends the simple skin.

  • blafplus-rich: This skin extends the blafplus-medium skin. Provides more styling than the blafplus-medium skin. For example, graphics in the blafplus-rich skin have rounded corners.

  • fusion: Defines the default styles for ADF Faces components. This skin provides a significant amount of styling.

  • fusion-11.1.1.3.0: Modifies the fusion skin to make the hierarchy structure in certain components that render tabs clearer. These components are panelTabbed, navigationPane (attribute hint="tabs"), and decorativeBox. This skin also defines a more subtle background image for disclosed panelAccordion component panes to make text that appears in these panes easier to read.

  • fusionFx-v1: This skin extends from the fusion-11.1.1.3.0 skin. If you create a custom skin that extends any of the skins provided by ADF Faces, you need to register it in the trinidad-skins.xml file. Use the following values in the trinidad-skins.xml file if you extend the fusionFx-v1 skin:

    <skin>    <id>yourSkin.desktop</id>    <family>yourSkinFamily</family>
        <extends>fusionFx-v1.desktop</extends>
                …</skin>
    

    Use the following value in the trinidad-config.xml file if you want your application to use the fusionFx-v1 skin:

    <skin-family>fusionFx</skin-family>
    

    The fusionFx-v1 contains design improvements and changes to address a number of issues. Specifically, it adds:

    • A background color to the .AFMaskingFrame global style selector to prevent the display of content from an underlying frame when an inline popup displays in certain browsers.

    • A boolean ADF skin property, -tr-stretch-dropdown-table, for the inputComboboxListOfValues component. This property determines whether the table in the dropdown list stretches to show the content of the table columns or limits the width of the table to the width of the input field in the inputComboboxListOfValues component.

    • The inlineFrame component displays an image that serves as a loading indicator until the browser determines that the frame's contents have been loaded.

      You can implement this functionality in a custom skin that you create. The af|inlineFrame selector has "busy" and "flow" pseudo-classes that enable you to do this. The inlineFrame component only generates an IFrame element when the parent component does not stretch the inlineFrame component (the inlineFrame component is flowing). Use af|inlineFrame:busy:flow to define a background-image style that references a loading indicator. When the parent component stretches the inlineFrame component, the generated content is more complex. This complexity allows you define a content image URL using the af|inlineFrame::status-icon and an optional additional background-image using the af|inlineFrame::status-icon-style. It also allows you to reuse images that other component selectors use. For example, the carousel component's af|carousel::status-icon and af|carousel::status-icon-style selectors. Use skinning aliases to reuse these images.

      The following global selectors have also been introduced that you can use if you implement this functionality in your ADF skin:

      • .AFBackgroundImageStatus:alias: use to reference the background image used in af|inlineFrame::busy:flow.

      • .AFStatusIcon:alias use to reference the af|carousel::status-icon and af|inlineFrame::status-icon.

      • .AFStatusIconStyle:alias use to reference the af|carousel::status-icon-style and af|inlineFrame::status-icon-style.

      A resource key (af_inlineFrame.LABEL_FETCHING) defines the string to display for the inlineFrame component's loading icon.

  • fusionFx-v1.1: This skin extends from the fusionFx-v1 skin. It adds supports for the ability to clear Query-By-Example (QBE) filters in an af:table component.

    If you create a custom skin that extends any of the skins provided by ADF Faces, you need to register it in the trinidad-skins.xml file. Use the following values in the trinidad-skins.xml file if you want to extend the fusionFx-v1.1 skin:

    <skin>    <id>yourSkin.desktop</id>    <family>yourSkinFamily</family>
        <extends>fusionFx-v1.1.desktop</extends>
                …</skin>
    

    Use the following value in the trinidad-config.xml file if you want your application to use the fusionFx-v1.1 skin:

    <skin-family>fusionFx</skin-family>
      <skin-version>v1.1<skin-version>
    
  • Projector skins: ADF Faces provides skins that define styles for an application that you want to demonstrate to an audience using a projector. Each projector skin modifies a number of elements in its parent skin so that an application renders appropriately when displayed using table-top projectors (particularly older models of projector). For example, the fusion-projector skin modifies a number of elements in the fusion skin. These skins are useful if the audience is present at the same location as the projector. They may not be appropriate for an audience that views an application online through a web conference. ADF Faces provides the projector skins as a download from the Oracle Technology Network (OTN) web site.

Figure 20-1 shows the default fusion skin applied to the File Explorer Application index page.

Note:

The syntax in a skin style sheet is based on the CSS 3.0 specification. However, many browsers do not yet adhere to this version. At runtime, ADF Faces converts the CSS to the CSS 2.0 specification.

Figure 20-1 Index Page Using the Fusion Skin

Page with Oracle formatting.

ADF Faces also provides the simple skin, shown in Figure 20-2 as applied to the File Explorer Application index page.

Figure 20-2 Index Page Using the Simple Skin

Page with simple formatting.

Skins provide more options than setting standard CSS styles and layouts. The skin's CSS file is processed by the skin framework to extract skin properties and icons and register them with the Skin object. For example, you can customize the skin file using rules and pseudo classes that are supported by the skinning framework. Supported rules and pseudo classes include @platform, @agent, @accessibility-profile, :rtl, and @locale. For more information, see Section 20.1.2, "Skin Style Selectors".

20.1.2 Skin Style Selectors

Style sheet rules include a style selector, which identifies an element, and a set of style properties, which describe the appearance of the components. ADF Faces components include two categories of skin style selectors:

  • Global selectors

    Global selectors determine the style properties for multiple ADF Faces components. If the global selector name ends in the :alias pseudo-class, then the selector is most likely included in other component-specific selectors and will affect the skin for more than one component. For example, most, if not all, components use the .AFDefaultFontFamily:alias definition to specify the font family. If your skin overrides this selector with a different font family, that change will affect all the components that have included it in their selector definition. Example 20-1 shows the global selector for the default font family for ADF Faces components in an application.

    Example 20-1 Global Selector for Default Font Family

    .AFDefaultFontFamily:alias {
           font-family: Tahoma, Verdana, Helvetica, sans-serif;
    }
    
  • Component selectors

    Component-specific selectors are selectors that can apply a skin to a particular ADF Faces component. Example 20-2 shows the selector set to red as the background color for the content area of the af:inputText component.

    Example 20-2 af:inputText Component Selector

    af|inputText::content {
             background-color: red;
    }
    

Each category may include one or more of these types of ADF Faces skin selectors:

  • Standard selectors

    Standard selectors are those that directly represent an element that can have styles applied to it. For example, af|body represents the af:body component. You can set CSS styles, properties, and icons for this type of element.

  • Selectors with pseudo-elements

    Pseudo-elements are used to denote a specific area of a component that can have styles applied. Pseudo-elements are denoted by a double colon followed by the portion of the component the selector represents. For example, af|chooseDate::days-row provides the styles and properties for the appearance of the dates within the calendar grid.

  • Icon selectors

    Some components render icons (<img> tags) using a set of base icons. These icons can have skins applied even though no entries appear in the CSS source file for the icons in the way, for example, that entries appear for the background-image CSS property. Instead, the icons are registered with the Skin object for use by the renderer. As no entries for an icon selector appear in the CSS source file that a browser interprets, you cannot create containment selector definitions for an icon definition. You can only create a containment selector definition for items that have an entry in the CSS source file.

    Icon selectors are denoted by -icon for component selectors and Icon:alias for global selectors. For example, the af:inputDate component has a changed icon that can have a skin using the selector af|inputDate::changed-icon. The changed icon can also be globally set for all components using that icon with the global selector .AFChangedIcon:alias. For more information, see Section 20.3.2, "How to Apply Skins to Icons".

  • Resource strings

    The text rendered by ADF Faces components is translatable. The text is abstracted as a resource string that has skins applied. For example, af_dialog.LABEL_OK is a resource string for the text label of an af:dialog component when the OK button has been configured. Resource strings do not have skins in the CSS skin file, but in a resource bundle referenced from the skin definition file in the trinidad-skins.xml file using the <bundle-name> parameter. You can also use the <translation-source> parameter for an EL binding to point to a Map or ResourceBundle. For more information, see Section 20.3.1, "How to Apply Skins to Text".

  • Selectors with style properties

    Skin style properties allow you to customize the rendering of a component throughout the application. A CSS property is stored with a value in the Skin object and is available when the component is being rendered. For example, in af|breadCrumbs{-tr-show-last-item: false}, the skin property -tr-show-last-item is set to hide the last item in the af:breadCrumbs navigation path.

The CSS specification defines pseudo-classes such as :hover and :active that can apply to almost every component. ADF Faces provides additional pseudo-classes for specialized functions. Pseudo-classes are denoted in the selector by a colon followed by the class definition. The following are common pseudo-classes used by ADF Faces style selectors:

  • Alias: The :alias pseudo-class is a special type of class that serves as a syntax aid to organize code in your skin file. You can, for example, use it to set styles for more than one component or more than one portion of a component. You can also create your own alias classes that you can then include on other selectors. For example, you can define an alias pseudo-class (.AFLabel:alias) where you define label colors for a number of form components. Subsequent changes to the alias pseudo-class impact all components referenced by the alias pseudo-class.

            af|inputText::label,
            af|inputChoice::label,
            af|selectOneChoice::label {-tr-rule-ref: ".AFLabel:alias"}
            .AFLabel:alias { color: blue }
    

    The .AFLabel:alias pseudo-class has color set to blue, but you can change all the component's label color to red by simply changing .AFLabel:alias:

    .AFLabel:alias {color: red}
    

    For more information, see Section 20.3.5, "How to Create a Custom Alias".

  • Drag and drop: The two pseudo-classes available are :drag-source applied to the component initiating the drag and removed once the drag is over, and :drop-target applied to a component willing to accept the drop of the current drag.

  • Standard: In CSS, pseudo-classes like :hover, :active, and :focus are considered states of the component. This same concept is used in applying skins to components. Components can have states like read-only or disabled. When states are combined in the same selector, the selector applies only when all states are satisfied.

  • Right-to-left: Use this pseudo-class to set a style or icon definition when the browser is in a right-to-left language. Another typical use case is asymmetrical images. You will want the image to be flipped when setting skin selectors that use the image in a right-to-left reading direction. Be sure to append the :rtl pseudo-class to the very end of the selector and point it to a flipped image file. For example, the end image of the panelBox component will be the panelBoxStart.png file when the browser is set to right-to-left. The panelBox end image in right-to-left is the same as the flipped left-to-right panelBox start image.

    af|panelBox::medium af|panelBox::top-end:rtl {
              background-image: url(/skins/purple/images/panelBoxStart.png);
              width:8px; 
              height:8px
    }
    

    You can also use :rtl to apply to skin icons. For more information, see Section 20.3.2, "How to Apply Skins to Icons".

  • Inline editing: This pseudo-class is applied when the application activates a component subtree for editing in the browser. For example, :inline-selected is a pseudo-class applied to currently selected components in the active inline-editable subtree.

  • Message: This pseudo-class is used to set component-level message styles using CSS pseudo-classes of :fatal, :error, :warning, :confirmation, and :info. For more information, see Section 20.3.3, "How to Apply Skins to Messages".

You may not want your selector's CSS properties to be applied to all browsers, all platforms, all locales, and both reading-directions. For example, you may need to add some padding in Internet Explorer that you do not need on any other browser. You may want the font style to be different on Windows than it is on other platforms. To style a selector for a particular user environment, put that skinning information inside a skinning framework rule or :rtl pseudo-class. The skinning framework picks the styles based on the HTTP request information, such as agent and platform, and merges them with the styles without rules. Those CSS properties that match the rules get merged with those outside of any rules. The most specific rules that match a user's environment take precedence. The skinning framework currently supports these rules and pseudo-classes:

  • @platform and @agent

    Define platform styles using @platform and browser styles using @agent.

    The supported values to set a platform-specific style are windows, macos, linux, solaris, and ppc. For a browser agent-specific style, the supported values are ie, mozilla, gecko, webkit (maps to safari), ice, and email.

    In this example, the content area of the af:inputText component is set to the color pink for versions 7 and 8 of Internet Explorer, and set to version 1.9 of gecko on Windows and Linux platforms:

    @platform window, linux {
      @agent ie and (version: 7) and (version: 8), gecko and (version: 1.9) {
       af|inputText::content {background-color:pink
       }
      }
    }
    

    Note that the following syntax examples results in the same behavior:

    @agent ie and (version: 7.*)
    @agent ie and (version: 7)
    

    In order to specify only version 7.0.x of Internet Explorer, use the following syntax:

    @agent ie and (version: 7.0)
    

    There is currently no syntax to specify a range of versions.

  • @accessibility-profile

    Define @accessibility-profile, which defines styles for high-contrast and large-fonts accessibility profile settings from the trinidad-config.xml file.

    The high-contrast value would be for cases where background and foreground colors need to be highly contrasted with each other. The large-fonts value would be for cases where the user must be allowed to increase or decrease the text scaling setting in the web browser. Defining large-fonts does not mean that the fonts are large, but rather that they are scalable fonts or dimensions instead of fixed pixel sizes.

    <!-- Enable both high-contrast and large-fonts content -->
      <accessibility-profile>high-contrast large-fonts</accessibility-profile>
    
  • :rtl

    Use the :rtl pseudo-class to create a style or icon definition when the browser is displaying a right-to-left language.

  • @locale

  • Suppress skin styles with the -tr-inhibit skin property.

    Suppress or reset CSS properties inherited from a base skin with the -tr-inhibit skin property. For example, the -tr-inhibit:padding property will remove any inherited padding. Remove (clear) all inherited properties with the -tr-inhibit:all property. The suppressed property name must be matched exactly with the property name in the base skin.

  • Merge styles with the -tr-rule-ref property.

    Create your own alias and combine it with other style selectors using the -tr-rule-ref property. For more information, see Section 20.3.5, "How to Create a Custom Alias".

  • Alter themes of child components with the -tr-children-theme property.

    For more information, see Section 20.3.4, "How to Apply Themes to Components".

Example 20-3 shows several selectors in the CSS file that will be merged together to provide the final style.

Example 20-3 Merging of Style Selectors

/** For IE and Gecko on Windows, Linux and Solaris, make the color pink. **/
@platform windows, linux, solaris
        {
          @agent ie, gecko
          {
            af|inputText::content {background-color:pink}
          }
        }
       af|someComponent {color: red; width: 10px; padding: 4px}
        
/* For IE, we need to increase the width, so we override the width. 
 We still want the color and padding; this gets merged in. We want to add
 height in IE.  */

@agent ie        {          af|someComponent {width: 25px; height: 10px}        }
/* For IE 7 and 8, we also need some margins.*/
@agent ie (version: 7) and (version: 8)
        {
          af|someComponent {margin: 5px;}
        }
        
/* For Firefox 3 (Gecko 1.9) use a smaller margin.*/
@agent gecko (version: 1.9)\
        {
          af|someComponent {margin: 4px;}
        }
        
/* The following selectors are for all platforms and all browsers. */
/* rounded corners on the top-start and top-end */
/* shows how to use :rtl mode pseudo-class. The start image in ltr mode is the */
 /* same as the end image in the right-to-left mode. */
af|panelBox::medium af|panelBox::top-start,
af|panelBox::medium af|panelBox::top-end:rtl {
          background-image: url(/skins/purple/images/panelBoxStart.png);
          width:8px; 
          height:8px
        }
        
af|panelBox::medium af|panelBox::top-end,
af|panelBox::medium af|panelBox::top-start:rtl {
          background-image: url(/skins/purple/images/panelBoxEnd.png);
          height: 8px;
          width:  8px;
        }  

The selectors used to apply skins to the ADF Faces components are defined in the "Skin Selectors for Fusion's ADF Faces Components" and "Skin Selectors for Fusion's Data Visualization Tools Components" topics in JDeveloper's online help.

You can also apply themes as a way to implement look and feel at the component level. For information about themes, see Section 20.3.4, "How to Apply Themes to Components".

For information about defining skin style properties, see Section 20.3, "Defining Skin Style Properties".

20.1.3 Component Style Properties

You can adjust the look and feel of any component at design time by changing the style-related properties, inlineStyle and styleClass, both of which render on the root DOM element. Any style-related property you specify at design time overrides the comparable style specified in the application skin or CSS for that particular instance of the component.

The inlineStyle attribute is a semicolon-delimited string of CSS styles that can set individual attributes, for example, background-color:red; color:blue; font-style:italic; padding:3px. The styleClass attribute is a CSS style class selector used to group a set of inline styles. The style classes can be defined using an ADF public style class, for example, .AFInstructionText, sets all properties for the text displayed in an af:outputText component.

For information about applying component style properties, see Section 20.4, "Changing the Style Properties of a Component".

Given a specific selector, you can get style properties for a custom component by creating a class for a renderer. For more information, see Section 30.4.7, "How to Create a Class for a Renderer".

20.2 Applying Custom Skins to Applications

Custom skins can change the colors, fonts, and even the location of portions of ADF Faces components to represent your company's preferred look and feel. You build the skin by defining style selectors in a CSS file. After you create your custom style sheet, register it as a valid skin in the application, and then configure the application to use the skin. If you versioned multiple ADF skins in the same skin family, as described in Section 20.6, "Versioning Custom Skins," use the <skin-version> element to identify the specific version that you want the application to use.

By default, ADF Faces components use the fusion skin. Custom skins can extend to any of the ADF Faces skins, fusion, blafplus-rich, blafplus-medium, or simple. To create a custom skin, you declare selectors in a style sheet that override or inhibit the selectors in the style sheet being extended. Any selectors that you choose not to override will continue to use the style as defined in that skin.

Extending the simple skin does not require inhibiting as many properties as you would if you extended the BLAF Plus skins. For example, the BLAF Plus skins use many different colors for style properties, including text, background, and borders. The simple skin uses the :alias pseudo-class, as in .AFDarkBackground:alias, instead of specific colors. Changing a color scheme would require overriding far fewer global skin selectors than component skin selectors that specify multiple colors.

The text used in a skin is defined in a resource bundle. As with the selectors for the blafplus-rich skin, you can override the text by creating a custom resource bundle and declaring only the text you want to change. After you create your custom resource bundle, register it with the skin.

You can create and apply multiple skins. For example, you might create one skin for the version of an application for the web, and another for when the application runs on a PDA. Or you can change the skin based on the locale set on the current user's browser. Additionally, you can configure a component, for example an af:selectOneChoice component, to allow a user to switch between skins.

While you can bundle the custom skin resources and configuration files with the application for deployment, you can also store skin definitions in a Java Archive (JAR) file and then add it to the deployed application. The advantages to using a JAR file are that the custom skin can be developed and deployed separately from the application, improving consistency in the look and feel, and that skin definitions and image files can be partitioned into their own JAR files, reducing the number of files that may have to be deployed to an application.

The steps to apply a custom skin to your application are the following:

  1. Add a custom skin to your application. For details, see Section 20.2.1, "How to Add a Custom Skin to an Application".

  2. Register the custom skin. For details, see Section 20.2.2, "How to Register the XML Schema Definition File for a Custom Skin" and Section 20.2.3, "How to Register a Custom Skin".

  3. Configure the application to use the custom skin. For details, see Section 20.2.4, "How to Configure an Application to Use a Custom Skin".

  4. Deploy a custom skin in a JAR file. For details, see Section 20.7, "Deploying a Custom Skin File in a JAR File".

20.2.1 How to Add a Custom Skin to an Application

To add a custom skin to your application, create a CSS file within JDeveloper, which places the CSS in a project's source file for deployment with the application.

To add a custom skin to an application:

  1. In JDeveloper, make sure that CSS Level 3 and ADF Faces are selected. From the main toolbar, choose Tools > Preferences > CSS Editor. For Support Level, choose CSS Level 3 from the dropdown menu, and for Supported Components, select ADF Faces Extension.

  2. In the Application Navigator, right-click the project that contains the code for the user interface and choose New from the context menu.

  3. In the New Gallery under Categories, expand Web Tier and select HTML.

  4. Double-click the CSS File option.

  5. In the Create Cascading Style Sheet dialog, enter a name and path for the CSS.

  6. Click OK.

You can now open the CSS in the CSS editor and define styles for your application. For information about setting ADF Faces component style selectors, see Section 20.3, "Defining Skin Style Properties".

You can also create a CSS outside the context of Oracle JDeveloper and package the CSS with the skin resources into a JAR file. For information about this recommended option, see Section 20.7, "Deploying a Custom Skin File in a JAR File".

20.2.2 How to Register the XML Schema Definition File for a Custom Skin

You need to register the trindidad-skins.xsd file with JDeveloper if you plan to register a custom skin, as described in Section 20.2.3, "How to Register a Custom Skin". The trindidad-skins.xsd file defines the valid elements for a custom skin.

To register an XML schema definition file:

  1. In JDeveloper, select Tools > Preferences.

  2. In the Preferences dialog, select XML Schemas in the left pane and click Add.

  3. In the Add Schema dialog, click Browse to navigate to the XML schemas included in your version of JDeveloper.

    The directory path to the XML schemas is similar to the following:

    JDeveloper_Home/jdeveloper/modules/oracle.adf.view_11.1.1/trinidad-impl.jar!/org/apache/myfaces/trinidadinternal/ui/laf/xml/schemas/skin/trinidad-skins.xsd

    Note:

    In the Add Schema dialog, make sure the value in the Extension input field is .xml. If you change it to .xsd, when you later create XML files, you will not be able to use the XML schema you have created.
  4. Click OK.

20.2.3 How to Register a Custom Skin

Registering a skin involves creating a file named trinidad-skins.xml and populating it with values that identify the skin's ID, family, location, and the custom resource bundle if you are using one.

Before you begin:

Register the XML schema definition file that defines valid elements for the trinidad-skins.xml file. For more information, see Section 20.2.2, "How to Register the XML Schema Definition File for a Custom Skin".

To register a custom skin:

  1. In the Application Navigator, right-click the project and select New.

  2. In the New Gallery, expand General and select XML.

  3. Select XML Document from XML Schema and click OK.

  4. In the Create XML from XML Schema - Step 1 of 2 dialog:

    • XML File: Enter trinidad-skins.xml.

    • Directory: Append \src\META-INF to the end of the Directory entry.

    • Select Use Registered Schemas, and click Next.

  5. In the Create XML Schema - Step 2 of 2 dialog:

    • Target Namespace: Select http://myfaces.apache.org/trinidad/skin.

    • Root Element: Select skins.

    • Click Finish. The new file automatically opens in the XML Editor.

  6. In the XML editor, enter values for the following elements:

    • <id>

      A skin is required to have a unique ID. You can also use an EL expression to reference the skin ID. For example, if you want to have different skins for different locales, create an EL expression that selects the correct skin based on its ID. The convention is to put a "desktop" or ".pda" or ".portlet" at the end of the ID, such as "fusion.desktop".

    • <family>

      You configure 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.

      For example, you can define the blafplus-rich.desktop skin and the blafplus-rich.pda skin to be part of the richDemo family and the system automatically chooses the right skin based on the render-kit-id.

      <skin>
             <id>richdemo.desktop</id>
             <family>richDemo</family>
             <extends>blafplus-rich.desktop</extends>
             <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
             <style-sheet-name>skins/richdemo/richdemo.css</style-sheet-name>
      </skin>
      <skin>
             <id>richdemo.pda</id>
             <family>richDemo</family>
             <extends>blafplus-rich.pda</extends>
             <render-kit-id>pda</render-kit-id>
             <style-sheet-name>skins/richdemo/richdemo.css</style-sheet-name>
      </skin> 
      

      Note:

      If you create more than one skin in a particular family of skins, you can version the skins that you create. For more information, see Section 20.6, "Versioning Custom Skins."
    • <extends>

      You extend a custom skin by using this element. The default value for this element is simple.desktop. However, you can extend any skin by using this element.

      For example, you can easily change the font of the entire skin by extending the skin and creating a CSS with the font alias. For example, extend the fusion.desktop family as follows:

      <extends>fusion.desktop</extends>
      <style-sheet-name>skins/fod_skin.css</style-sheet-name>
      

      In the CSS, set the alias to change the font for the entire skin:

      .AFDefaultFontFamily:alias {font-family: Tahoma}.AFDefaultFont:alias {font-size: 16px}
      
    • <render-kit-id>

      This value 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 the application is rendered on a PDA.

    • <style-sheet-name>

      This is the URL of the custom style sheet. The style sheet name file is retrieved as a URL object using the following methods:

      • For nonstatic URLs, those that could change after the server has started, the URL is created by calling new java.new.URL(style-sheet-name) if style-sheet-name starts with http:, https:, file:, ftp:, or jar:. Otherwise, the URL is created by calling <FacesContext> <ExternalContext> getResource<style-sheet-name>. It will add a slash (/) to delimit the URL parts if it is not already present. For example, the slash is added between skins/bigfont/bigfont.css.

      • If still not retrieved, the URL is created using the <ClassLoader> getResource in a style-sheet-name format similar to META-INF/purpleSkin/styles/myPurpleSkin.css. Once the URL is converted to this format, it can be searched for in JAR files that may contain the style sheet.

    • <bundle-name>

      This is the resource bundle created for the skin. If you did not create a custom bundle, then you do not need to declare this element. For more information, see Section 20.3.1, "How to Apply Skins to Text".

      Note:

      If you have created localized versions of the resource bundle, then you need to register only the base resource bundle.
    • <translation-source>

      This is an EL binding that can point to a Map or a ResourceBundle. You can use this instead of the bundle name if you would like to be more dynamic in your skin translations at runtime. The <bundle-name> tag takes precedence.

    Example 20-4 shows the entry in the trinidad-skins.xml file for the mySkin skin.

    Example 20-4 Skin Entry in the trinidad-skins.xml File

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <skins xmlns="http://myfaces.apache.org/trinidad/skin">
        <skin>
            <id>
                mySkin.desktop
            </id>
            <family>
                mySkin
            </family>
            <extends>blafplus-rich.desktop</extends>
            <render-kit-id>
                org.apache.myfaces.trinidad.desktop
            </render-kit-id>
            <style-sheet-name>
                skins/mySkin/mySkin.css
            </style-sheet-name>
            <bundle-name>
                myBundle
            </bundle-name>
            <translation-source></translation-source>
        </skin> 
    </skins>
    
  7. Save the file.

20.2.4 How to Configure an Application to Use a Custom Skin

You set an element in the trinidad-config.xml file that determines which skin to use, and if necessary, under what conditions.

Note:

If you do not see the skin, check to see whether or not the af:document tag has been added to the page. The af:document tag initializes the skin framework to create the CSS and link it to the page.

To configure an application to use a skin:

  1. Open the trinidad-config.xml file.

  2. In the trinidad-config.xml file, write entries to specify the value of the <skin-family> element for the skin you want to use and, optionally, the <skin-version> element.

    Example 20-5 shows the configuration to use for the mySkin skin family.

    Example 20-5 Configuration to Use a Skin Family

    <trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">
      <skin-family>mySkin</skin-family>
       <skin-version>v2</skin-version>
    </trinidad-config>
    
  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 when the user's browser is set to the German locale, and to use the English skin otherwise, you would have the following entry in the trinidad-config.xml file:

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

During development, after you make changes to the custom skin, you can see your CSS changes without restarting the server by setting the web.xml file parameter org.apache.myfaces.trinidad.CHECK_FILE_MODIFICATION to true, as shown in Example 20-6. However, you must always restart the server to see icon and skin property changes.

Example 20-6 web.xml Parameter to Check Skin Changes

<context-param> 
    <param-name>org.apache.myfaces.trinidad.CHECK_FILE_MODIFICATION</param-name>
    <param-value>true</param-value> 
</context-param> 

20.3 Defining Skin Style Properties

The ADF Faces skin style selectors support multiple options for applying skins to a component to create a custom look and feel to your application. The af:goButton component skin style selectors are described in Table 20-1.

Table 20-1 af:goButton Component Style Selectors

Name Description

af|goButton

Style on the root element of the af:goButton component. You can use any valid CSS-2.1 pseudo-class, like :hover, :active, or :focus, as well as :disabled, to style the component for different states. Note that for buttons, the :active and :focus pseudo-classes do not work in Internet Explorer 7 (IE7). IE7 also does not allow disabled buttons to be styled. You should use the .AFButton*:alias selectors as a shortcut to apply a skin to all button components in the same manner.

af|goButton::icon-style

Style on the button icon, if the icon attribute is set on the af:goButton.

af|goButton::access-key

Style on the text of the button. This includes the .AFButtonAccessKeyStyle:alias style.


Figure 20-3 shows the application of the default fusion skin on the af:goButton component and the component icon.

Figure 20-3 af:goButton Component Default Appearance

af:goButton component default appearance.

Figure 20-4 shows the new appearance of the button and icon by setting the following style properties in a custom skin:

af|goButton::access-key {color: red;}
af|goButton::icon-style {border: 1px solid black;}

Figure 20-4 af:goButton Component with Custom Skin Applied

af:goButton component using custom skin.

The ADF Faces skin style selectors used by the default skin are defined in the "Skin Selectors for Fusion's ADF Faces Components" and "Skin Selectors for Fusion's Data Visualization Tools Components" topics in JDeveloper's online help. They are located in All Online Help > Developing Oracle ADF Faces Applications.

JDeveloper provides coding support while editing your CSS files. You can invoke the CSS code editor when editing your file directly or when editing an ADF Faces component in the JSP source editor. Code support is available for the following:

  • Code insight

  • Error highlighting

  • Preview of styles

  • Refactoring

  • Finding usages

  • Quick comment

  • Formatting

  • Matching tag highlighting

20.3.1 How to Apply Skins to Text

In addition to using a CSS file to determine styles, skins also use a resource bundle to determine the text within a component. The text that ADF Faces components render can be translated and abstracted as a resource string. For example, af_chooseDate.LABEL_SELECT_YEAR is the resource string for the label of the field used to select the year using an af:chooseDate component. All the ADF Faces skins use the same resource bundle.

To apply a skin to the text in ADF Faces components, create a custom resource bundle and override the default resource string values. Then, set the <bundle-name> property for your custom resource bundle in the trinidad-skins.xml file.

Note:

ADF Faces components provide automatic translation. The resource bundle used for the components' skin is translated into 28 languages. If a user sets the browser to use the German (Germany) language, any text contained within the components will automatically be displayed in German. For this reason, if you create a resource bundle for a custom skin, you must also create localized versions of that bundle for any other languages the application supports.

See Chapter 21, "Internationalizing and Localizing Pages" for more information.

To create and register a custom resource bundle:

  1. In JDeveloper, create a new simple Java class:

    • In the Application Navigator, right-click where you want the file to be placed and choose New to open the New Gallery.

    • In the Categories tree, select Java, and in the Items list, select Java Class.

    • Enter a name and package for the class. The class must extend java.util.ListResourceBundle.

  2. Add any keys to your bundle that you wish to override and set the text as needed. Example 20-7 shows the SkinBundle custom resource bundle.

    Example 20-7 Resource Strings Set in Custom SkinBundle

    public class SkinBundle extends ListResourceBundle {
            @Override
            public Object[][] getContents() {
              return _CONTENTS;
            }
          
            static private final Object[][] _CONTENTS = {
              {"af_tableSelectMany.SELECT_COLUMN_HEADER", "Select A Lot"},
              {"af_tableSelectOne.SELECT_COLUMN_HEADER", "Select Just One"},
              {"af_showDetail.DISCLOSED_TIP", "Click to Hide"}
            };
     }
    
  3. Set the name of your custom resource bundle in the <bundle-name> parameter of the trinidad-skins.xml file. Example 20-8 shows the custom SkinBundle set in the trinidad-skins.xml file.

    Example 20-8 Custom SkinBundle Set in trinidad-skins.xml

    <skin>
        <id>
           purple.desktop
        </id>
        <family>
           purple
        </family>
        <render-kit-id>
           org.apache.myfaces.trinidad.desktop
        </render-kit-id>
        <style-sheet-name>
           skins/purple/purpleSkin.css
        </style-sheet-name>
        <bundle-name>
           org.apache.myfaces.trinidaddemo.resource.SkinBundle
        </bundle-name>
    </skin>
    
    

Another option for applying skins to text is to use the <translation-source> parameter instead of <bundle-name>. The <translation-source> parameter is an EL binding that points to a Map or a ResourceBundle. The benefit of this option is that you can automatically change the translation value based on any logic that you want at runtime. The <bundle-name> tag takes precedence if both are set. Example 20-9 shows the code for using an EL expression to set the <translation-source> parameter in a bundle map.

Example 20-9 Custom Resource Bundle Map

public class SkinTranslationMapDemo
{
  /* Test a skin's translation-source EL pointing to a Map */
  public Map<String, String> getContents()
  {
    return _CONTENTS;
  }
 
  static private final Map<String, String> _CONTENTS = new HashMap<String, String>();
  static 
  {
    _CONTENTS.put("af_inputDate.LAUNCH_PICKER_TIP", "Launch PickerMap");
    _CONTENTS.put("af_showDetail.DISCLOSED_TIP", "Hide Tip Map");
    _CONTENTS.put("af_showDetail.DISCLOSED", "Hide Map");
 
  }
}

Example 20-10 shows setting the <translation-source> parameter for the resource map in the trinidad-skins.xml file.

Example 20-10 Custom Resource Bundle Map Set in trinidad-skins.xml

<skin>
   <id>
       purple.desktop
   </id>
   <family>
       purple
   </family>
   <render-kit-id>
       org.apache.myfaces.trinidad.desktop
   </render-kit-id>
   <style-sheet-name>
       skins/purple/purpleSkin.css
   </style-sheet-name>
   <translation-source>
       #{skinTranslationMap.resourceBundle}
   </translation-source>
 </skin>

20.3.2 How to Apply Skins to Icons

You can apply skins to the default icons associated with ADF Faces components by specifying the URL path to the icon image in the icon style selector.

Note that CSS syntax like pseudo-classes (:hover, and so forth) and descendant selectors and composite class selectors does not work with icon selectors.

Note:

If you are overriding a selector for an icon, use a context-relative path for the URL to the icon image (that is, start with a leading slash (/)), and do not use quotation marks.

Also, you must include the width and the height for the icon.

Example 20-11 shows a selector for an icon.

Example 20-11 Selector for an Icon

.AFErrorIcon:alias {
      content:url(/adf/images/error.png);
      width:7px; height:18px
 }

Icons and buttons can both use the rtl pseudo-class. This defines an icon or button for use when the application displays in right-to-left mode. Example 20-12 shows the rtl pseudo-class used for an icon.

Example 20-12 Icon Selector Using the rtl Pseudo-Class

.AFErrorIcon:alias:rtl {
      content:url(/adf/images/error.png);
      width:16px; height:16px
 }

20.3.3 How to Apply Skins to Messages

You can apply style to ADF Faces input components based on whether or not they have certain levels of messages associated with them. When a message of a particular type is added to a component, the styles of that component are automatically modified to reflect the new status. If styles are not defined for the status in question, then the default styles are used.

In order to define styles for your input components based on message levels that are tied to them, you would append a style pseudo-class to your component definition. For example, to define the base style for the content region of the af:inputText component to a background color of purple, use the style selector af|inputText::content{background-color:purple}. To define the content region of the component when an error message is present, use the skin style selector af|inputText:error::content.

The valid message properties are :fatal, :error, :warning, :confirmation, and :info.

20.3.4 How to Apply Themes to Components

Themes are a way of implementing a look and feel at a component level. The purpose is to provides a consistent look and feel across multiple components for a portion of a page. A common usage for themes is in a JSF page template where certain areas have a distinct look. For example, a page may have a branding area at the top with a dark background and light text, a navigation component with a lighter background, and a main content area with a light background.

A component that sets a theme exposes that theme to its child components and therefore the theme is inherited. Themes can be set (started or changed) by the following components:

  • af:document

  • af:decorativeBox

  • af:panelStretchLayout

  • af:panelGroupLayout

The Fusion and BLAF Plus skins (blafplus-rich and blafplus-medium) support the following themes:

  • Dark

  • Medium

  • Light

  • None (default)

In the JSPX page, the theme is started by the af:document component, as in:

<af:document theme="dark">
  <af:panelTabbed>...</af:panelTabbed>
</af:document>

To set the theme for a component, specify a theme attribute in the skin selector in the CSS file. For example, the selector to change the text color under an af:panelTabbed component to a dark theme is:

af|panelTabbed[theme="dark"] {
  color: red;
}

If you do not want a child component to inherit modifications made to a parent component in a JSPX page, set a value for the -tr-children-theme property in the CSS file. For example, you do not want the af:panelTabbed child component to inherit the dark theme defined for the af:document parent component in the JSPX page. Set the -tr-children-theme property in the CSS file as follows:

af|panelTabbed::content {
  -tr-children-theme: default;
}

By default, themes are not set for components or their child components. Because themes are inherited, the following values are supported when a component has a theme attribute that is not set:

  • not given - If no theme is given, the theme is inherited, as in <af:decorativeBox>...

  • #{null}- The theme is inherited; same as not given.

  • inherit - The theme is inherited; same as null.

  • default - The theme is removed for the component and its child components.

  • empty string - If the theme is set to a blank string, it has the same behavior as default. For example, <af:decorativeBox theme=""> will remove the theme for the component and its child components.

Because the themes are added to every HTML element of a component that supports themes and that has style classes, there is no need for containment-style CSS selectors for themes. With the exception of :ltr and :rtl, all theme selectors should always appear on the last element of the selector. For example, the selector to apply a dark theme to each step of an af:breadCrumbs component would be:

af|breadCrumbs::step:disabled[theme="dark"] {
  color:#FFFFFF;
}

Color incompatibility may occur if a component sets its background color to a color that is not compatible with its encompassing theme color. For example, if a panelHeader component is placed in a dark theme, the CSS styles inside the panelHeader component will set its component background to a light color without changing its foreground color accordingly. The result is a component with a light foreground on a light background. Many other components also set their foreground color to a light color when placed in a dark theme.

If color incompatibility occurs, you can resolve color incompatibility between parent and child components by setting a value for the -tr-children-theme property. For components that do not have a parent-child relationship, you can manually set the component's theme color to a color that is compatible with the surrounding theme color. You do this by inserting the panelGroupLayout or panelStretchLayout component inside the component and by setting the panelGroupLayout or panelStretchLayout theme to a compatible color.

<af:panelHeader text="Header Level 0"> 
            <af:panelGroupLayout layout="vertical" theme="default"> 
              ... 
            </af:panelGroupLayout>
</af:panelHeader> 

20.3.5 How to Create a Custom Alias

You can create your own alias that you can then include on other selectors.

To create a custom alias:

  1. Create a selector class for the alias. For example, you can add an alias to set the color of a link when a mouse cursor hovers over it:

    .MyLinkHoverColor:alias {color: #CC6633;}
    
  2. To include the alias in another selector, add a pseudo-element to an existing selector to create a new selector, and then reference the alias using the -tr-rule-ref:selector property.

    For example, you can create a new selector for the af|menuBar::enabled-link selector to style the hover color, and then reference the custom alias, as shown in Example 20-13.

    Example 20-13 Referencing a Custom Alias in a New Selector

    af|menuBar::enabled-link:hover
    {
      -rt-rule-ref:selector(".MyLinkHoverColor:alias");
    }
    

20.3.6 How to Configure a Component for Changing Skins Dynamically

To configure a component to dynamically change the skin, you must first configure the component on the JSF page to set a scope value that can later be evaluated by the configuration file. You then configure the skin family in the trinidad-config file to be dynamically set by that value.

To conditionally configure a component to set the skin family:

  1. Open the main JSF page (such as the index.jspx or a similar file) that contains the component that will be used to set the skin family.

  2. Configure the page to display the skin family by using the sessionScope component.

    Example 20-14 shows an af:selectOneChoice component that takes its selected value, and sets it as the value for the skinFamily attribute in the sessionScope component on the index.jspx page.

    Example 20-14 Using a Component to Set the Skin Family

    <af:selectOneChoice label="Choose Skin:" value="#{sessionScope.skinFamily}" autoSubmit="true">
        <af:selectItem value="blafplus-rich" label="blafplus-rich"/>
        <af:selectItem value="blafplus-medium" label="blafplus-medium"/>
        <af:selectItem value="simple" label="simple"/>
        <af:selectItem value="richDemo" label="richDemo"/>
        <af:selectItem value="mySkin" label="mySkin"/>
    </af:selectOneChoice>
    

    The Refresh button on the page resubmits the page. Every time the page refreshes, the EL expression is evaluated and if there is a change, the page is redrawn with the new skin.

To conditionally configure a component for changing skins at runtime:

In the trinidad-config.xml file, use an EL expression to dynamically evaluate the skin family:

<skin-family>#{sessionScope.skinFamily}</skin-family>

20.4 Changing the Style Properties of a Component

ADF Faces components use the CSS style properties based on the Cascading Style Sheet (CSS) specification. Cascading style sheets contain rules, composed of selectors and declarations, that define how styles will be applied. These are then interpreted by the browser and override the browser's default settings.

WARNING:

Do not use styles to achieve stretching of components. Using styles to achieve stretching is not declarative and, in many cases, will result in inconsistent behavior across different web browsers. Instead, you can use the geometry management provided by the ADF Faces framework to achieve component stretching. For more information about layouts and stretching, see Section 8.2.1, "Geometry Management and Component Stretching.".

20.4.1 How to Set an Inline Style

Set an inline style for a component by defining the inlineStyle attribute. You can use inline style to specify the style of a component for that instance of the component. For more information, see Section 8.3, "Arranging Contents to Stretch Across a Page".

To set an inline style:

  1. Set the inlineStyle attribute of the component to the inline style you want to use.

  2. If you use the Property Inspector to set a style, you can select the style features you want from dropdown lists, as shown in Figure 20-5.

    Figure 20-5 Setting an inlineStyle

    Setting inlineStyle attribute with Property Inspector

    JDeveloper adds the corresponding code for the component to the JSF page. Example 20-15 shows the source for an af:outputText component with an inlineStyle attribute.

    Example 20-15 InlineStyle in the Page Source

    <af:outputText value="outputText1"
                   inlineStyle="color:Red; text-decoration:overline;"/>
    
  3. You can use an EL expression for the inlineStyle attribute itself to conditionally set inline style attributes. For example, if you want the date to be displayed in red when an action has not yet been completed, you could use the code similar to that in Example 20-16.

    Example 20-16 EL Expression Used to Set an inlineStyle Attribute

    <af:outputText value="#{row.assignedDate eq  
        null?res['srsearch.unassignedMessage']:row.assignedDate}"
                  inlineStyle="#{row.assignedDate eq null?'color:rgb(255,0,0);':''}"/>
    
  4. The ADF Faces component may have other style attributes not available for styling that do not register on the root DOM element. For example, for the af:inputText component, set the text of the element using the contentStyle property, as shown in Example 20-17.

Example 20-17 Using the contentStyle Property

<af:inputText value="outputText1"
          contentStyle="color:Red;"/>

20.4.2 How to Set a Style Class

You can define the style for a component using a style class. You create a style class to group a set of inline styles.

To set a style using a style class:

  1. Set the styleClass attribute of the component to the style class you want to use.

    Example 20-18 shows an example of a style class being used in the page source.

    Example 20-18 Page Source for Using a Style Class

    <af:outputText value="Text with a style class" 
                   styleClass="overdue"/>
    
  2. You can also use EL expressions for the styleClass attribute to conditionally set style attributes. For example, if you want the date to be displayed in red when an action has not yet been completed, you could use code similar to that in Example 20-16.

20.5 Referring to URLs in a Skin's CSS File

You can refer to a URL from a skin's CSS file in a number of different formats. The supported formats are:

  • Absolute

    You specify the complete URL to the resource. For example, a URL in the following format:

    http://www.mycompany.com/WebApp/Skin/skin1/img/errorIcon.gif

  • Relative

    You can specify a relative URL if the URL does not start with / and no protocol is present. A relative URL is based on the location of the skin's CSS file. For example, if the skin's CSS file directory is WebApp/Skin/skin1/ and the specified URL is img/errorIcon.gif, the final URL is /WebApp/Skin/mySkin/img/errorIcon.gif

  • Context relative

    This format of URL is resolved relative to the context root of your web application. You start a context relative root with /. For example, if the context relative root of a web application is:

    /WebApp

    and the specified URL is:

    /img/errorIcon.gif

    the resulting URL is:

    /WebApp/img/errorIcon.gif

  • Server relative

    A server relative URL is resolved relative to the web server. This differs to the context relative URL in that it allows you reference a resource located in another application on the same web server. You specify the start of the URL using //. For example, write a URL in the following format:

    //WebApp/Skin/mySkin/img/errorIcon.gif

20.6 Versioning Custom Skins

You can specify version numbers for your custom skins in the trinidad-skins.xml file using the <version> element. Use this capability if you want to distinguish between custom skins that have the same value for the <family> element in the trinidad-skins.xml file. Note that when you configure an application to use a particular custom skin, you do so by specifying values in the trinidad-config.xml file, as described in Section 20.2, "Applying Custom Skins to Applications."

20.6.1 How to Version a Custom Skin

You specify a version for your custom skin by entering a value for the <version> element in the trinidad-skins.xml file.

To version a custom skin:

  1. In the Application Navigator, double-click the trinidad-skins.xml file. By default, this is in the Web Content/WEB-INF node.

  2. In the structure window, right-click the skin node for the custom skin that you want to version and choose Insert inside skin > version.

  3. In the Insert version dialog, select true from the default list if you want your application to use this version of the custom skin when no value is specified in the <skin-version> element of the trinidad-config.xml file, as described in Section 20.2, "Applying Custom Skins to Applications."

  4. Enter a value in the name field. For example, enter v1 if this is the first version of the custom skin.

  5. Click OK.

20.6.2 What Happens When You Version Custom Skins

Example 20-19 shows an example trinidad-skins.xml that references three source files for custom skins (skin1.css, skin2.css, and skin3.css). Each of these custom skins have the same value for the <family> element (test). The values for the child elements of the <version> elements distinguish between each of these custom skins. At runtime, an application that specifies test as the value for the <skin-family> element in the application's trinidad-config.xml file uses skin3 because this custom skin is configured as the default skin in the trinidad-skins.xml file (<default>true</default>). You can override this behavior by specifying a value for the <skin-version> element in the trinidad-config.xml file, as described in Section 20.2, "Applying Custom Skins to Applications."

Example 20-19 trinidad-skins.xml with versioned custom skin files

<?xml version="1.0" encoding="windows-1252"?>
<skins xmlns="http://myfaces.apache.org/trinidad/skin">
  <skin>
    <id>skin1.desktop</id>
    <family>test</family>
    <extends>simple.desktop</extends>
    <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
    <style-sheet-name>skins/skin1/skin1.css</style-sheet-name>
    <version>
      <name>v1</name>
    </version>
  </skin>
  <skin>
    <id>skin2.desktop</id>
    <family>test</family>
    <extends>fusionFx-v1.desktop</extends>
    <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
    <style-sheet-name>skins/skin2/skin2.css</style-sheet-name>
    <version>
      <name>v2</name>
    </version>
  </skin>
  <skin>
    <id>skin3.desktop</id>
    <family>test</family>
    <extends>fusion.desktop</extends>
    <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
    <style-sheet-name>skins/skin3/skin3.css</style-sheet-name>
    <version>
     <default>true</default>
      <name>v3</name>
    </version>
  </skin>
</skins>

20.7 Deploying a Custom Skin File in a JAR File

You may want to store skin definitions in a Java Archive (JAR) file and then add it to the deployed application. The benefits of packaging skins into a JAR file as compared to bundling them into the application are the following:

  • A skin can be deployed and developed separately from the application. This also helps to reduce the number of files to be checked in case some changes must be applied to the skin. Foremost is that using a skin definition contained in a JAR file improves consistency in the look and feel of the application.

  • Skin definitions and images can be separated into their own JAR files. Therefore, you can partition the image base into separate JAR files, so that not all files have to be deployed with all applications.

To deploy a skin into a JAR file, follow these rules:

  • The trinidad-skins.xml file that defines the skin and that references the CSS file must be within the META-INF directory.

  • All image resources and CSS files must also be under the META-INF directory. The images must be in a directory that starts with an adf root directory or any directory name that is mapped in the web.xml file for the resource servlet, as shown in Example 20-20.

  • The JAR file must be placed in the WEB-INF/lib directory of the view layer project of the application to deploy (or use a shared library at the application-server level).

Example 20-20 web.xml File with Paths

<servlet-mapping>
      <servlet-name>resources</servlet-name>
      <url-pattern>/adf/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
      <servlet-name>resources</servlet-name>
      <url-pattern>/afr/*</url-pattern>
 </servlet-mapping>

To deploy a skin into a JAR file:

  1. Create a directory structure similar to the following:

          c:\temp\META-INF\adf\oracle\skin\images
                  META-INF\skins\fusion.css
                  META-INF\trinidad-skins.xml
    
  2. Confirm that the directory in the META-INF directory starts with adf. The images directory contains all the images used within the oracleblaf.css skin. The CSS reference to the images should have a path similar to this:

          af|inputColor::launch-icon:rtl {
            content:url(../adf/oracle/skin/images/cfsortl.png);
            width: 12; height: 12;
            left:-7px;
            position:relative;
            right:-7px;
            top:5px;
    }
    

    Note the two leading periods in front of the image path ../adf/oracle/skin/images/cfsortl.png. This allows the search for the META-INF root to start one directory above the META-INF/skin directory in which the CSS is located.

  3. Check that the trinidad-skins.xml file is located in the META-INF directory and that it contains content in a format similar to this:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <skins xmlns="http://myfaces.apache.org/trinidad/skin">
        <skin>
            <id>richdemo.desktop</id>
            <family>richDemo</family>
            <extends>fusion.desktop</extends>
            <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
            <style-sheet-name>skins/richdemo/richdemo.css</style-sheet-name>
        </skin>
    </skins>
    

    This example defines the skin as richdemo.desktop in the richDemo family. The trinidad-skins.xml file can have more than one skin definition. The richdemo.css file (or your custom CSS file) is referenced from the style-sheet-name element.

  4. To create the JAR file, issue the following command from the c:\temp directory:

    jar -cvf customSkin.jar META-INF/
    
  5. Copy the resulting customSkin.jar file to the WEB-INF/lib directory of the consuming ADF project. Configure the trinidad-skins.xml file located on the WEB-INF directory of the ADF project.

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

    Because the skin can be discovered at runtime, you do not need to code the skin family name.

Note:

The skin definition in the JAR file is not displayed in the JDeveloper visual editor. You may see a message in the log window that the skin family could not be found. You can ignore this message.