home
products
education
support
partners
company

introduction

get started

articles

manual

tutorials

reference docs

case studies

knowledge base

goodies

screenshots

demos

echoes

Carousel zone




home

forums

downloads

bugs

mailing list
XUI Zone - manual

number of ratings 0
average rating 0.00

9 Building pages with XML

As we have already seen, Carousel allows pages to be built without having to write Java code to setup the user interface components. The functionality afforded by this process is not complex and contributes greatly towards the goal of removing trivial screen building from your Java code.

Pages built with Carousel can be integrated with pages coded directly in Java and with Java classes containing just your application logic. Very little change is needed to the application to employ this package, in fact all you need do is use the XML page names when making requests to show a page.

The next few sections provide an overview of what can be done with the XML declarations. Later chapters go into greater detail about specific features such as validation and data binding.

Basic form building

The basic components and layout of a user interface can be described in an external XML. The XML file contains entries for the individual components on the page which are processed by the Carousel framework when it constructs a page.

You can think of a page as panel or container that holds your user interface components. The page is constructed from either a Java class or from an XML file by the page manager component built into the Carousel framework.

In processing the XML the framework constructs a page object and adds the specified components to it. The page and the objects added are all normal Java components so once the page has been setup you can interact with all the components as though the page had been constructed with Java code.

A snippet of the XML file for the form shown above is shown below.

Code Sample 9-1 - A basic address page described in XML

< ?xml version= "1.0" encoding= "UTF-8" ?>

< XPage >

< Components >

< Panel x= "10" y= "10" w= "210" h= "80" border= "1" >

< Label x= "5" y= "10" w= "90" h= "20" content= "Firstname:" style= "prompt" />

< Edit x= "100" y= "10" w= "100" h= "20" content= "Joe" />

< Label x= "5" y= "30" w= "90" h= "20" content= "Surname:" style= "prompt" />

< Edit x= "100" y= "30" w= "100" h= "20" content= "Bloggs" />

< Label x= "5" y= "50" w= "90" h= "20" content= "Age:" style= "prompt" />

< Edit x= "100" y= "50" w= "100" h= "20" content= "38" />

< /Panel >

< /Components >

< /XPage >

Perhaps the most important thing to note about this sample is that there is absolutely no Java code written in order to display it.

This absence of a Java class leads to the important question of how it is possible for a page to be both and XML file and a Java class. The answer of course is that it isn't. Carousel constructs an instance of a Java class, the XPage class by default and populates it with the components you have specified in the XML.

Indeed, you can even customize this page class to add your own functionality and behavior by specifying the class to create and populate (as in the example below where an instance of XQuestionPage is constructed).

Much can be achieved with this simple step of putting the user interface declaration into XML. Some additional processing and aggregation of content can be performed, for example by adding a new XML element it is possible to allows for repeated inclusion of children.

Thus one page can be composed of multiple pages.

Code Sample 9-2 - An advanced page decription showing repeating elements, embedded data etc

< ?xml version= "1.0" encoding= "UTF-8" ?>

< XPage next= "Finished" layout= "Border" class= "net.xoetrope.xforms.awt.XQuestionPage" >

< Components >

< Panel layout= "Box" layoutStyle= "0" constraint= "center" >

< Repeat while= "hasMoreQuestions()" >

< Include file= "template" />

< /Repeat >

< /Panel >

< /Components >

This aggregation further extends the separation of UI from the data model by allowing multiple instances of a component or set of components to be included. The data or content displayed by these components can be even pulled from a data model on demand.

Built-in components

Carousel includes a set of built-in components that can be used interchangeably in Swing or AWT applications. These components are listed below along with a brief description.

The XML element name is shown in brackets[]. Note that this name is not case sensitive.

Table 9-1 - Component types

Component

Usage

XButton

A simple push button type. [ Button ]

XCheckbox

A check box normally used to indicate options [ Checkbox ]

XComboBox

A drop down list used to display a fixed set of choices or options.[ Combo ]

XDialog

A holder for a page that is displayed in a popup window or dialog. The dialog can be modal or modeless. [requires a separate page to be shown, the dialog is actually constructed implicitly when the showDialog method is used]

XEdit

A basic input field. [ Edit ]

XHotspotImage

An image that when clicked in certain areas triggers events. [ Hotspot ]

XImage

A simple image display component. [ Image ]

XImageMap

