ZWT V0.3.1 JavaScript framework for Rich Internet Applications

Getting Started with Zeleos Web Toolkit V0.3.0

Introduction

The JavaScript API is the core component of Zeleos Web Toolkit. It was designed to be highly extensible and it follows a strict coding convention. The result is a clean, easy to use framework to develop powerful Rich Internet Applications.

The Zeleos User Interface Description Language or ZUIDL is the other key component. It is used to describe the user interfaces of a ZWT application and then compiled to generate runtime files.

This user guide describes how you can create and develop a ZWT application.

Set up the Environment
Getting Zeleos Web Toolkit

In order to start working with ZWT, you first need to download the last ZWT distribution and extract it to the location of your choice.

You should get the following files:

jkuhn@jkuhn-Studio-XPS-8100:~/devel/lib/zwt-V0.3.0$ ls -lh
total 36K
-rw-r--r-- 1 jkuhn jkuhn   75 2011-11-09 19:29 AUTHORS
-rw-r--r-- 1 jkuhn jkuhn 3,5K 2011-11-09 19:29 build.xml
drwxr-xr-x 4 jkuhn jkuhn 4,0K 2011-11-09 19:29 docs
drwxr-xr-x 3 jkuhn jkuhn 4,0K 2011-11-09 19:29 lib
-rw-r--r-- 1 jkuhn jkuhn  12K 2011-11-09 19:29 LICENSE
-rw-r--r-- 1 jkuhn jkuhn  825 2011-11-09 19:29 README
drwxr-xr-x 4 jkuhn jkuhn 4,0K 2011-11-09 19:29 resources
jkuhn@jkuhn-Studio-XPS-8100:~/devel/lib/zwt-V0.3.0$ 

The docs/ directory contains the JavaScript API documentation and the Java API documentation of the ZWT Tools.

The lib/ directory contains the JavaScript API and the zwt-tools.jar.

The resources/ directory contains the ZWT Themes provided with the distribution and the skeleton of any new ZWT projects.

The ZWT distribution provides an Ant build file to create ZWT projects.

Add ZUIDL to the Eclipse XML Catalog

It is recommended to use Eclipse IDE to develop ZWT applications, you can get Eclipse from the Eclipse web site.

In order to benefit from code assist and validation when writing ZUIDL files, you should add the ZUIDL schema to the Eclipse XML Catalog. Please open Eclipse and go to Window > Preferences and select XML > XML Catalog:

Eclipse XML Catalog preferences
Figure 1 : Eclipse XML Catalog preferences

You can now add the ZUIDL schema to the XML catalog. Enter the path to the schema embedded in lib/zwt-tools.jar in the location field, in my environment I need to enter jar:file:/home/jkuhn/devel/lib/zwt-V0.3.0/lib/zwt-tools.jar!/org/zeleos/zwt/uidl/zwt.xsd and the key http://www.zeleos.org/zwt/zwt-uidl.

Add ZUIDL schema to the XML catalog
Figure 2 : Add ZUIDL schema to the XML catalog

Your environment is now properly set to create ZUIDL files with XML validation and code assist.

Eclipse XML catalog
Figure 3 : Eclipse XML catalog
Deploy the ZWT runtime

The ZWT runtime environment is composed of the JavaScript API, providing the ZWT system and the UI components, and the ZWT Themes. It must be accessible by the application.

By default, the ZWT runtime is deployed within the ZWT application but in a production environment, you may want to deploy it in a central location so that many applications can share the same runtime.

This choice really depends on how you want to deploy your applications. During the development, it's easier to have everything available at the same place that's why the runtime is included in any new project.

The runtime configuration is specified in the HTML file that loads the application. In the header of the file, you should have the following lines:

...
<script type="text/javascript" src="zwt/api/zwt.js"> </script>
<script type="text/javascript">
System.setClassPath(['zwt/api/','js/']);
</script>
<link id="zwt_theme" rel="stylesheet" type="text/css" href="zwt/themes/Default/zwt.css"/>
...

You can modify those path to point to a given runtime. Please note that the runtime should be in the same domain as your application.

Create a ZWT application project

Now that your environment is correctly set, you can create a ZWT application.

Create the project

The ZWT distribution includes an Ant build file to help you create a ZWT application project. You can get Ant (>1.7.0) from the Apache Ant web site.

Simply run ant command at the root of the ZWT distribution to display the help message:

jkuhn@jkuhn-Studio-XPS-8100:~/devel/lib/zwt-V0.3.0$ ant
Buildfile: /home/jkuhn/devel/lib/zwt-V0.3.0/build.xml

