Folder-based Themes

From Documentation
Revision as of 01:59, 8 April 2013 by Neillee2 (talk | contribs)

Before creating a new ZK theme, web designers need to understand its directory structure, let's start off by discovering where the default theme (a.k.a. breeze) is. Basically, the default theme is contained inside three java archive files: zul.jar (ZK CE), zkex.jar (ZK PE) and zkmax.jar (ZK EE). Note: freshly or evaluation versions will have special suffix to indicate the zk version and the build date. (e.g. zul-6.5.1.FL.20121204.jar).

As mentioned previously, a 'theme' is a collection of stylesheets and associated images for ZK's component set. Stylesheets are the files with extension of ".css.dsp". Think of them as normal CSS files that could utilize JSP taglib functionality. Associated images all have file extension either of ".gif" or ".png".

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png

In ZK EE, users will also have access to tablet-enhanced theme in zkmax.jar. In addition to the stylesheets and associated images, the tablet-enhanced theme also contains a property file (default.theme-properties) that could be used to easily customize attributes such as font-sizes and color values.

Once those resources are extracted from the respective java archives while preserving the original directory structure, they can be placed inside a folder, and become a basis for a new theme.

The top level subdirectories for this folder should look similar to the figure below.

Theme skeleton.png

Create a Folder-based Theme

Introduced in ZK 6.5.2, the embodiment of a theme can come from a sub-folder under the web application's context root. Creating a folder-based theme can be broken down into the following steps.

  1. Create a theme folder skeleton
  2. Modify the theme resources

Create a theme folder skeleton

The general idea is described in the introductory paragraph. However, it is tedious and error-prone to do this step manually. Hence, these steps should be performed using a tool such as the ZK Default Theme Extractor Utility (ztx.bat)[1].

Following are the steps:

  1. Download ZK library into a directory.
    Note: ZK library can also be found inside an existing ZK project.
  2. Execute ztx.bat to extract the default theme into an archive

Assume ZK library can be found inside C:\zk_jars, and the new theme is to be named dark. After a typical ztx session depicted by the following figure, dark.jar archives the exact replica of the default theme in the folder structure required by ZK theming support. Once this archive is generated, it becomes the basis where the new theme could be derived.

Ztx session.png

Modify the theme resources

Now it is just a matter of modifying the relevant stylesheets and importing associated image files.

Setting up the environment:

  1. Create a ZK Application Project [2]
  2. Create a folder named theme under the root folder of the web content.
  3. Unpack dark.jar under the folder theme

Also, please make sure the ZK Application is configured to process *.css.dsp by the following configuration in WEB-INF/web.xml.

<servlet>
    <servlet-name>dspLoader</servlet-name>
    <servlet-class>org.zkoss.web.servlet.dsp.InterpreterServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>dspLoader</servlet-name>
    <url-pattern>*.dsp</url-pattern>
</servlet-mapping>

After the environment is set up, the ZK Application Project should look like the following.

Zk folder theme project.png

Next, the new theme will need to be registered first before it could be used by the ZK application. Since the origin of the new theme is from a folder, ZK 6.5.2 extends the theme registration API for this purpose. ThemeOrigin is an enum defined to specify the origin of the registered theme. It has two valid values: JAR (default) and FOLDER. Since ThemeOrigin.JAR is the default value, the extended theme registration API is only needed in the case of folder-based themes. Theme registration could be done in the initialization code of the view model.

For example,

 1 ...
 2 import org.zkoss.zul.theme.Themes;
 3 import org.zkoss.web.theme.StandardTheme.ThemeOrigin;
 4 ...
 5 public class MainViewModel {
 6 	...
 7 	@Init
 8 	public void init() {
 9 		...
10 		Themes.register("dark", ThemeOrigin.FOLDER);
11 		...	
12 	}
13 	...
14 }

Now, the component style modifications shall begin. Please refer to [1] for more detailed example on doing this.

General steps for component style modification:

  1. Locate the stylesheet for a given component
  2. Modify existing images or add new images as needed
  3. Customize the component style by tweaking the stylesheet located in step 1

If a component style rule needs to refer to images within the theme folder, please use the zk core taglib function encodeThemeURL for path resolution. For example, to refer to zul/img/input/combo-btn.png under the dark theme folder, use the following syntax.