An extension of XImage that allows querying of the mouse coordinates. [ ImageMap ]

XLabel

A simple static piece of text that does not permit user interaction. Text can be flowed over multiple lines. [ Label ]

XList

A simple list. [ List ]

XMenu

A menu, either drop down or popup, depending on the context. [ Menu ]

XMenuBar

A menu bar for holding menus in an application. [ MenuBar ]

XMenuItem

An individual menu item. Selection triggers an action. [ MenuItem ]

XMessageBox

A popup dialog for display of simple messages, warnings or errors. [constructed implicitly by calling showMessage ]

XMetaContent

A text field that can display some simple meta content, altering typefaces and embedding tables and so on. [ MetaContent ]

XPanel

A container that can holder other components. The container can be displayed with a border and is considered to 'own' its children. [ Panel ]

XPassword

An edit field that masks the user input so that an observer can not see what has been keyed. [ Password ]

XRadioButton

A radio button control for selection of mutually exclusive options. [ RadioButton ]

XScrollPane

A container that allows scrolling of its content. [ ScrollPane ]

XScrollableMetaContent

A version of the meta content control that supports scrolling of its content. [ ScrollabelMetaContent ]

XTab

An individual Tab for a tab pane. [Added implicitly when a child panel is added to a tab panel]

XTable

A component that displays tabular data. [ Table ]

XTabPanel

A contain that allows access to multiple child panels by selection of a tab. [ TabPanel ]

XTextArea

A multiline text field. [TextArea]

More details of these controls can be found in the appendix.

The component can be used by creating an child element of the ' Components ' element or one of its children (a panel for instance). The new element should begin with the name of the component type (as listed above in parenthesis), for example a new button is described as

Code Sample 9-3 - Specifying a button

The actual attributes depend on the component type.

Common properties

Although the full set of attributes for a component are specific to that component, a subset of these attributes are shared by all components. These attributes are optional and need not be specified in all cases.

The attribute names in the XML are case insensitive, but generally they are specified in lower case. Some of the attribute properties are used for constant values, for example when specifying alignment term like 'left' and 'right' are used. In such cases the attribute values are also case insensitive.

Table 9-2 - Common component properties

Property

Usage

name

The component name as it will be used for lookups. If you intend interacting with a component it is a good idea to name the component. Failing this an index can be used to access the component and this depends on the order in which components were added.

x

T he 'x' or left coordinate of the component (if absolute positioning is being used).

y

The 'y' or top coordinate of the component (if absolute positioning is being used).

w

The width dimension of the component (if absolute positioning is being used) .

h

The height dimension of the component (if absolute positioning is being used).

style

The component style name, referencing the style file. This will set the colors and font of the component

content

The component content depending on the component type. Frequently this refers to the text displayed by the component.

Panels

Panels differ from other components in that they are designed to contain other components. The ' panel ' element needs to span the children to conform to normal XML document structure e.g.

Code Sample 9-4 - A panel

< ?xml version= "1.0" encoding= "UTF-8" ?>

< XPage >

< Components >

< Panel layout= "Box" layoutStyle= "0" constraint= "center" border= "1" >

< Label x= "5" y= "10" w= "90" h= "20" content= "Firstname:" style= "prompt" />

< Edit x= "100" y= "10" w= "100" h= "20" content= "Joe" />

< /Panel >

< /Components >

Panels may also specify a border attribute so as to display a thin line border around the edges of the panel. The value for the border attribute should be '1' for a border or '0' for none or else the attribute can be omitted.

The panel is considered to own its children so showing or hiding a panel will also show or hide its children.

A panel can include a layout manager by specifying the 'layout' attribute. In the above example the layout is set to the ' Box ' layout type. If a layout is being used each of its children should be given a 'constraint' attribute.

ScrollPanes

Scrollpanes have many of the same properties as panels, however they implicitly have associated layout managers. These layout managers will in some circumstances to resize the children of the scrollpane, for example where tables are being used.

Layout managers are not always necessary with the scrollpanes and in such circumstances you will need to appropriately size the scrollpane and its content.

Frames

Frameset support is included to allow for inclusion of non swapping areas of the screen such as toolbars, navigation controls, headers and sidebars. Each frame contains an XPage and is positioned using a layout manager. Navigation commands such showPage have been enhanced to take the name of the target frame.

Code Sample 9-5 - A frameset

< ?xml version= "1.0" encoding= "UTF-8" ?>