help:
     [echo] ==== Zeleos Web Toolkit V0.3.0 ====
     [echo] 		
     [echo] create-project - Create a new ZWT project.
     [echo] 	  -Dname=projectName : The name of the project to create.
     [echo] 	  -Dout=outputDir    : The output directory where to create the project files (default to current).
     [echo] 		

BUILD SUCCESSFUL
Total time: 0 seconds
jkuhn@jkuhn-Studio-XPS-8100:~/devel/lib/zwt-V0.3.0$ 

This utility creates a project you can import in Eclipse. Although you don't have to use Eclipse (a ZWT project is an Ant based project), it is recommended to do so.

Type the following command to create the zwtTutorial project in your Eclipse workspace directory (~/devel/workspace in my environment):

jkuhn@jkuhn-Studio-XPS-8100:~/devel/lib/zwt-V0.3.0$ ant create-project -Dname=zwtTutorial -Dout=../../workspace/
Buildfile: /home/jkuhn/devel/lib/zwt-V0.3.0/build.xml

create-project:
    [mkdir] Created dir: /home/jkuhn/devel/workspace/zwtTutorial
     [copy] Copying 8 files to /home/jkuhn/devel/workspace/zwtTutorial
     [copy] Copied 13 empty directories to 4 empty directories under /home/jkuhn/devel/workspace/zwtTutorial
    [mkdir] Created dir: /home/jkuhn/devel/workspace/zwtTutorial/src/main/webapp/zwt
     [copy] Copying 136 files to /home/jkuhn/devel/workspace/zwtTutorial/src/main/webapp/zwt/api
     [copy] Copying 82 files to /home/jkuhn/devel/workspace/zwtTutorial/src/main/webapp/zwt/themes

BUILD SUCCESSFUL
Total time: 0 seconds
jkuhn@jkuhn-Studio-XPS-8100:~/devel/lib/zwt-V0.3.0$ 

A new project zwtTutorial has been created in the Eclipse workspace.

jkuhn@jkuhn-Studio-XPS-8100:~/devel/working/workspace-manual/zwtTutorial$ tree
.
├── build.xml
└── src
    └── main
        ├── java
        ├── webapp
        │   ├── css
        │   ├── js
        │   ├── META-INF
        │   │   └── MANIFEST.MF
        │   ├── WEB-INF
        │   │   ├── lib
        │   │   └── web.xml
        │   └── zwt
        │       ├─+ api
        │       └─+ themes
        └── zwt
            └── org
                └── zeleos
                    └── sample
                        ├── SampleApp.xml
                        └── Sample.xml

37 directories, 223 files
jkuhn@jkuhn-Studio-XPS-8100:~/devel/working/workspace-manual/zwtTutorial$ 

The project includes the files required by Eclipse (.project and .classpath) to import it in the workspace. Note that an Ant build file is provided to build the project, so you can use another IDE than Eclipse.

To import your project in Eclipse, run Eclipse, select your workspace directory as workspace and go to File > Import.

Import existing project into Workspace
Figure 4 : Import existing project into Workspace

Select "Existing project into Workspace" and select the zwtTutorial directory.

Import projects
Figure 5 : Import projects

Click on Finish, your workspace should now looks like this:

zwtTutorial project in Eclipse Workspace
Figure 6 : zwtTutorial project in Eclipse Workspace
src/main/java/
contains the Java source files for the server side actions. A ZWT application does not require any Java code to run correctly, it is a pure client side application running in a Web Browser.
src/main/zwt/
contains the ZUIDL files describing the user interfaces of the application. A Sample ZUIDL application is included in any new project.
src/main/webapp/
represents the root directory of the web application. This directory will contain everything you need to run the application.
src/main/webapp/css
contains the CSS files of the application.
src/main/webapp/js
contains the JavaScript files of the application.
src/main/webapp/zwt
contains the ZWT runtime with the JavaScript API and the ZWT Themes. The ZWT runtime is included in the application project to ease the development but the runtime can be deployed anywhere as long as it is accessible by the application.
build.xml
The Ant build file used to build the application (compile the ZUIDL files to generate the JavaScript/CSS/HTML files of the application).
Compile and run the Sample application

Our new project contains a Sample application you can compile and run. You need to open the Eclipse Ant view, go in Window > Show View > Ant and drag and drop the project build file (build.xml) to the Ant view, you should see:

Eclipse Ant view
Figure 7 : Eclipse Ant view

Run the zwt.compile target (double click on zwt.compile) to compile the zwtTutorial application. On the console you should see:

Buildfile: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/build.xml
zwt.compile:
[zwt-zuidlc] INFO: ==== Zeleos UIDL Compiler ====
[zwt-zuidlc] INFO: Load ZUIDL Generator
[zwt-zuidlc] INFO: Load ZUIDL Parser
[zwt-zuidlc] INFO: Processing /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/zwt
[zwt-zuidlc] INFO: --------------------------------------------------------------------------------
[zwt-zuidlc] INFO: Compiling org/zeleos/sample/SampleApp.xml
[zwt-zuidlc] INFO:  ---> Validate ZUIDL Source...
[zwt-zuidlc] INFO:  ---> Generate Application JavaScript: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/js/org/zeleos/sample/SampleApp.js
[zwt-zuidlc] INFO:  ---> Generate Application JavaScript Controller: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/js/org/zeleos/sample/SampleAppController.js
[zwt-zuidlc] INFO:  ---> Generate Application JavaScript Controller Callback: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/js/org/zeleos/sample/SampleAppController_callback.js
[zwt-zuidlc] INFO:  ---> Generate CSS: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/css/org/zeleos/sample/SampleApp.css
[zwt-zuidlc] INFO:  ---> Generate Application HTML: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/org.zeleos.sample.SampleApp.html
[zwt-zuidlc] INFO: Compiling org/zeleos/sample/Sample.xml
[zwt-zuidlc] INFO:  ---> Validate ZUIDL Source...
[zwt-zuidlc] INFO:  ---> Generate JavaScript: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/js/org/zeleos/sample/Sample.js
[zwt-zuidlc] INFO:  ---> Generate JavaScript Controller: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/js/org/zeleos/sample/SampleController.js
[zwt-zuidlc] INFO:  ---> Generate JavaScript Controller Callback: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/js/org/zeleos/sample/SampleController_callback.js
[zwt-zuidlc] INFO:  ---> Generate JavaScript Model: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/js/org/zeleos/sample/SampleModel.js
[zwt-zuidlc] INFO:  ---> Generate CSS: /home/jkuhn/devel/working/workspace-manual/zwtTutorial/src/main/webapp/css/org/zeleos/sample/Sample.css
[zwt-zuidlc] INFO: --------------------------------------------------------------------------------
[zwt-zuidlc] INFO: Compiled 2 file(s) with 0 error(s).
BUILD SUCCESSFUL
Total time: 1 second

Your application is now compiled and JavaScript, CSS and HTML code has been generated. If you refresh your project (F5) you should now see:

Compiled zwtTutorial application
Figure 8 : Compiled zwtTutorial application

The org.zeleos.sample.SampleApp.html file is the entry point of the Sample application, you can open it in a Web browser to run the application but it is highly recommended to deploy the application on a web server to avoid security issues that may occur on certain web browsers when directly accessing a local file.

The default Sample application is pretty basic, it simply displays a button in a Part.

The default Sample application
Figure 9 : The default Sample application

Congratulations!!! You have compiled and run your first ZWT application.

Design the UI in ZUIDL
Structure of a ZWT application

A ZWT application is composed of one or more Parts attached to the Window. A Part represents a specific area in the page that actually contains a ZWT user interface. The Part is itself composed of UI components or widgets (Button, TextField...) the user can use to interact with the application.

ZWT Application structure
Figure 10 : ZWT Application structure

Model-View-Controller pattern has become an industry standard and ZWT obviously provides facilities to implement it. You can easily isolate the application logic from the view. For instance, a Part Controller (zwt.control.PartController) is used to handle the user interaction with the Part (zwt.ui.Part) and to read or update the Model accordingly (zwt.model.Model).

The ZUIDL compiler generates the required code to use the MVC pattern for every application defined in ZUIDL.

The Zeleos User Interface Description Language

ZWT provides a complete UI Description Language: the Zeleos UI Description Language or ZUIDL. It is used to describe the graphical user interfaces of the applications. Using such language has many advantages:

Reusability
A User interface described in such language is easily reusable among applications as it guarantees the isolation of the UI code.
Flexibility
A UI Description language makes it easy to modify an existing user interface by simply changing a simple XML file and generate the corresponding UI code. For instance, you can completely change the layout with almost no impact on the application code. You can also imagine interpreting the language differently to adapt user interfaces to different devices or other technologies (Java Swing, XUL,...).
Focus on the Design
It's also easier to focus upon the design of a user interface while using an appropriate language instead of writing tedious and tiresome UI code a compiler can better generate for you.
Simplicity
Above all, it's simpler to describe a user interface with an adhoc language.

Basically, user interfaces are described in XML files following the ZUIDL grammar and the ZUIDL Compiler generates the corresponding JavaScript, CSS and HTML code.

