home
products
education
support
partners
company

introduction

get started

articles

manual

tutorials

reference docs

case studies

knowledge base

goodies

screenshots

demos

echoes

Carousel zone


SourceForge.net Logo

home

forums

downloads

bugs

mailing list
XUI Zone - manual

number of ratings 0
average rating 0.00

15 Event handling

Carousel aims to simplify application development by reducing the amount of boilerplate code that must be generated for an application. One of the most time consuming activities and a troublesome feature of application development is the wiring together of components and events.

Java's abstract event handling mechanism is certainly flexible but more often than not the code needed for even simple event handling is repetitive and adds little of particular value to the application. In Carousel the most common instances of this event handling wiring is taken care of by basic library functions so that all the Carousel user need do is specify what is specific to a particular event.

Carousel's event handling relies on the basic Java event handling mechanisms and at any point you can go beyond the Carousel library and work directly with the low level event mechanisms. This chapter shows how to work with both mechanisms.

Adding EventHandlers interactively

Adding event handling in Carousel is very easy. Simply select the component whose event you want to handle within the page designer. Then in the properties palette locate the event of interest. In the screen shot below you can see a mouse event being entered for the selected button.

Once the name has been entered and you press enter Carousel finds the event handler in the source code or adds a new event handler if the handler doesn't exist already.

To correctly add the handler Carousel must do a few extra things that may require additional input or modify the source code in other ways. Of these tasks the most obvious occurs if no name has been given to the component being edited then a popup dialog will appear requesting that you enter a name for the component.

Once a name is available for the component Carousel can proceed and opens the source code in a text editor at the new event handler method.

If necessary a new source file may have been created into which the handler is added. The event is bound to the user interface and the new Java class by a declaration in the page's XML. You can see the event declaration by switching to the page designer and selecting the XML button in the designer's toolbar..

The page XML is updated as soon as the new method is added and the XML text editor is displayed.

And that's it, all of the infrastructure for event handling is taken care of and you can begin entering the application specific business logic.

Basic event handling

Regardless of how you edit the event handlers for your application the basic mechanisms are the same. The page's XML declaration names the event to be used to respond to a particular event type for a given component.

While the XML could point to a method in the page's base class or some existing utility class, most pages involve some form of custom class for handling the custom logic that belongs to the page. Pages can derive directly from XPage but by changing the base class you can customize the event handling for components

This example re-introduces some Java code. Now the base class is our own custom written class derived from NavigationHelper so that calls specified in the XML can be intercepted by the custom class.

Code Sample 15-1 - A new Java class declaration

public class EventHandling extends NavigationHelper

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

Code Sample 15-2 - A page specifying events

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

< Components >

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

< Component name= "btnCancel" type= "XBUTTON" x= "110" y= "10" w= "60" h= "20" content= "Proceed" />

< /Components >

< Events >

< Event method= "nextPage" target= "btnProceed" type= "MouseHandler" next= "xmlnavsamplescr2" />

< Event method= "cancel" target= "btnCancel" type= "MouseHandler" />

< /Events >

So now the java code handling the events is as follows:

Code Sample 15-3 - The Java class's implementation of the events

public void nextPage()

{

if ( wasMouseClicked() ){

// Do something here...

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

}

}

public void cancel()

{

if ( wasMouseClicked() ){

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

button.setText( "Clicked!" );

}

}

Built-in event handlers

Carousel supports several basic types event, the support types are described below:

Table 15-1 - Various event handler types

Type

Usage

ActionHandler

Action handlers respond to ActionEvents such as button clicks, selections, edit completions and so on. This is a simple interface with just a single event.

MouseHandler

Mouse events comprise an number of events including mouse entry, exit and changes of state including when the mouse is pressed, released and clicked. It is normal to check the type of event that trigger the call to a mouse handler method unless you have some generic action for all the above events.

MouseMotionHandler

Like the above mouse handler the mouse motion handler responds to more than one mouse event, namely the mouse moved and mouse dragged events. It is unusual to interact with this type of handler.

ItemHandler

This type of handler is invoked whenever the state of a component changes, for example the selection state of a radio button or a check box.

KeyHandler

This type of handler is used for handling keyboard event including key pressed, released and typed. Sometimes this type of handler is used to help enforce validation rules on input fields.

FocusHandler

A change of focus will trigger this handler both when a component gains focus and when it looses focus.

MenuHandler

Invoked whenever a menu item is selected.

TextHandler

Invoked whenever a text value has changed.

All of these basic event handlers are added via the XPage class or its derivatives. We have already seen an example above of adding a handler via XML but the handlers can also be added via Java with just as much ease. Here's an example that is equivalent to the above XML:

Code Sample 15-4 - Adding an event handler with Java

addMouseHandler( btnProceed, "nextPage" );

addMouseHandler( btnCancel, "cancel" );

Accessing event objects

In the case of multiple event being processed by a single event handler it is sometimes useful to query the properties of the event that caused the handler to be invoked. This is frequently the case with mouse events and key events (and special helper methods are defined for working with mouse events).

To access the event that triggered the handler it is necessary to call the getCurrentEvent method. The event can then be cast to whatever the appropriate type and the event specific data is then accessible. The example below shows how information is extracted from a mouse event. Note that the event is first checked to ensure that it is a mouse event before attempting to cast the value.

Code Sample 15-5 - Accessing the current event

public void handleMouseClicks()

