Copyright © 2011, Zeleos Project Team
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.
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.
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:
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
.
Your environment is now properly set to create ZUIDL files with XML validation and code assist.
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.
Now that your environment is correctly set, you can create a ZWT application.
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.
Select "Existing project into Workspace" and select the zwtTutorial
directory.
Click on Finish, your workspace should now looks like this:
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:
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:
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.
Congratulations!!! You have compiled and run your first 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.
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.
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:
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:
The HTML file is only generated if the ZUIDL source file is describing an application, it represents the entry point of the application.
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.
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:
We can for instance map the didResizeWindow
method to the windowResize
event.
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.
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.
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.
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:
The ZUIDL Compiler used in the build file compiles the ZUIDL source files and generates the files of the applications.
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.
The JavaScript files are stored in the src/main/webapp/js
source folder.
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:
main
method.
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:
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.
The CSS files are stored in the src/main/webapp/css
source folder.
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.
The HTML files are stored in the src/main/webapp
directory.
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.
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.
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.
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.
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.
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:
Choose to create the file from an XML schema file:
Then select the ZUIDL schema in the XML Catalog
We want to create a Popup Window so the root element of the file must be 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:
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.
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.
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 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.
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:
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.
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.
Now if you open org.zeleos.sample.SampleApp-pack.html
, you'll see that the sample application loads much faster.
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.
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.