1 <%@ taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" %>
2 ...
3 .z-combobox {
4 	background-image: url(${c:encodeThemeURL('~./zul/img/input/combo-btn.png')});
5 }

Note: The special prefix ~./ will be interpreted as the theme folder root (e.g. /theme/dark/).

After all this has been done, button, the components should look the way your customization intended. Please refer to ZK Themes: Getting Started</ref> for how to switch themes dynamically within the ZK application.

Dark theme.png

  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png

Developers could also follow the same process described above to tailor the appearance of ZK components when viewed on tablets. When locating the stylesheets to modify, look inside the ~./zkmax/css/tablet folder instead.

For ZK EE users, custom themes could support styling for desktop-only, tablet-only, or both. Web application needs to know about the platforms a custom theme may support. This is also accomplished through theme registration. When a custom theme overrides the default tablet theme, its theme name must be prefixed with "tablet:" before making registration. For example, to notify the web application that dark' theme is tablet-capable, please use the following code snippet.

1 Themes.register("tablet:dark", ThemeOrigin.FOLDER);

In addition, the default tablet-enhanced theme has refactored many attributes such as color values, font-sizes, border-widths, ... into a property file in ~./zkmax/default.theme-properties. Changing the attribute values inside this property file could quickly alter the appearance of the components without touching their stylesheets. Nevertheless, developers may also combine these two approaches to suit their needs.

Beneath are some simple editings that could be performed to darken the color scheme of button and window components.

Button component (for tablet):

  1. Modify the highlighted attributes in ~./zkmax/css/default.theme-properties
    			...
    			Button_Color = #FFFFFF
    			...
    			Button_FontWeight = bold
    			...
    			Button_Background = ${t:gradient('ver', '#2E2E2E 0%; #030303 100%')}
    			...
    

Window component (for tablet):

  1. Modify the highlighted attributes in ~./zkmax/css/default.theme-properties
    			...
    			G_TextShadow = text-shadow: none;
    			...
    
  2. Edit the highlighted lines in ~./zkmax/css/tablet/window.css.dsp
    			...
    			.z-window-modal-header,
    			.z-window-popup-header,
    			.z-window-highlighted-header,
    			.z-window-overlapped-header,
    			.z-window-embedded-header {
      				line-height: 36px;
    				padding: 6px 0;
    				font-size: ${fontSizeS};
    				color: #D0D0D0;
    				font-weight: bold;
    				${G_TextShadow}
    			}
    			...
    			.z-window-embedded,
    			.z-window-modal,
    			.z-window-highlighted,
    			.z-window-overlapped,
    			.z-window-popup {
    				background: ${t:gradient('ver', '#2f2f2f 0%; #1d1d1d 25%; #020202 100%')}
    				padding: 5px;
    				border: 1px solid rgba(17, 17, 17, 0.3);
    				${t:boxShadow('inset 0px 1px 1px #FFFFFF')}
    				overflow: hidden;
    				${t:applyCSS3('box-sizing','border-box')}
    			}
    			...
    

With only a few modifications, button and window components already match the dark thematic feel as seen from tablet devices though more finer adjustments may be necessary.

Partial dark tablet.png

To simplify the demo, the dark theme only includes the style customization of four components. Tablet-enhanced theme also barely scratches the surface. For real-life theme development, every components in all their possible states (e.g. disabled, selected, mouse over, ...) must be considered. Moreover, the look-and-feel from both the PC and Tablet perspectives must also be taken into account.

After the new theme is developed, the entire theme folder can be exported as a zip file for distribution, say dark.zip.

Use a Folder-based Theme

Using a folder-based theme in a ZK Application is simple and versatile. Simply adopt the same environment as the one for developing a new folder-based theme. Furthermore, the ZK Application must be informed of the existence of the newly installed theme.

The process can be summarized as follows:

  1. Create a theme root folder
  2. Install the folder-based theme
  3. Register the folder-based theme

Let's walk through an example of using the folder-based theme dark.zip in another ZK application

Create a theme root folder

Theme root folder is where a ZK Application stores all its folder-based themes. By default, this folder is assumed to be named 'theme' and is directly under the application's root directory for its web content. This default location can be changed via the library property org.zkoss.theme.folder.root. For example, to move the theme root folder to /view/themes, the web developer would make the following configuration setting in WEB-INF/zk.xml. Please note that the value for the theme root folder cannot have leading and trailing forward slashes.