{

if ( wasMouseClicked()) {

MouseEvent me = (MouseEvent)getCurrentEvent();

Point pt = me.getPoint();

statusLabel.setText( "The mouse is at: + Integer.toString(pt.x) + "," + Integer.toString(pt.y));

}

}

Under the hood

In adding event handlers Carousel has to go through a number of steps and it is worth understanding these steps, if only for the sake of in-depth knowledge.

Consider first of all the process of adding the event handler. Carousel constructs your page and the user interface for the page. This is really a process of adding the user interface components to an instance of your page's class. That class is derived from XPage which includes the event handling mechanism. In processing the event declaration in your page's XML Carousel therefore uses the page's event handling mechanism.

Like most normal Java code Carousel pages respond to event through the standard listener interfaces and to save coding the page implements a number of the more common listener interfaces. The page can therefore listen for the common events associated with these interfaces. One of the most common is the ActionListener interface which is invoked in response to an event such as a button click. So when you ask a Carousel page to add an actionHandler for a button it justs adds itself as an ActionListener for the button.

Once the button is clicked the page is notified through the interface. The method you registered is then looked-up and invoked via reflection (since Carousel doesn't really have any knowledge of your method). No great magic there, but the process saves some more of the plumbing code.

Exception handling

Any application logic relying on user input is susceptible to a variety of errors and exceptional conditions that make process impossible to complete. In the Java world it is normal to trap these exceptions as they occur.

In Carousel exception handling is closely tied to the event handling mechanism and the validation mechanism. The idea is that exceptions and validation errors can be handled in a manner similar to the event handling mechanism. Furthermore exceptions can be handled with a certain degree of separation from the normal flow of events since, as the name suggests they occur in exceptional circumstances.

For example an incomplete form could potentially produce a series of exceptions during event processing and during validation. From a user point of view it is unlikely that individual warnings would be produced for each error and instead the user would be informed of a set of errors or a synopsis of the errors. Carousel supports this type of error handling and also redirection of errors to a central error handler. You can find more information on exception handling and input validation at "Writing a custom exception handler" on page 165

Generic event handling

Carousel has built in handlers for the event types listed above however in some cases it is not adequate for all demands or it may be necessary to handle some other event types. Therefore the Carousel API includes a number of methods to assist in integration of other event types.

To customize the event handling it is necessary to subclass the XPage class. In subclassing XPage there are three possible mechanisms for changing the event handling.

First the setEventHandler method can be used to set a specific event handler. Changing the event handler gives considerable scope to change the behavior of the event handling within Carousel.

Secondly individual events can be added with the methods listed below. Choosing to add or modify specific events means that the changes will have less impact than modifying the event handler but at the cost of more work if the changes are to be reused elsewhere.

Finally the underlying Java event handling mechanisms can be used to handle events just as would be the case in a plain old Java application. Nothing in XUI should interfere with the basic event handling mechanism.

Code Sample 15-6 - Event Handler API

public void setEventHandler( XEventHandler eh );

public void addListener( Object comp, String listenerName, String argType );

public void addHandler( Object comp, long eventType, String methodName ) throws Exception;

The first method setEventHandler sets the event handler class for the page. This method should be called in the page constructor. The page delegates to the event handler whenever an attempt is made to add a new event handler.

Most applications call specific methods in the page's API such as addActionHandler , which in turn delegates to the event handler instance. The event handler is essentially a helper class that takes care of adding the event listener (by calling addListener and addHandler ) and mapping the listener to a response method in the page. Further information on these APIs can be found in the API documentation.

Under the hood the XPage class implements the methods specified by the ActionListener interface. In adding an event the page adds itself as a listener to the target component. When the event of interest is fired the page therefore responds to the event via this listener interface. The page then searches for the handler (that you had registered) and invokes it.

Extended Event Specification

As we saw in the earlier data binding chapter the syntax for dynamic method bindings has been extended to include referencing of classes other than the class upon which the current page is based.

The obvious difference from the data binding syntax is that an event binding sets up a reference to a method (the event handler method) and does not itself cause the method to be evaluated. The syntax for the extended event bindings is as follows:

Table 15-2 - Event specifications

Syntax

Role

mypackage.MyClass.myMethod

to invoke a static method

mypackage.MyClass[].myMethod

to create a new instance of the class on each evaluation

mypackage.MyClass[referenceName].myMethod

for a named object instance

myMethod[referenceName]

for a method contained with the invoking page

[referenceName].myMethod

for a method contained with the class instance referred to by the reference name.

To illustrate this extended event specification syntax let's have a look at an example.

Table 15-3 - Counter example extended with library functions

1

2

3

4

5

In the above example we are recreating the simple calculator that we have used in other examples. While the example is a contrived (we will document some more realistic examples later) it shows the new syntax in action.

Line 14 sets up an event binding to a static member of the com.xoetrope.library. Calculator class

Line 15 constructs a new instance of the class each time the event is bound (when the XML expression is loaded and evaluated).

Line 16 constructs a new instance and sets up a reference to the new instance. If the instance already existed it would be reused. In this case a instance of 'foo' had already been created at line 7 so that instance is reused instead of creating a new instance.

Lines 17 and 18 create bindings to other methods in the class and as in the case of line 16 they each use the 'foo' object created on line 7.

The importance of this simple extension should not be under estimated. Quite simply this extension means that your event handlers do not necessarily have to exist in a class derived from XPage . In fact the extension means that you can build libraries of utility functions for common tasks and these functions can be used for things like navigation, calculations and other tasks that do not have to be tied to a particular page.

It is also worth noting that this extension mechanism does not mean that the library functions built using the mechanism cannot access the current page or the current component. Such values can be passed as arguments to the function are they can be accessed via the project, the page, the current event and the component hierarchy.

comments


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