< FrameSet >

< Frame name= "header" constraint= "NORTH" width= "640" height= "80" content= "header" />

< Frame name= "content" constraint= "CENTER" width= "640" height= "350" content= "Welcome" />

< Frame name= "footer" constraint= "SOUTH" width= "640" height= "50" content= "footer" />

< /FrameSet >

By default the frames are described in the frames.xml file an example of which is shown below.

The container for the frames or target areas has a BorderLayout .

Using imported pages

As mentioned earlier pages can be imported into others by using the import tag in the XML file. Importing pages allows reuse of common page elements and also helps promote consistency within the user interface.

In this example we're importing a simple navigation screen in two other files. The imported file defines two buttons within a panel as follows

Code Sample 9-6 - The included file

< Component type= "XPANEL" x= "10" y= "180" w= "210" h= "40" border= "1" >

< Button name= "btnProceed" x= "40" y= "10" w= "60" h= "20" content= "Next" />

< Button name= "btnPrevious" x= "110" y= "10" w= "60" h= "20" content= "Previous" style= "btnReverse" />

< /Component >

Now, in order to use this screen we simply use the Include tag within another screen.

Code Sample 9-7 - The include statement

< Include file= "xmlimportnav" >

And to attach events to the buttons we add events for each screen.

Code Sample 9-8 - Attaching an event

< Events >

< Event name= "nextPage" target= "btnProceed" type= "MouseHandler" next= "xmlimportsamplescr2" />

< /Events >

Carousel provides support for the Include element so that it can be nested within the Components element or its children. An example of this can be seen in conjunction with the Repeat element.

The declarations within the included file are processed as though they are part of the page within which they are included. Therefore an include 'page' does not actually cause one page to be instantiated within another.

Repeat elements 1

The Repeat element includes a while attribute that specifies the criteria for repetition. In the example above a method returning a boolean value is invoked.

The method is part of the XQuestionPage class, but any method could be used as an attribute value so long as the method name is followed by a pair of brackets. In fact any attribute in the XML can be replaced by a method call when using the FormZ package.

Within the Repeat element is an Include element. In the example this points to the following XML file.

Code Sample 9-9 - The complete example

< ?xml version= "1.0" encoding= "UTF-8" ?>

< XPage >

< Components >

< Panel layout= "Border" style= "question" w= "640" h= "75" constraint= "center" >

< Panel layout= "Flow" style= "question" constraint= "north" >

< Image name= "icon" w= "20" h= "20" content= "qmark.gif" style= "Question" />

< Label name= "qtext" w= "620" h= "20" content= "getNextQuestion()" style= "Question" />

< /Panel >

< Panel layout= "Box" layoutStyle= "1" constraint= "center" w= "630" h= "55" >

< Repeat while= "hasMoreOptions()" >

< RadioButton w= "100" h= "20" content= "getNextOption()" name= "getOptionId()"
style= "question/response" />

< /Repeat >

< /Panel >

< /Panel >

< /Components >

Again a repeat element is used as are more method calls. The main file is a form from a survey application that displays a set of question while the included file represents a template for each question. The data for each question is pulled from a data model via the XQuestionPage class. The results can be seen in the screen shot below.

Layout managers

Layout managers can be used in Carousel via both Java code and XML. In the Java API a new method has been added to the ComponentFactory class to allow components to be constructed with a layout manager as an alternative to the absolute coordinates.

The new method takes one parameter, the layout manager constraint.

Code Sample 9-10 - Adding a component via Java (API)

public Component addComponent( int type, Object constraint );

The constraint depends on the type of layout manager being used, so for example for a BorderLayout the constraints are BorderLayout.NORTH, BorderLayout.WEST and so on. However before using this method of adding components the LayoutManager needs to be set. Again this can be accomplished with the component factory by calling the method within Java

Code Sample 9-11 - Specifying a layout (API)

public LayoutManager addLayout( layoutType );

The layoutType can be one of the XPage constants:

Table 9-3 - Layout types

Type

Behavior

Border

Aligns components in five zone, along the edges (North, South, East and West) of the container or in the centre of the container.

Flow

Aligns components horizontally or vertically in the order in which they are added.

Card

Fills the container with one of the components, like a rolodeck.

Grid

A tabular type of layout where components can be placed in a grid cell in the order in which they are added

GridBag

A complex layout. No support is given within the XuiEditor

Box

Arrange components in a row or column.

