Folder-based Themes"

From Documentation
m
Line 37: Line 37:
 
</ol>
 
</ol>
  
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.
+
After a typical ztx session has been executed, an archive would be generated that contains the exact replica of the default theme in the folder structure required by ZK theming support. This generated archive becomes the basis where the new theme could be derived.
 
 
[[File:ztx_session.png|400px]]
 
  
 
== Modify the theme resources ==  
 
== Modify the theme resources ==  
Line 49: Line 47:
 
<li>Create a ZK Application Project <ref>Please refer to [http://books.zkoss.org/wiki/ZK_Installation_Guide ZK Installation Guide]</ref>
 
<li>Create a ZK Application Project <ref>Please refer to [http://books.zkoss.org/wiki/ZK_Installation_Guide ZK Installation Guide]</ref>
 
<li>Create a folder named '''theme''' under the root folder of the web content.</li>
 
<li>Create a folder named '''theme''' under the root folder of the web content.</li>
<li>Unpack '''dark.jar''' under the folder '''theme'''</li>
+
<li>Unpack the generated archive under the folder '''theme'''</li>
 
</ol>
 
</ol>
  
Line 65: Line 63:
 
</source>
 
</source>
  
After the environment is set up, the ZK Application Project should look like the following.
+
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.
  
[[File:zk_folder_theme_project.png]]
+
'''Note:''' the registered name should match the folder name.
 
 
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,
 
For example,
Line 90: Line 86:
 
</source>
 
</source>
  
Now, the component style modifications shall begin. Please refer to [http://http://books.zkoss.org/index.php?title=Small_Talks/2013/January/Packaging_Themes_Inside_Folders_in_ZK_6.5.2] for more detailed example on doing this.
+
Now, the component style modifications shall begin. Please refer to this [http://http://books.zkoss.org/index.php?title=Small_Talks/2013/January/Packaging_Themes_Inside_Folders_in_ZK_6.5.2 smalltalk] for a more detailed example on doing this. Here would just summarize the steps.
  
 
General steps for component style modification:
 
General steps for component style modification:
Line 110: Line 106:
 
Note: The special prefix '''~./''' will be interpreted as the theme folder root (e.g. /theme/dark/).
 
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 [https:///zkoss/zkthemes/wiki/GetStarted ZK Themes: Getting Started]</ref> for how to switch themes dynamically within the ZK application.
+
After all this has been done, the components should have their views customized. Please refer to this [http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/Theming_and_Styling/Understanding_the_Theming_Subsystem/Switching_Themes article]</ref> for how to switch themes dynamically within the ZK application.
 
 
[[File:dark_theme.png]]
 
  
 
{{ZK EE}}
 
{{ZK EE}}
  
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.
+
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.
 
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.
Line 124: Line 118:
 
</source>
 
</source>
  
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.
+
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):
 
<ol>
 
<li>Modify the highlighted attributes in '''~./zkmax/css/default.theme-properties'''
 
<source lang="css" highlight="2,4,6">
 
...
 
Button_Color = #FFFFFF
 
...
 
Button_FontWeight = bold
 
...
 
Button_Background = ${t:gradient('ver', '#2E2E2E 0%; #030303 100%')}
 
...
 
</source>
 
</li>
 
</ol>
 
 
 
Window component (for tablet):
 
<ol>
 
<li>Modify the highlighted attributes in '''~./zkmax/css/default.theme-properties'''
 
<source lang="css" highlight="2">
 
...
 
G_TextShadow = text-shadow: none;
 
...
 
</source>
 
</li>
 
<li>Edit the highlighted lines in '''~./zkmax/css/tablet/window.css.dsp'''
 
<source lang="css" highlight="10,20">
 
...
 
.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')}
 
}
 
...
 
</source>
 
</li>
 
</ol>
 
 
 
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.
 
 
 
[[File:partial_dark_tablet.png|700px]]
 
 
 
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'''.
 
After the new theme is developed, the entire theme folder can be exported as a zip file for distribution, say '''dark.zip'''.
Line 253: Line 182:
 
</listener>
 
</listener>
 
</source>
 
</source>
 
= 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.
 
 
<source lang="xml">
 
<desktop-config>
 
<theme-uri>/styles/window.css.dsp</theme-uri>
 
<theme-uri>/styles/button.css.dsp</theme-uri>
 
</desktop-config>
 
</source>
 
 
Another solution would be to create a custom ThemeProvider<ref>[http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/Theming_and_Styling/Theme_Providers Theme Providers]</ref>. 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.
 
 
<source lang="java" line="true">
 
WebApps.getCurrent().getConfiguration().setThemeProvider(new StandardThemeProvider() {
 
 
@Override
 
public String beforeWidgetCSS(Execution exec, String uri) {
 
if (uri.endsWith("window.css.dsp"))
 
return "/styles/window.css.dsp"; // replace the window.css.dsp in the current theme with the one in /styles
 
else if (uri.endsWith("button.css.dsp"))
 
return "/styles/button.css.dsp"; // replace the button.css.dsp in the current theme with the one in /styles
 
else
 
return super.beforeWidgetCSS(exec, uri); // apply the current theme
 
}
 
});
 
</source>
 
 
= Summary =
 
 
In the past, additional themes are created and packaged inside Java archives. In the future, ZK 6.5.2<ref name="zk652"/> 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 [https://github.com/leeyt/ZKSmalltalk github].
 
 
To obtain the war files to deploy on your web server, please use maven.
 
# Import each sample applications separately as maven projects
 
# Use '''mvn clean compile war:war''' to generate the war files
 
  
 
= References =
 
= References =

Revision as of 04:19, 8 April 2013

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

After a typical ztx session has been executed, an archive would be generated that contains the exact replica of the default theme in the folder structure required by ZK theming support. This generated archive becomes the basis where the new theme could be derived.

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 the generated archive 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>

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.

Note: the registered name should match the folder name.

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 this smalltalk for a more detailed example on doing this. Here would just summarize the steps.

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, the components should have their views customized. Please refer to this article</ref> for how to switch themes dynamically within the ZK application.

  • 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.

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>

References

  1. ZK Default Theme Extractor Utility. Please download at github.
  2. Please refer to ZK Installation Guide



Last Update : 2013/04/08

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