ZUIDL defines two types of files to describe user interfaces:

zwt:application
It is used to define an application. It basically contains the declaration of the Part controllers to include in the application and the actions to execute on global page events (window resize...).
zwt:part (or zwt:popup or zwt:popupWindow)
A part typically represents an isolated part of an application defining its own UI and controller.

The HTML file is only generated if the ZUIDL source file is describing an application, it represents the entry point of the application.

Using ZUIDL to develop ZWT applications

ZUIDL files are located in src/main/zwt/, you can have a look at the Sample ZUIDL files in the zwtTutorial project. Just like in Java a ZUIDL file is stored in a directory structure that corresponds to its namespace. Sample ZUIDL files are in the org.zeleos.sample namespace and they are then stored in the org/zeleos/sample directory.

Define the Application

org/zeleos/sample/SampleApp.xml describes the Sample application:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	This is a sample application:
	- id must be the file name
	- namespace the path to the file
-->
<zwt:application id="SampleApp" namespace="org.zeleos.sample" title="Sample App" theme="Default" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zwt="http://www.zeleos.org/zwt/zwt-uidl" xsi:schemaLocation="http://www.zeleos.org/zwt/zwt-uidl http://www.zeleos.org/zwt/zwt-uidl ">
	<!-- 
		Sample App has only one part, you can add as many as you want
		When declaring a part, you must provide:
		- an id
		- the full namespace to the controller class
	 -->
	<zwt:controller id="SampleApp" class="org.zeleos.sample.SampleController"/>
</zwt:application>

The id of the application has to be the same as the file name and as stated before, the namespace must match the directory structure.

The title of the application corresponds to the HTML title displayed in the Web Browser.

The theme specifies the ZWT theme to use in the application.

The Sample application contains one part controller defined by the org.zeleos.sample.SampleController class. The controller id is used to identify the part in the Window and also to specify the id of the DIV that will host it in the page. In our example, the DIV element should have SampleApp as ID.

Apart from declaring the controllers of the application, you can bind any application events to an action defined in the application controller. If your Eclipse environment is correctly set, use the code assist (Ctrl+space) to see what you can do:

ZUIDL Code assist
Figure 11 : ZUIDL Code assist

We can for instance map the didResizeWindow method to the windowResize event.

Bind the windowResize event to the didResizeWindow action
Figure 12 : Bind the windowResize event to the didResizeWindow action
Define the Part

org/zeleos/sample/Sample.xml describes the Sample Part declared in the Sample application.

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	This is the sample part definition:
	- id must be the file name
	- namespace the path to the file
	
	A part is a top UI component that can be included in an application. For each part, a controller is created that contains your custom code.
-->
<zwt:part id="Sample" namespace="org.zeleos.sample" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zwt="http://www.zeleos.org/zwt/zwt-uidl" xsi:schemaLocation="http://www.zeleos.org/zwt/zwt-uidl http://www.zeleos.org/zwt/zwt-uidl ">
	<zwt:button id="HelloButton" fill="none">
		<zwt:set name="Text" value="'Hello World'"/>
		<zwt:action name="hello" event="click"/>
	</zwt:button>
</zwt:part>

As for the application, the id has to be the same as the file name and the namespace must match the directory structure.

A Part is a single container (zwt.ui.container.SingleContainer) so it can only contain one widget. In our example, it contains a button with 'Hello World' as a label and you can see that the hello action is bind to the click event.

All the Widgets can be used in ZUIDL, you can refer to the ZUIDL Reference documentation to see how to use them. We can for instance use a panel to improve a bit our Sample application.

<?xml version="1.0" encoding="UTF-8"?>
<zwt:part id="Sample" namespace="org.zeleos.sample" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zwt="http://www.zeleos.org/zwt/zwt-uidl" xsi:schemaLocation="http://www.zeleos.org/zwt/zwt-uidl http://www.zeleos.org/zwt/zwt-uidl ">
	<zwt:verticalPanel id="SamplePanel">
		<zwt:button id="HelloButton" weight="1" fill="none">
			<zwt:set name="Text" value="'Hello World'"/>
			<zwt:action name="hello" event="click"/>
		</zwt:button>
		<zwt:label id="HelloLabel" weight="1">
			
		</zwt:label>
	</zwt:verticalPanel>
</zwt:part>

The SamplePanel is now the content widget of the Sample Part, it's a vertical panel (zwt.ui.panel.VerticalPanel) that displays widgets vertically. We have added a simple label (zwt.ui.Label) that will be used to display some text.