Scale

Reposition the components relative to the container size and in proportion to the original container size and absolute coordinates. A variation on the null layout.

Spring

A complex layout, not yet supported in the XuiEditor.

Guide

The XuiEditor preferred layout. Components are aligned along the visual guides set out in the editor.

null

No layout. Use absolute positioning.

In the XML page descriptions layout managers can be specified for both pages and panels. An example is shown below. For both the XPage element and Panel components two attributes can be used: ' layout ' and ' layoutStyle '. The layout attribute specifies the layout type ( Border, Flow, Card, Grid or GridBag ) and is case insensitive. If the attribute is omitted a NULL layout is assumed. The layout attribute ties into a set of attributes in the applications style file.

The components are then added using a constraint attribute instead of the x,y,w and h attributes of the NULL layout. The attribute strings are converted to constants via the XLayoutHelper class.

Code Sample 9-12 - A simple border layout

< ?xml version= "1.0" encoding= "UTF-8" ?>

< XPage layout= "BORDER" >

< Components >

< Button name= "northBtn" constraint= "NORTH" content= "NORTH" />

< Button name= "westBtn" constraint= "WEST" content= "WEST" />

< Button name= "eastBtn" constraint= "EAST" content= "EAST" />

< Button name= "southBtn" constraint= "SOUTH" content= "SOUTH" />

< Button name= "centerBtn" constraint= "CENTER" content= "CENTER" />

< /Components >

Some layout managers (such as the FlowLayout ) rely on the preferred size of a component to calculate the layout. In such cases a W and H attribute can be specified to set the components preferred and minimum size.

More details on the layouts can be found in the chapter "Layout" (see page 119).

Validations

Validations are rules that can be used to check that input is correct. Carousel includes a number of built-in validation types, but since the validation of input can range from a trivial to a complex task the framework for performing validations is extensible. Ultimately you can add your own input validation rules and checks to an application.

Validations often have a general role within an application. For example the validation for a phone number or address could be of use in many places and in many applications. Therefore validation rules are specified in a separate XML file (named validations.xml by default) so that they can be used across projects. An example of the file's contents is:

Code Sample 9-13 - A validation rules file


msg="The [firstname] cannot be blank" mandatory="true"/>

msg="The [surname] cannot be blank" mandatory="true"/>

msg="The [age] ({value} [years]) must be between {min} [years] and {max} [years]"

mandatory="true"/>

The validation rules include a warning or error message that is displayed should the validation fail, i.e. if the user input is not valid. The message can include references to the parameters used to control the validation rule, the example shows the user value being embedded in the warning message as the {value} tag.

Details of the tags that can be used and the validations rules can be found in the reference documentation.

Three validation rules are specified for the example page shown below. The validations are then assigned to the input fields in the page XML. The complete XML for the form is as follows:

Code Sample 9-14 - A complete example

< Component type= "XPANEL" x= "10" y= "180" w= "210" h= "40" border= "1" >

< Label x= "10" y= "10" w= "150" h= "20" content= "First Name" />

< Edit name= "firstNameEdit" x= "170" y= "10" w= "100" h= "20" />

< Label x= "10" y= "40" w= "150" h= "20" content= "First Name" />

< Edit name= "secondNameEdit" x= "170" y= "40" w= "100" h= "20" />

< Label x= "10" y= "70" w= "150" h= "20" content= "First Name" />

< Edit name= "ageEdit" x= "170" y= "70" w= "100" h= "20" />

< Button name= "validateBtn" x= "10" y= "130" w= "150" h= "20" />

< /Component >

< Validations >

< Validation name = "firstNameEdit" rule= "firstNameRule" />
< Validation name = "secondNameEdit" rule= "surnameRule" />
< Validation name = "ageEdit" rule= "ageRule" />
< /Validations >

< Events >

< Event target= "validateBtn" method= "checkValidations" />

< /Events >

The checkValidations method can of course be overloaded (or another method can be invoked) to do whatever custom processing is desired.

Normally it is not necessary to add such an additional check of the validations as the validations are checked upon page transition. The default behavior is to display a warning or error (for mandatory validations) message, taking the error message from the validations file and substituting values as appropriate.

Events

Under the hood Carousel uses the normal Java mechanism of adding events listeners to the components on your page, however all the details of adding the events are hidden within the framework. All you need do is write a response method implementing your business logic and then tell the framework when you want that method called.