<library-property>
	<name>org.zkoss.theme.folder.root</name>
	<value>view/themes</value>
</library-property>

Install the folder-based theme

Suppose the theme root folder is changed to /view/themes through the configuration setting and that directory has been created. Simply extract the theme folder under this directory would finish this step. Since the name of the theme folder is also the name of the theme, renaming the theme folder would also rename the theme. For instance, to change the theme name from dark to darkstar, one would rename the folder accordingly.

Register the folder-based theme

Before the folder-based theme can be used, it must be registered first. The relevant code is as follows.

Themes.register("darkstar", ThemeOrigin.FOLDER);
// For ZK EE, also make customized tablet theme available
if ("EE".equals(WebApps.getEdition()))
    Themes.register("tablet:darkstar", ThemeOrigin.FOLDER);

This code fragment can be written in several places. For an example incorporating MVVM, please refer to the section Modify the theme resource. To make the folder-based theme available at application startup, write a class implementing the WebAppInit interface and place the above code inside the init() function.

public class DarkstarThemeWebAppInit implements WebAppInit {
	public void init(WebApp webapp) throws Exception {
		Themes.register("darkstar", ThemeOrigin.FOLDER);
		// For ZK EE, also make customized tablet theme available
		if ("EE".equals(WebApps.getEdition()))
		    Themes.register("tablet:darkstar", ThemeOrigin.FOLDER);
	}
}

The configuration file WEB-INF/zk.xml must also include the following configuration item.

<listener>
	<listener-class>DarkstarThemeWebAppInit</listener-class>
</listener>

Partial Override

Usually, the reason for creating a new theme is to completely change the appearance of each and every ZK components. In the case where only a few components have their visual styles altered, creating a new theme may be an overkill. In such a case, partial override may be a better solution.

Partial override refers to the mechanism allowing the developer to supply additional stylesheets that supplement and/or override the style rules defined in the current theme. The additional stylesheets are specified in WEB-INF/zk.xml.

For a concrete example, let's suppose that our application only wants the window and the button components to look like the ones in the dark theme. First of all, copy the relevant stylesheets and associated images to our application. Next, specify the stylesheets' locations in WEB-INF/zk.xml. Then, correct the urls for the associated images, if necessary.

<desktop-config>
	<theme-uri>/styles/window.css.dsp</theme-uri>
	<theme-uri>/styles/button.css.dsp</theme-uri>
</desktop-config>

Another solution would be to create a custom ThemeProvider[3]. In the sample code below, the default theme provider is extended to override the styling defined in the current theme with the ones placed inside the folder /styles under the context root. Notice that the overriding paths are not wrapped by ServletFns.encodeThemeURL(). Consequently, for this example, window.css.dsp and button.css.dsp would always be overridden no matter which theme the user switches to.

Other partial overriding schemes are certainly possible.

 1 WebApps.getCurrent().getConfiguration().setThemeProvider(new StandardThemeProvider() {
 2 
 3 	@Override
 4 	public String beforeWidgetCSS(Execution exec, String uri) {
 5 		if (uri.endsWith("window.css.dsp"))
 6 			return "/styles/window.css.dsp";			// replace the window.css.dsp in the current theme with the one in /styles
 7 		else if (uri.endsWith("button.css.dsp"))
 8 			return "/styles/button.css.dsp";			// replace the button.css.dsp in the current theme with the one in /styles
 9 		else
10 			return super.beforeWidgetCSS(exec, uri);	// apply the current theme
11 	}
12 });

Summary

In the past, additional themes are created and packaged inside Java archives. In the future, ZK 6.5.2[4] will introduce a new approach where theme could be packaged folder-based. This small talk describes the new approach in detail and explains the process the web developer would follow for theme creation and usage. In cases where only a few components need their visual presentation modified, web developer could choose to perform partial override.

Downloads

Source codes for both sample applications are now available at github.

To obtain the war files to deploy on your web server, please use maven.

  1. Import each sample applications separately as maven projects
  2. Use mvn clean compile war:war to generate the war files

References

  1. ZK Default Theme Extractor Utility. Please download at github.
  2. Please refer to ZK Installation Guide
  3. Theme Providers
  4. Cite error: Invalid <ref> tag; no text was provided for refs named zk652



Last Update : 2013/04/08

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.