The weight attribute is used by vertical and horizontal panels to define the space occupied by a widget in the panel. The HelloLabel and the HelloButton occupy the same space in the panel. The fill attribute is used to indicate whether the widget should fill the available space horizontally and/or vertically. The default setting depends on the Widget, in the case of the HelloButton, all the space available is used.

Set Widget properties

Widget properties can be set with an attribute on the widget tag like the fill attribute or the weight attribute but most of the time, widget properties are set through accessor methods using the set tag.

...
<zwt:widget id="MyWidget">
	...
	<zwt:set name="$NAME" value="$VALUE"/>
	...
</zwt:widget>				
...

The properties you can set depend on the widget, so please refer to the ZUIDL schema or the ZWT JavaScript API to know the accessor methods defined for a given widget.

The value of the property is specified in JavaScript so if the property Text is a String, you need to enter 'My text', otherwise you'll get a JavaScript error at runtime.

Handle User Events

A user typically interacts with an application through its user interface which basically emits events on user actions like a mouse click or a key press. The action tag is used to bind an event to a controller's action.

...
<zwt:widget id="MyWidget">
	...
	<zwt:action name="$NAME" event="$EVENT_TYPE"/>
	...
</zwt:widget>				
...

The name of the action correponds to the name of the controller's method to execute. The event type depends on the Widget, for instance a button and a list box don't emit the same type of events.

The ZUIDL Compiler generates an empty method in the Controller class for each action defined on a Widget.

As for the properties, please refer to the ZUIDL schema or the ZWT JavaScript API to know the type of events emitted by a given widget.

There's almost no limit in what you can do with ZUIDL. I encourage you to have a look at the ZUIDL Reference documentation and the ZWT JavaScript API to have a better understanding what you can really do.

You should also have a look at the ZWT Samples that cover a lot of use cases you may be interested in your own applications.

Compiling a ZWT Application

A ZWT project uses the ZWT Tools to generate the JavaScript, CSS and HTML code of the application from the ZUIDL files.

Every project provides an Ant build file to compile the ZUIDL files. The build.xml at the root of the project defines the following targets:

build.clean
Clean the build files.
build.webapp
Build the web application, including Java code and package it in a WAR.
help [default]
Display the help message.
zwt.compile
Compile the ZUIDL files and generate the JavaScript, CSS and HTML files.
zwt.compile.css
Generate the CSS files only.
zwt.compile.html
Generate the HTML files only.
zwt.compile.js
Generate the JavaScript files only.
zwt.package
Package the applications defined in the project. Packaging your application actually improves the performances by reducing the footprint and the loading time.

The ZUIDL Compiler used in the build file compiles the ZUIDL source files and generates the files of the applications.

The ZUIDL Compiler
Figure 13 : The ZUIDL Compiler

It generates different files depending on the type of the ZUIDL source file. You can call the zwt.compile target in the zwtTutorial project to generate all the project files. Don't forget to refresh your workspace to see the generated files in Eclipse. You can also call the other targets zwt.compile.js, zwt.compile.css or zwt.compile.html if you want to generate or regenerate the JavaScript files, the CSS files and the HTML files separately.

JavaScript

The JavaScript files are stored in the src/main/webapp/js source folder.

JavaScript files
Figure 14 : JavaScript files

You can modify the selected files which should basically contain the functional code of the application. You should never modify the other files as they are always regenerated by the compiler.

For an application ZUIDL source file, the compiler generates the following files:

[FILE].js
The main application file defining the main method.
[FILE]Controller.js
The application Controller class definition.
[FILE]Controller_callback.js
The application controller callback extension containing the action methods specified in the ZUIDL source file.

No Model is generated by the Compiler for an application because it doesn't have much meaning in that context.

The functionnal code of the application should go in the controller callback extension file that defines the action methods. This file is updated by the compiler if it already exists, all the other files are regenerated.

For a part ZUIDL source file, the Compiler generates the following files:

[FILE].js
The Part class with all the UI code corresponding to the ZUIDL source file.
[FILE]Controller.js
The Part Controller class.
[FILE]Controller_callback.js
The Part controller callback extension containing the action methods specified in the ZUIDL source file.
[FILE]Model.js
The Model attached to the controller that should store the data displayed in the Part.

In that context, the Model has a real role to play since the user can actually view the data displayed in the Part and modify them through the controller when interacting with the part.

As for the application, the functionnal code should go in the controller callback extension and the model, all the other files are systematically regenerated by the compiler.

CSS

The CSS files are stored in the src/main/webapp/css source folder.

CSS files
Figure 15 : CSS files

The compiler generates one CSS file per ZUIDL source file. It defines empty CSS selectors to modify the style of the different widgets.