Once your XML page has been loaded by the XUI framework it exists as Java class. By changing this class you can add your own functionality and behavior to a page, even customizing the event handling for components.

To illustrate the event handling mechanism at work we need to re-introduce some Java code. First off we need to create a place in which to insert our Java code and we do this by setting the class attribute for a page. The framework that loads your page expects an instance of the XPage class or one of its derivatives so we need to extend that base class.

In the example below our own custom class is derived from NavigationHelper so that calls specified in the XML can be intercepted by the custom class. The NavigationHelper class extends XPage to provide additional functionality for things like navigation panels and controls.

Code Sample 9-15 - Specifying a support class/page

public class EventHandling extends NavigationHelper

The XML file now specifies this custom class as its base class and defines the two buttons which have attached events.

Code Sample 9-16 - Binding to a class

< XPage class= "net.xoetrope.samples.xmlbuild.EventHandling" >

< Components >

< Button name= "btnProceed" x= "40" y= "10" w= "60" h= "20" content= "Proceed" />

< Button name= "btnCancel" x= "110" y= "10" w= "60" h= "20" content= "Cancel" />

< Events >

< Event name= "nextPage" target= "btnProceed" method= "nextPage"

type= "ActionHandler" next= "xmlnavsamplescr2" />

< Event name= "cancel" target= "btnCancel" method= "cancel" type= "ActionHandler" />

< /Events >

< /Page >

So now our Java code needs to handle the events by implementing the referenced methods:

Code Sample 9-17 - Coding event handlers

public void nextPage()

{

// Do something here...

XPageManager.showPage( getAttribute( "next" ) );

}

public void cancel()

{

XButton button = ( XButton ) findComponent( "btnCancel" );

button.setText( "Clicked!" );

}

On execution the XUI framework intercepts the action events (having been told to add an action listener for each button) and invokes the nextPage method when the btnProceed button is clicked, or the cancel method for a click on the btnCancel button.

All the plumbing needed to hook up the events and the response methods are hidden for your convenience and to make the code clearer. The hiding of the plumbing also helps reduce your code dependence of the base class. In later chapters ( "Evaluated attributes and helpers" (see page 223)) we will see how to break free of this dependency altogether.

In some rare circumstances you may want to have more control or information about the events so the XUI framework allows you to retrieve the current event object (the event that caused your method to be invoked), you can do this by calling the getCurrentEvent() method of the base class.

Data bindings

Carousel uses a data binding technique that allows components to reference data through links that point to the data's location within a hierarchical model. The data contained within this model can be simple scalar values or more complex types like lists and tables.

The bindings that link the user interface components to the data in the model take care of reading the data and updating the user interface (UI) component. The bindings can also save data to the model whenever the value stored within the user interface component changes.

Since the model lives for the duration of the application the same data model data (or nodes) can be used in many different places. For example the data from one page can be saved to the model and then reused on another page.

To establish a link between a user interface component and a node with the data mode all that needs to be known is where the data resides in that model. Once the location has been declared Carousel takes care of getting and saving the data.

An example of this is shown below:

Code Sample 9-18 - Adding data

< Data >

< Bind target = "firstNameEdit" source= "defaultData/first" />

< Bind target = "secondNameEdit" source= "defaultData/second" />

< /Data >

Here the data from two edit fields is persisted to two separate nodes within the data model. If the same binding specifications were inserted in another page then the edit fields to which the data was bound would update automatically when the new page was displayed.

The data model can also be accessed directly from your Java code and therefore you can use the same data within your event handlers or business logic. It is worth noting that once your data has been saved to the model it is independent of the user interface component from which it originated.

This data independence has a number of fringe benefits. Firstly your business logic can be free of dependencies on the user interface and therefore the user interface can be modified in appearance and form without affecting the workings of your business logic. In this way you could rebrand an application or refactor the user interface, even changing the type of component used to capture the user input.

Secondly, because your application code references the data through a relatively abstract mechanism it is not explicitly aware of the data source. Therefore the data source can be changed independently of the UI and of the application logic. During the life of an application this can occur at several levels. At design time some dummy data may be assembled in text files and then migrated to a database tables as the application grows and ultimately the database may then be accessed remotely as the application is finally deployed. Such changes can be accommodated seamlessly by the data binding framework.

1 A feature of Carousel only and XUI 2.0 and later

comments


If you were logged in you could rate this article or add a comment.