These files are only updated by the compiler if they already exist, so you can safely modify them.

HTML

The HTML files are stored in the src/main/webapp directory.

HTML files
Figure 16 : HTML files

The compiler generates one HTML file per application ZUIDL source file. The name of the HTML file is the qualified name of the application. It represents the entry point of the ZWT application.

The HTML files are only generated if they don't already exist, you can safely modify them.

Develop the functional code

The functional code defines the behavior of the application. It is basically executed when the user interacts with the application. It has to be defined in a controller in respect of the MVC pattern.

The controller callback extension files regroups all the methods bound to UI events, the functional code should naturaly go in these files. The controller handles events and can modify the model and/or the view. Therefore, an action method in a controller can interact with both the model and the view.

Open the org/zeleos/sample/SampleAppController_callback.js Controller extension. If you remember, we have declared the didResizeWindow on windowResize event in the application ZUIDL file.

namespace('org.zeleos.sample');

include('org.zeleos.sample.SampleAppController');

org.zeleos.sample.SampleAppController.prototype.didResizeWindow = function(zwt_ui_Window_window, zwt_event_WindowEvent_event) {
};

The didResizeWindow is correctly defined in the SampleAppController and should normally be executed when the browser window is resized.

Let's display the viewport dimension in the HelloLabel when the window is resized.

namespace('org.zeleos.sample');

include('org.zeleos.sample.SampleAppController');

org.zeleos.sample.SampleAppController.prototype.didResizeWindow = function(zwt_ui_Window_window,zwt_event_WindowEvent_event) {
	this.getSampleApp().getPart().getHelloLabel().setText('Height: ' + zwt_ui_Window_window.getInnerHeight() + 'px, Width: ' + zwt_ui_Window_window.getInnerWidth() + 'px');
};

As you can see the application controller provides an accessor to get the SampleApp controller.

We have also defined an action in the SamplePart. The controller should normally stores the data being displayed in the part in the model. Since our sample application is pretty basic, it doesn't make much sense to use the model for now.

namespace('org.zeleos.sample');

include('org.zeleos.sample.SampleController');

org.zeleos.sample.SampleController.prototype.hello = function(zwt_ui_Button_button, zwt_event_ClickEvent_event) {
	this.getPart().getHelloLabel().setText('Hello World!!!');
};

The hello method should be executed when the user clicks on the HelloButton and simply displays 'Hello World!!!' in the HelloLabel.

You can now run the application and see the result.

The Sample application
Figure 17 : The Sample application

When resizing the window the new viewport dimension is displayed in the label. When clicking on the button, as expected, 'Hello World' is displayed in the label.

You may have noticed the namespace and include methods in the controller extension. They are used to indicate the namespace of the file and its dependencies to other classes.

Please have a look at the ZWT JavaScript API to have a detailed documentation on the controller (zwt.control.PartController), the model (zwt.model.Model) and the widgets.

Handle events

Although event handling is specified in ZUIDL through the action tag, it may be interesting to know how events are handled in a ZWT application.

First of all, all the events are not necessarily emitted by user interface components, they may also be emitted by a model when it is updated or any kind of objects. These various kind of events are handled in the same way using event handlers registered on an event manager associated to an Object that emits the events. This is the typical Observer pattern used in many UI frameworks.

A handler function is registered to the appropriate event manager of an object for a specific event type. An object emits events when its state changes in some ways programmatically or on a user action. The event is then handled by the appropriate event manager which delegates the event processing to the handlers registered for the type of the event.

ZWT Event Handling
Figure 18 : ZWT Event Handling

In practice here is how we add a click event handler to the click event manager of the HelloLabel:

namespace('org.zeleos.sample');

include('org.zeleos.sample.SampleController');
include('zwt.event.ClickAdapter');

org.zeleos.sample.SampleController.prototype.hello = function(zwt_ui_Button_button,zwt_event_ClickEvent_event) {
	this.getPart().getHelloLabel().setText('Hello World!!!');
	
	var clickEventHandler = function(zwt_ui_Label_label, zwt_event_ClickEvent_event) {
		zwt_ui_Label_label.setText('');
		zwt_ui_Label_label.getClickEventManager().removeClickHandler(clickEventHandler);
	};
	this.getPart().getHelloLabel().getClickEventManager().addClickHandler(clickEventHandler);
};

When the HelloButton is clicked, a click event handler is registered to the click event manager of the HelloLabel. And when the HelloLabel is clicked, its text is cleared and the handler is unregistered.

Work with the MVC Pattern

You already had a small overview of the MVC Pattern is used in ZWT, but we didn't go deep into it.

As stated in the previous section, a model can also emits events when its state changes and we can then handle them with an event manager. This is particularily powerful to have parts communicating with each other. Basically, a part controller may monitor the changes on the model of another part by registering an event handler to its event manager. We'll complexify the Sample application to play a bit with controllers and models.

Let's create a new ZUIDL file SamplePopup.xml in the org.zeleos.sample package. If you have correctly set your Eclipse envrionment, you should be able to have code assist provided by the ZUIDL XML schema.

Select org.zeleos.sample package in the src/main/zwt source folder and press Ctrl+N to create a new ZUIDL file:

Create a new ZUIDL file
Figure 19 : Create a new ZUIDL file

Choose to create the file from an XML schema file:

Create a new ZUIDL file from an XML schema file
Figure 20 : Create a new ZUIDL file from an XML schema file

Then select the ZUIDL schema in the XML Catalog

Select the ZUIDL schema
Figure 21 : Select the ZUIDL schema

We want to create a Popup Window so the root element of the file must be popupWindow:

Create a PopupWindow
Figure 22 : Create a PopupWindow

A new SamplePopup.xml ZUIDL file has been created, we need to specify the id and the namespace that must match the file name and the directory structure.

Our Sample popup contains only a simple text field that will be used to enter a name.

<?xml version="1.0" encoding="UTF-8"?>
<zwt:popupWindow id="SamplePopup" namespace="org.zeleos.sample" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zwt="http://www.zeleos.org/zwt/zwt-uidl" xsi:schemaLocation="http://www.zeleos.org/zwt/zwt-uidl http://www.zeleos.org/zwt/zwt-uidl ">
	<zwt:textField id="NameTextField">
		<zwt:action name="onKeyUp" event="keyUp"/>
	</zwt:textField>
	<zwt:set name="Title" value="'Enter your name:'"/>
	<zwt:set name="Dimension" value="250,75"/>
	<zwt:set name="Maximize" value="false"/>
	<zwt:set name="Minimize" value="false"/>
	<zwt:set name="Resizable" value="false"/>
</zwt:popupWindow>

You need to recompile the zwtTutorial project to generate the JavaScript and CSS files of the new SamplePopup.

Now that we have created the sample popup, we have to modify the hello method in the SampleController to open it the first time the user clicks on the HelloButton.

namespace('org.zeleos.sample');

include('org.zeleos.sample.SampleController');
include('zwt.model.ModelAdapter');
include('org.zeleos.sample.SamplePopupController');
include('org.zeleos.sample.SamplePopupController_callback');

org.zeleos.sample.SampleController.prototype.hello = function(zwt_ui_Button_button,zwt_event_ClickEvent_event) {
	if(this._samplePopupController == null) {
		this._samplePopupController = new org.zeleos.sample.SamplePopupController();
		
		this._samplePopupController.getModel().getModelEventManager().addNotifyHandler(function(zwt_model_Model_model, zwt_model_ModelEvent_event) {
			this.getPart().getHelloLabel().setText('Hello ' + zwt_model_Model_model.name + '!!!');
		}.bind(this));

		zwt.ui.Window.getWindow().addPopup(this._samplePopupController.getPart());
		this._samplePopupController.getPart().show();
	}
};

The hello method now creates a SamplePopupController, registers an event handler to the model event manager of the popup's model and finally shows the popup which needs first to be attached to the window.

When the model of the sample popup is modified, an event should be emitted to notify its event manager that its state has changed. The event manager then dispatches the event to the registered event handlers. In our sample application, the handler sets the text of the HelloLabel using the name attribute of the sample popup model.

Basically when the SamplePopupController modifies its Model, it must send a event to notify the registered handlers that its state has changed, this is done in the onKeyUp method.

namespace('org.zeleos.sample');

include('org.zeleos.sample.SamplePopupController');
include('zwt.event.ModelEvent');

org.zeleos.sample.SamplePopupController.prototype.onKeyUp = function(zwt_ui_TextField_textField, zwt_event_KeyboardEvent_event) {
	this.getModel().name = this.getPart().getNameTextField().getText();
	this.getModel().onEvent(new zwt.model.ModelEvent(zwt.model.ModelEvent.NOTIFY));
};

The following steps describe the complete process:

Part communication
Figure 23 : Part communication

You can now test the sample application and see that the behavior is as expected: when you click on the HelloButton the SamplePopup shows up and when you enter some text in the NameTextField the HelloLabel is automatically updated.

The Sample application
Figure 24 : The Sample application

In order to completely use the MVC pattern, we should also register a model event handler on the sample model. We can do this when the SampleController is initialized:

<?xml version="1.0" encoding="UTF-8"?>
<zwt:part id="Sample" namespace="org.zeleos.sample" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zwt="http://www.zeleos.org/zwt/zwt-uidl" xsi:schemaLocation="http://www.zeleos.org/zwt/zwt-uidl http://www.zeleos.org/zwt/zwt-uidl ">
	...
	<zwt:action name="didInitController" event="controllerInit"/>
</zwt:part>

In the didInitController method, we simply register an event handler on the model event manager:

...
org.zeleos.sample.SampleController.prototype.didInitController = function(zwt_control_PartController_controller, zwt_control_PartControllerEvent_event) {
	this.getModel().getModelEventManager().addNotifyHandler(function(zwt_model_Model_model, zwt_model_ModelEvent_event) {
		this.getPart().getHelloLabel().setText(zwt_model_Model_model.message);
	}.bind(this));
};
...

We can also modify the event handler we have registered on the sample popup model:

...
org.zeleos.sample.SampleController.prototype.hello = function(zwt_ui_Button_button, zwt_event_ClickEvent_event) {
	if(this._samplePopupController == null) {
		this._samplePopupController = new org.zeleos.sample.SamplePopupController();
		this._samplePopupController.getModel().getModelEventManager().addNotifyHandler(function(zwt_model_Model_model, zwt_model_ModelEvent_event) {
			this.getModel().message = 'Hello ' + zwt_model_Model_model.name + '!!!';
			this.getModel().onEvent(new zwt.model.ModelEvent(zwt.model.ModelEvent.NOTIFY));
		}.bind(this));
		zwt.ui.Window.getWindow().addPopup(this._samplePopupController.getPart());
		this._samplePopupController.getPart().show();
	}
};
...

Now all the views in the sample application are synchronized with their model.

Customize the application
Edit the application CSS files

The ZUIDL compiler generates default CSS files for the applications and the parts. You can (and probably) should modify these default settings to customize your application.

By default, the dimension of a part is set to 800x600 which is definitely too big for the sample application.

The CSS files are stored in src/main/webapp/css. To modify the dimension of the sample part, you can edit the SampleApp.css file:

@CHARSET "UTF-8";
	
@IMPORT url("../../../org/zeleos/sample/Sample.css");

#sampleSlot {
	width: 300px;
	height: 100px;
	margin: 50px auto auto auto;
}

You can also modify the CSS style of the HelloLabel in the Sample.css file:

...
#HelloLabel .zwt_label {
	color: red;
	font-size: 160%;
	font-weight: bold;
	text-align: center;
	border: 1px solid #A4A4A4;
	margin: 5px;
	padding-top: 6px;
}
...

Now the Sample application should look much better:

The Sample application
Figure 25 : The Sample application

The ZUIDL compiler generates empty CSS selectors for all the widgets in the application to facilitate the customization. You can also get information about widgets CSS rules in the ZWT JavaScript API documentation.

Use ZWT Themes

The Theme to use is specified in the HTML file of the application. You can safely modify this file:

...
<link id="zwt_theme" rel="stylesheet" type="text/css" href="zwt/themes/HighContrast/zwt.css"/>
...

The ZWT distribution provides two themes: the Default theme and the HightContrast theme. If you run your application now, you can see the difference:

The Sample application with HighContrast theme
Figure 26 : The Sample application with HighContrast theme

Note that you can also dynamically change the ZWT theme at runtime using the setTheme method on the zwt.ui.Window.

A ZWT theme basically defines all the CSS rules for all the widgets in the framework. As themes are defined in pure CSS, creating your own theme is not that tedious.

Package the application

When the application is developed and ready to be deployed in a production environment, you may want to package it to get rid of the loading time overhead introduced by the dependency loading system.

The zwt.package Ant target is used to package the application. It generates a new HTML file and a packaged, optimized JavaScript file for each application ZUIDL file.

Package the sample application
Figure 27 : Package the sample application

Now if you open org.zeleos.sample.SampleApp-pack.html, you'll see that the sample application loads much faster.

Extend the API

ZWT is an extensible framework that let's you create your own themes or create your own widgets. Indeed the API makes it very easy to override existing widgets or create custom ones.

Going further

If you want to participate in the development of the Zeleos Web Toolkit, please get the source code from the subversion repository and check the ZWT development page.

We also encourage you to consult the ZWT API documentation and the Zeleos UIDL reference documentation.

If you need support, please use the mailing lists.

We also strongly recommand to have a look at the demos and samples to see what you can do with Zeleos Web Toolkit.