JavaEnterprise JavaUsing the DOM class in AJAX with the GWT and Java

Using the DOM class in AJAX with the GWT and Java

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Java Programming Notes # 2558


Preface

General

Historically, the development of Ajax web applications has been a complex
process. This is due mainly to the requirement to learn and use a variety of
technologies, such as HTML, JavaScript, XML, ASP.NET, Java servlets, various
scripting languages, etc.

Recently several products have emerged that make it possible to develop Ajax
web applications using the Java development environment. Some use exclusively
Java, while others use mainly Java.  I have discussed several of these new
programming environments in previous lessons in this series (see
Resources)
.

The Google Web Toolkit (GWT)

One development environment that allows you to use mainly Java for the
development of web applications is the Google Web Toolkit (GWT) (see
Resources and
Download)
, which is the primary topic
of this tutorial lesson.

Most of the client-side code for a GWT Ajax application can be written in
Java.  There is no requirement to write JavaScript code.  As you will
see in this lesson, however, it is sometimes necessary to think about the
JavaScript code.

Fifth in a series

This is the fifth lesson in a series designed to help you learn
how to use the GWT to create rich Ajax web applications.  You will find links to
the previous lessons in the series in the
Resources
section.

Purpose of the tutorial

The main purpose of the tutorial is to teach you how to write
the Java code necessary to make effective use of the DOM class in the GWT.

Viewing tip

I recommend that you open another copy of this document in a separate
browser window and use the following links to easily find and view the figures
and listings while you are reading about them.  You may also find it useful
to open a third browser window at the Resources section near the end of the
document.  That will make it easy for you to open those resources when they
are mentioned in the text.

Figures

  • Figure 1. Creating a DOM node using the GWT.
  • Figure 2. The application GUI at startup.
  • Figure 3. GUI after clicking the button.
  • Figure 4. GUI after clicking the button with Alt
    key depressed.
  • Figure 5. Button clicked with middle mouse
    button.
  • Figure 6. Application GUI for GwtApp022 at
    startup.
  • Figure 7. Application GUI after clicking the
    button once.
  • Figure 8. Application GUI after clicking the
    button twice.
  • Figure 9. GUI for DoubleClick01 after
    single-click on button.
  • Figure 10. GUI after double-click on button.
  • Figure 11. A basic problem in the GWT.
  • Figure 12. Application GUI at startup for
    GwtApp023.
  • Figure 13. Application GUI after clicking both
    buttons.
  • Figure 14. The state of focus of the top
    button.

Listings

Supplementary material

I recommend that you also study the other lessons in my extensive collection
of online Java tutorials.  You will find a consolidated index at

www.DickBaldwin.com
.

General background information

What is the DOM class and why should you care?

According to the javadocs on the GWT, the DOM class "… provides a
set of static methods that allow you to manipulate the browser’s Document Object
Model (DOM). It contains methods for manipulating both elements and events."

Not a fun place to be

In truth, this is a class that you would probably just as soon not have to
use, particularly if your strong suite is Java and not JavaScript.  Any
time you have to use the DOM class, you probably have to think
about HTML, JavaScript, or both.  However, you will probably encounter
things that you need to do in your web applications that you can only do by
using methods of the DOM class.

A requirement for drag-and-drop

For example, in the previous lesson entitled "Focus events, click events, and
Drag-and Drop in AJAX using the GWT and Java" (see Resources), it was
necessary to invoke the setCapture method of the DOM class to make
certain that the mouse would not lose the button as the button slid underneath
another component while the button was being dragged.  I don’t know of any
way to accomplish that in the GWT without using a method of the DOM
class.

Would prefer not to have to think about JavaScript
or HTML

Usually when we are using Java and the GWT to develop a web application, we
would usually prefer not to have to think about JavaScript or HTML. 
However, it is not possible in some cases to totally ignore JavaScript and HTML. 
Sometimes we have to think about them and do something that involves one or the
other or both.  In reality, when a situation like that occurs, we usually
need to do something that involves the Document Object Model (DOM) tree
(see Resources) that represents the web page.

What is the DOM tree?

Instruction on the DOM tree is well beyond the scope of this tutorial, but
you can read all about it on the W3C website (see
Resources
)
.  The DOM class in the GWT defines about ninety
different static methods that you can use to manipulate the DOM tree in your web
application.

Will discuss a subset of the available methods

Given that the DOM class contains such a large number of different methods, it
won’t be possible for me to teach you about all the capabilities that derive
from those methods in this lesson.  However, I will teach you about
five different capabilities that the methods support in different ways. 
Hopefully, that will give you enough of a background on the topic that you can
progress from there on your own.

Preview

Five GWT applications and one standard Java
application

I will present and explain five sample GWT applications and one standard Java
application in this lesson.  The names of the applications are shown in the
following list.  This list also shows the primary topic that each application is
designed to illustrate.

  • GwtApp019 – Creation of an HTML element or DOM node using the
    GWT.
  • GwtApp020 – Using the EventPreview capability to determine
    the state of the Alt key when a click event is fired
  • GwtApp021 – Determining which mouse button was pressed to cause a
    mouse event to be fired.
  • GwtApp022 – Dynamically controlling the style of GUI components
    at runtime.
  • DoubleClick01 – Illustrates the simplicity of single versus
    double-click event handling in standard Java.
  • GwtApp023 – Handling double-click events in the GWT.

Discussion
and sample code


Complete program listings

I will discuss
the code for the following applications in fragments.  A complete listing of
each application is provided in Listing 23 through Listing 33 near the end of
the lesson.

The HTML host pages

With one exception, the HTML host pages used for the applications in this
lesson are essentially the same as those used for the applications in my earlier
tutorials.  I will explain the one that is different, but I won’t discuss the
others in this lesson.  However, a complete listing of each HTML host page is
also provided in Listing 23 through Listing 33 along with the Java source code
for the application.

GwtApp019 – Creation of an HTML element or
DOM node using the GWT

The purpose of this application is to demonstrate the use of a method of the
DOM class to create of a new DOM node.  The application GUI is shown
in Figure 1.

Figure 1. Creating a DOM node using the GWT.

Not a lot of fun.
Writing Java code to create HTML elements at runtime is not the most enjoyable
way to spend your programming time.  However, as you can see in this
application, such elements can be created at runtime and this capability is
something that you may find useful in your web applications.  Although
not demonstrated in this lesson, such elements can also be removed at
runtime.  The DOM class provides methods for dynamically creating more
than 25 different types of HTML elements at runtime.

As you will see shortly, the boldface line of text in Figure 1 was created from a static
h3 element in the HTML host page.

A
dynamically created paragraph

However, the paragraph below that header was not included in the HTML host page. 
Rather, it was generated dynamically at runtime by the code in the GWT.


HTML host page for GwtApp019

The HTML host page for this application is shown in Listing 1.  An HTML
comment shows the location at which the new element is created at runtime. Note that an ID attribute is assigned to the
body element in the host HTML
page to make it accessible to the Java code.  This is the only thing that makes
this HTML host page different from most of the host pages that you have seen in
earlier lessons.

Listing 1. HTML host page for GwtApp019.

<!--------------------------------------------------------
File GwtApp019.html
GWT host page.
--------------------------------------------------------->
<html>
<head>
<title>Wrapper HTML for GwtApp019</title>
<meta name='gwt:module' content='GwtApp.GwtApp019'>

</head>

<!--Assign an ID to the body element to make it accessible
by the Java code-->
<body id="rootNode">
<script language="javascript" src="gwt.js"></script>
<iframe id="__gwt_historyFrame" 
              style="width:0;height:0;border:0"></iframe>

<h3>GwtApp019</h3>

<!--A paragraph element will be placed here in the output 
HTML by the Java code-->


</body>
</html>

It may be possible to accomplish what this application accomplishes without a
requirement to establish such an ID attribute, but it wasn’t obvious to me how
to do so.


Java code for GwtApp019

The Java source code for this application is shown in its entirety in Listing
2.

Listing 2. Java code for GwtApp019.

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;

public class GwtApp019 implements EntryPoint{

  //This is the entry point method.
  public void onModuleLoad(){
    
    //Get a handle on the root node of the DOM tree.
    Element rootNode = DOM.getElementById("rootNode");
    
    //Text to be displayed in the paragraph element that 
    // will be generated using Java code.
    String para = "This paragraph element was generated "
                + "by the Java code.";
    
    //Create and populate the new paragraph element.
    Element pElement = DOM.createElement("<p>");
    DOM.setInnerText(pElement,para);
    
    //Append the new paragraph element to the DOM tree.
    DOM.appendChild(rootNode,pElement);
    
  }//end onModuleLoad method
  //====================================================//

}//end class GwtApp019

Get a handle on the root node

The source code begins by using a static method of the DOM class named
getElementById to get and save a handle on the root node of the
DOM tree (the body element)

Create and populate a new paragraph element

Then it uses the following two static methods of the DOM class to
create and populate a new paragraph element.

  • createElement
  • setInnerText
Manipulating nodes in DOM tree.
There are several methods in the DOM class that make it possible for you to
manipulate the nodes in the DOM tree in various ways.

Append the new element to the DOM tree

Finally, it uses a static
method of the DOM class named appendChild to append the new node (the new paragraph element) to
the DOM tree.

When the application is executed, the new paragraph element is created and displayed
as shown in Figure 1.

Testing

This application was tested using J2SE 5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27
running as a localhost server under WinXP.

GwtApp020 – Determining the state of the Alt
key when a click event is fired

The event preview capability

This application will introduce you to a very important capability made
available to the GWT by the DOM class.  This is the capability to preview events before
they are handled by registered event handlers and possibly to intervene in some
way before they are handled.  This capability will be used extensively in
the subsequent applications in this lesson.

What key or keys were pressed?

Sometimes you need to know whether the user was holding down the Alt key, the
Shift key, or the Ctrl key when an event is fired.  This application will
teach you how to use the event preview capability to determine the state of the
Alt key when a click event is fired.  You should be able to extend that
knowledge to cover the Shift key and the Ctrl key on your own.

The application GUI at startup

Figure 2 shows the application GUI at startup, before the user clicks the
button with the mouse.

Figure 2. The application GUI at startup.

As you can see, the label at the bottom displays the default text "Startup."

GUI after clicking the button

Figure 3 shows the GUI after the user has clicked the button with the mouse.

Figure 3. GUI after clicking the button.

At this point, the label at the bottom indicates that the Alt key was not
depressed when the click event was fired.

GUI after clicking the button with Alt key depressed

Figure 4 shows the GUI after the user has clicked the button with the mouse
while holding down the Alt key.

Figure 4. GUI after clicking the button with Alt key
depressed.

In this case, the label at the bottom indicates that the Alt key was
depressed when the click event was fired.  This demonstrates that it is
possible to determine if the Alt key is being held down when a click event is
fired.  Although it won’t be demonstrated in this lesson, as mentioned
earlier, similar code can
be used to determine if the Shift key or the Ctrl key is depressed when a click
event is fired.

Description of the application

As mentioned earlier, the purpose of this application is to introduce the
event preview capability of the DOM class.  An object of a class
that implements the EventPreview interface is registered using a static
method of the DOM class to preview all events.  When an event is
fired in this application, a reference to the event is saved in an instance variable named
theEvent
.  This reference is used later by the onClick method of
a ClickListener object registered on a GUI button to determine the state
of the Alt key when the click event was fired.

The application was tested using J2SE 5.0, GWT version 1.2.22, and
jakarta-tomcat-5.0.27 running as a localhost server under WinXP.

Beginning of the class definition

The class definition for GwtApp020 begins in Listing 3.

Listing 3. Beginning of the class definition for
GwtApp020.

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;

public class GwtApp020 implements EntryPoint{
  //The contents of this label are modified by the onClick
  // method when the user clicks a GUI button.
  Label label = new Label("Startup");
  
  //The following variable is used to store a reference to
  // each event that is fired.  When the GUI button fires
  // a click event, this reference is used to determine
  // the state of the Alt key when the user clicked the
  // GUI button with the mouse.
  Event theEvent;

  public void onModuleLoad(){
    //Instantiate a new Button object and register a click
    // listener on it.
    Button button = new Button("Click Me");
    button.addClickListener(new ClickLstnr());

The code in Listing 3 is straightforward and shouldn’t require an explanation
beyond that provided by the comments.


Register an EventPreview listener object

Listing 4 uses a static method of the DOM class to register an EventPreview listener object.

Listing 4. Register an EventPreview listener object.

    DOM.addEventPreview(new EventPrevue());

Register it on what?

Normally when we register a listener object, we register it on a specific
component.  As you can see from Listing 4, however, this listener object
isn’t being registered on any specific component.  I suppose we might say
that it is being registered on the entire application.  In any event, the
EventPreview listener will have an opportunity to preview all events
fired anywhere in the application before they are delivered to listener objects
that are registered on specific components.

Add the GUI button and the label to the RootPanel

Listing 5 completes the onModuleLoad method by adding the button and
the label to the RootPanel as shown in Figure 2.

Listing 5. Add the GUI button and the label to the RootPanel.

    RootPanel.get().add(button);
    RootPanel.get().add(label);
    
  }//end onModuleLoad method


An EventPreview listener class

Listing 6 defines an inner (member) listener class that implements the
EventPreview interface.

Listing 6. An EventPreview listener class.

  class EventPrevue implements EventPreview{
    public boolean onEventPreview(Event event){
      theEvent = event;
      return true;//Don't cancel the event.
    }//end onEventPreview
  }//end class EventPrevue

Recall that an object of this class is registered on the application using
a static method of the DOM class to preview all events in Listing 5.

Save a reference to the Event object

When any event is fired within the application, a reference to the event is
saved in the instance variable named theEvent by the code in Listing 6. 
This reference is used later by the onClick method of a ClickListener
object to determine and display the state of the Alt key when the event was
fired.

Don’t cancel the event

The onEventPreview method in Listing 6 returns true to prevent
the event from being cancelled.  If the method were to return false,
the event would be cancelled and would not be delivered to the ClickListener
object that is registered on the GUI button.

An inner ClickListener class

Listing 7 defines an inner class that implements the ClickListener
interface.

Listing 7. An inner ClickListener class.

  class ClickLstnr implements ClickListener{
    public void onClick(Widget sender){

      if(DOM.eventGetAltKey(theEvent)){
        label.setText("Alt key is down.");
      }else{
        label.setText("Alt key is up.");
      }//end else

    }//end onClick
  }//end class ClickLstnr

}//end class GwtApp020

An object of this class is registered on the GUI button in Listing 3. 
When the user clicks the GUI button with the mouse, the code in this event
handler uses a static method of the DOM class named eventGetAltKey along
with the reference to the event that was saved during the event preview process
to determine and display the state of the Alt key when the event was fired. 
The text in the label is set to reflect the state of the Alt key as shown in
Figure 3 and Figure 4

Testing the Shift and Ctrl keys

In addition to the method named eventGetAltKey, the DOM class
also defines the following static methods that can be used to determine the
state of the Ctrl key and the Shift key when any event is fired:

  • eventGetCtrlKey
  • eventGetShiftKey

End of the class

Listing 7 also signals the end of the GwtApp020 class and the end of
the discussion of the application having the same name.

GwtApp021 – Determining which mouse button
was pressed when a mouse event is fired

While describing the drag-and-drop sample application in the lesson titled
"Focus events, click events, and Drag-and Drop in AJAX using the GWT and Java"
(see Resources) I identified a potential
problem.  I told you that the GUI button could be dragged across the screen
by pressing any of the three mouse buttons on the GUI button to execute the drag
operation.

That is not normally how we would want a web application to behave. 
Normally, we would want to reserve the drag operation for a specific mouse
button and use the other two mouse buttons for other purposes.  This, of
course, requires you to be able to write your code in such a way that it knows
which mouse button was pressed.  That is the main topic of this
application.

The application GUI

Figure 5 shows the result of clicking the large GUI button with the middle
mouse button.

Figure 5. Button clicked with middle mouse button.

Label identifies the mouse button

As you can see, the label at the bottom reports on which mouse button was
pressed to cause the event to be fired.  Clicking the GUI button with the
left or right mouse buttons cause a similar report to appear in the label,
except that the corresponding mouse button is identified in the label.

Description of the application

The purpose of this application is to demonstrate the ability to determine
which mouse button was pressed when a mouse event is fired.

An object of a class that implements the EventPreview interface is
registered on the application using a static method of the DOM class to
preview all events.  When any event is fired, a reference to the event is
saved in an instance variable named theEvent.  This reference is
used later by the onMouseDown method of a MouseListener object
registered on the GUI button shown in Figure 5.  The purpose of the
MouseListener
object is to determine and to display which mouse button was
pressed, causing the mouse event to be fired.

Recall that as standard Button object in the GWT is not capable of
firing mouse events.  Therefore, the GUI button used in this application is a custom button (like the one in the earlier lesson
titled "Focus events, click events, and Drag-and Drop in AJAX using the GWT and
Java – see Resources)
that knows how to fire mouse
events.

The application was tested using J2SE 5.0, GWT version 1.2.22, and
jakarta-tomcat-5.0.27 running as a localhost server under WinXP.


The onModuleLoad method

The beginning of the class and the complete onModuleLoad method are
shown in Listing 8.

Listing 8. The onModuleLoad method for GwtApp021.

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;

public class GwtApp021 implements EntryPoint{
  //The contents of this label are modified by the 
  // onMouseDown method when the user clicks a GUI 
  // inputButton causing the inputButton to fire a mouse
  // event.
  Label outputLabel = new Label("Startup");
  
  //The following variable is used to store a reference
  // to each event that is fired.  When the GUI
  // inputButton fires a mouse event, this reference is
  // used to determine which mouse button was pressed.
  Event theEvent;

  public void onModuleLoad(){
    //Instantiate a new custom button object and register
    // a mouse listener on it. This custom button knows
    // how to fire mouse events.
    Button button = new Button("Mouse Me");
    button.setSize("100px","50px");
    FocusPanel inputButton = new FocusPanel(button);
    inputButton.setSize("100px","50px");
    
    //Cause the focus to skip the FocusPanel and go
    // straight to the button that is wrapped in the
    // FocusPanel.
    inputButton.setTabIndex(-1);
    
    //Register a mouse listener on the GUI inputButton.
    inputButton.addMouseListener(new MouseLstnr());

    //Use a static method of the DOM class to register an
    // EventPreview listener object.
    DOM.addEventPreview(new EventPrevue());

    //Add the GUI inputButton and the outputLabel to the
    // RootPanel.
    RootPanel.get().add(inputButton);
    RootPanel.get().add(outputLabel);
    
  }//end onModuleLoad method

There is nothing new in Listing 8, and the code is heavily
commented.  Therefore, I won’t discuss the code in Listing 8 further.


The EventPreview class

An inner listener class that implements the EventPreview interface is
shown in Listing 9.

Listing 9. The EventPreview class.

  class EventPrevue implements EventPreview{
    public boolean onEventPreview(Event event){
      theEvent = event;
      return true;//Don't cancel the event.
    }//end onEventPreview
  }//end class EventPrevue

An object of this class was registered on the application in Listing 8, using
a static method of the DOM class.  This listener object previews all events
that are fired within the application.  When an event is fired, a reference
to the event is saved in the instance variable named theEvent.  This
reference is used later by the onMouseDown method to determine and
display which mouse button was pressed to cause the event to be fired.  The
onEventPreview method returns true in Listing 9 to prevent the event from
being cancelled.

The MouseListener class

Listing 10 defines an inner listener class that implements the
MouseListener
interface.

Listing 10. The MouseListener class.

  class MouseLstnr extends MouseListenerAdapter{
    public void onMouseDown(Widget sender,int x,int y){
      int theMouseButton = DOM.eventGetButton(theEvent);
      if(theMouseButton == Event.BUTTON_LEFT){
        outputLabel.setText("Left Mouse Button");
      }else if(theMouseButton == Event.BUTTON_MIDDLE){
        outputLabel.setText("Middle Mouse Button");
      }else if(theMouseButton == Event.BUTTON_RIGHT){
        outputLabel.setText("Right Mouse Button");
      }else{
        outputLabel.setText("Don't Know");
      }//end else
    }//end onMouseDown
  }//end class MouseLstnr

}//end class GwtApp021

Register the listener on the GUI button

An object of this class is registered on the GUI button in Listing 8.  When the user clicks the GUI
button shown in Figure 5 with the mouse, the code in
this event handler uses a static method of the DOM class along with a reference
to the Event object and constants defined in the Event class to determine and display an identification of the mouse
button that was pressed to cause the event to be fired.

Otherwise, the code in Listing 10 is straightforward and shouldn’t require
additional explanation.

End of the class

Listing 21 also signals the end of the class named GwtApp021, and the
end of the discussion of the application having the same name.

GwtApp022 – Dynamically controlling the style
of GUI components at runtime

As you learned in an earlier lesson, you can control the style of GWT GUI
components through the use of a style sheet.  That style sheet can either
be embedded in the HTML host page, referenced by the HTML host page, or both.

In his application, you will learn that you can also control the style of GUI
components dynamically at runtime through the use of Java code.  This makes
it possible for the style of the components to change as a result of the firing
of different events as the execution of the application progresses.

Application GUI at startup

Figure 6 shows the application GUI at startup.

Figure 6. Application GUI for GwtApp022 at startup.

As you can see, the text on the face of the button is colored red.


Application GUI after clicking the button once

Figure 7 shows the GUI after clicking the button once following startup.

Figure 7. Application GUI after clicking the button
once.

Clicking the button once following startup causes the text on the face of the
button to change from red to green as show in Figure 7.  Thus, the style of
the button has been modified as a result of the click event fired by the button.

Application GUI after clicking the button twice

Figure 8 shows the GUI after clicking the button twice following startup.

Figure 8. Application GUI after clicking the button
twice.

Clicking the button twice following startup causes the text to change from
red to green, and then from green to blue.  Once again, this occurs as a
result of the click events fired by the button.

Application GUI after clicking the button three
times

Although I didn’t show it here, clicking the button three times following
startup causes the GUI to return to the state shown in Figure 6 with red text on
the face of the button.  The third click event causes the text color to
change from blue back to red.

Cycle colors among red, green, and blue

In other words, each click event fired by the button causes the text on the
face of the button to change dynamically at runtime.  The changes in color
trace out a repetitive pattern of red, green, blue, and back to red in that
order.

Upper-case color values don’t stick.
Note that even if you set the color style to #FF0000, it will later be found
to have a value of #ff0000.  Therefore, any testing that is done on the
hexadecimal values (when treated as a String) must use the lower-case
representation of the hexadecimal values.

Description of the application

The purpose of this application is to use static methods of the DOM
class to dynamically control the style of GUI components at runtime.

As shown in Figure 6, the application:

  • Instantiates a Button object.
  • Uses a static method of the DOM class to set its style to red.
  • Adds it to the root panel.

Then the application registers a click
listener on the button that causes the text on the button to cycle through the
colors of red, green, and blue each time the button is clicked.

The application was tested using J2SE
5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27 running as a localhost server
under WinXP.


Begin class definition for GwtApp022

Listing 11 shows the beginning of the class definition for GwtApp022.

Listing 11. Begin class definition for GwtApp022.

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;

public class GwtApp022 implements EntryPoint{

  public void onModuleLoad(){
    //Instantiate a Button object, set its style to red,
    // and add it to the root panel.
    Button button = new Button("Button");
    DOM.setStyleAttribute(
                   button.getElement(),"color","#ff0000");
    RootPanel.get().add(button);
Attribute methods in the DOM class.
The DOM class contains a number of static methods that deal with attribute
values including those in the following list:

  • getAtttribute
  • getBooleanAttribute
  • getIntAttribute
  • getIntStyleAttribute
  • getStyleAttribute
  • setAttribute
  • setBooleanAttribute
  • setIntAttribute
  • setIntStyleAttribute
  • setStyleAttribute

As you can see, after instantiating the Button object, the code in
Listing 11 invokes the setStyleAttribute to set its "color" attribute to
red (an attribute value of "#ff0000").

Method parameters

The three parameters to the setStyleAttribute method shown in Listing
11 are pretty interesting.  The javadocs describe them in order as:

  • The element whose style attribute is to be set.
  • The name of the style attribute to be set.
  • The style attribute’s new value.

When you compare the last two parameters in Listing 11 with the descriptions
of the parameters in the above list, the last two are pretty obvious.  The
first one isn’t so obvious, however.

Wrap your mind around this.
As I mentioned in an earlier lesson, the Java object of the Button class never
really exists, because the Java source code is translated into JavaScript
code before it is executed.  Because the Java source code is never
compiled and executed under a Java virtual machine, the Java objects that I
talk about in these lessons never really exist.

The getElement method

As you can see, Listing 11 invokes the getElement method on a
reference to the button.  According to the javadocs, the getElement
method "Gets a handle to the object’s underlying DOM element."  In
other words, this method makes it possible to manipulate the actual element in
the DOM tree that is represented by the Java object of type Button.

Add the button to the root panel

After the button is instantiated and has had its style set in Listing 11, it is
added to the root panel for display as shown in Figure 6.


Register a click listener on the button

Listing 12 shows the beginning of an anonymous inner class that registers a
click listener on the button in order to cycle the color of the text through
red, green, and blue each time the button is clicked.

Listing 12. Register a click listener on the button.

    button.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          //Get a reference to the element that
          // represents the button, and then get the
          // current value of the color style for that
          // element.
          Element element = sender.getElement();
          String attr = 
                   DOM.getStyleAttribute(element,"color");

Listing 12 gets a handle on the sender of the event as a DOM element,
(which must be the button in this case).  Then it invokes the
getStyleAttribute
method, passing the element and the name of the style
attribute of interest for the purpose of getting and saving the value of the
attribute.


Cycle the colors

Listing 13 shows the remaining code for the anonymous inner class, from which
a click listener object is instantiated and registered on the button.

Listing 13. Cycle the colors.

          if(attr.equals("#ff0000")){
            DOM.setStyleAttribute(
                               element,"color","#00ff00");
          }else if(attr.equals("#00ff00")){
            DOM.setStyleAttribute(
                               element,"color","#0000ff");
          }else{
            DOM.setStyleAttribute(
                               element,"color","#ff0000");
          }//end else
        }//end onClick
      }//end constructor
    );//end addClickListener
    
  }//end onModuleLoad method

}//end class GwtApp022

Listing 13 executes the logic that cycles the color style through red, green, and blue each time the button is clicked. 
This code is straightforward and shouldn’t require further explanation.

End of the class

Listing 13 also signals the end of the onModuleLoad method, the end of
the class named GwtApp022, and the end of the discussion of the
application having the same name.

DoubleClick01 – Illustrates the
simplicity of single versus double-click event handling in standard Java

Now I’m going to show you something a little different.  The next
(and last)
topic of interest in this lesson has to do with being able to
differentiate between single-click and double-click events.  I’m going to
show you a standard Java application that illustrates the simplicity with which
such differentiation can be accomplished in standard Java.  Following that,
I will show you how to accomplish part of the same thing with the GWT, which as you
will see isn’t quite so simple.


GUI for DoubleClick01 after single-click on button

Figure 9 shows the application GUI after the user has performed a
single-click on the button.

Figure 9. GUI for DoubleClick01 after single-click on
button.

The label on the right in Figure 9 indicates that the event was a
single-click event.


GUI after double-click on button

Similarly, Figure 10 shows the GUI after the user has performed a
double-click on the button.

Figure 10. GUI after double-click on button.

As you can see, the program can differentiate between the two, and can take a
different action depending on whether the event was a single-click event or a
double-click event.

Beginning of the code for DoubleClick01

The code for the desktop application named DoubleClick01 begins in
Listing 14.

Listing 14. Beginning of the code for DoubleClick01.

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class DoubleClick01 extends JFrame{

  public static void main(String[] args){
    new DoubleClick01();
  }//end main

The class named DoubleClick01 extends the JFrame class. 
Hence, an object of the class is the program GUI.

The main method in Listing 14 instantiates an object of the
DoubleClick01
class, thus creating the GUI and causing it to be displayed.


Beginning of the constructor

Listing 15 declares and initializes a couple of instance variables to create
the button and the label shown in Figure 9.  Then Listing 15 shows the
beginning of the constructor for the class.

Listing 15. Beginning of the constructor.

  Button button = new Button("Click me");
  Label label = new Label("Single-click");

  DoubleClick01(){
    setLayout(new FlowLayout());
    add(button);
    add(label);
    setSize(250,100);
    setTitle("Copyright 2006,R.G.Baldwin");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

The constructor code in Listing 15 is straightforward, and should be
self-explanatory on the basis of the names of the methods that are invoked to
construct the GUI.


An anonymous mouse listener

Listing 16 defines, instantiates, and registers a MouseListener object
on the button.

Listing 16. An anonymous mouse listener.

    button.addMouseListener(
      new MouseAdapter(){
        public void mouseClicked(MouseEvent event){
          switch(event.getClickCount()){
            case 1:label.setText("Single-click");break;
            case 2:label.setText("Double-click");break;
            default: label.setText("Don't know");
          }//end switch
        }//end mouseClicked
      }//end constructor
    );//end addMouseListener
  }//end constructor

}//end class DoubleClick01

Listing 16 uses a standard Java switch statement go determine whether
the event was a single-click event or a double-click event and to display the
results in the label as shown in Figure 9 and Figure 10.

The incoming parameter

Not so easy with the GWT.
As you will see later, the information necessary to differentiate between
single-click and double-click events is not so easy to access in the GWT.

The critical thing about Listing 16 and the thing that makes this task so
easy in standard Java (which is totally missing in the GWT) is the
incoming parameter of type MouseEvent to the mouseClicked method.

Very little information in the GWT.
In comparison, the only incoming information to the onClick method in the GWT
is a reference to the source of the event as type Widget.  As near as I
have been able to determine, there is no incoming information about single
versus double-click events.

This incoming parameter to the standard Java mouseClicked method is a reference to an object that encapsulates a lot
of information about the event.  For example, the object encapsulates
information that makes it almost trivial to determine if the event was a
single-click or a double-click event.  All that is necessary to get that
information is to invoke the getClickCount method on the incoming
parameter.

A choice between two different actions

Listing 16 invokes the getClickCount method on the incoming parameter,
and uses the information returned by that method to make a choice between two
different actions.  Those two actions were purposely made very simple in
this example program, but could be as simple or as complex as may be necessary
to solve the problem at hand.  The important point is that it is easy to
write the code necessary to make the choice.

Simple as 1-2-3.
I’m hoping that after this article is published, someone will contact me to
tell me that I am completely wrong and show me how to differentiate between
single-click and double-click events in the GWT. 
If that happens, and if the approach isn’t too overly complex, I will publish an update to this lesson on my web site giving that
person credit for the information.

I can’t make such a choice in the GWT

Quite frankly, I haven’t figured out how to make such a choice in the GWT. 
It can probably be done, but I haven’t figured out how to do it, and so far, my
research on the web hasn’t led me to anything indicating that anyone else has
figured out how to do it either (except for some Rube Goldberg-like
approaches involving the use of a timer.)
  Therefore, the next application that
deals with the double-click event topic in the GWT will provide much less capability, (with
quite a bit more code)
, than this simple application in standard Java.

GwtApp023 – Handling double-click events in
the GWT

As near as I have been able to determine, the only way to identify double-click
events in the GWT is through the use of an EventPreview listener object
as described in the earlier applications in this lesson.

The basic problem

No ONMOUSEMOVE events.
Note that I purposely suppressed the display of mouse move events in Figure
11, because they occur in great numbers and quickly fill up the screen.

The basic problem is illustrated by the text in Figure 11, which shows the
time sequence in which information regarding events becomes
available to an event preview object for the case where the user has
double-clicked a Button object.  The words on the left in Figure 11
identify the types of events as they occur.  You will learn what the words on the right
mean later when I explain this application.

Figure 11. A basic problem in the GWT.

mousedown: passed through
focus: passed through
mouseup: passed through
click: cancelled
mouseup: passed through
dblclick: handled

As you can see in Figure 11, performing a single double-click on the button
caused the event preview object to see a sequence of six different individual
events of five different types culminating with the double-click event of
interest.

One line of text per event

Each line of text in Figure 11 shows the output produced by one invocation of
the onEventPreview method that is defined in an object of a class that
implements the EventPreview interface.  At the end of each invocation, the method must return either true or false.  If the method
returns true, listener objects that are registered for that type of event will
be notified of the event and are free to execute their code.  If the method returns false, the event will
be cancelled
at that point and no listener objects will be notified that the event was fired.

An erroneous single-click event is the problem

The problem arises from the time sequence of the two boldface lines in Figure
11.  The first boldface line indicates that a single-click event was fired. 
The second boldface line indicates that a double-click event was fired.

An intervening ONMOUSEUP event.
In Figure 11, the listener object was actually notified of a mouse up event
after the erroneous notification of the single-click event and before the
notification that the event was actually intended by the user to be a
double-click event.

As you can see in Figure 11, when the user performs a double-click, the event preview object is
first notified erroneously that a single-click event has been fired.  It isn’t until much
later (after the onEventPreview method has terminated) that the
listener object is notified that the event was actually intended by the user to
be a double-click event.  By that point in time, the onClick method
for the erroneous single-click event will already be executing unless the event
was cancelled or delayed in some other manner.

Registered onClick methods may already
be executing

Unless the event-preview listener cancels the erroneous single-click event by returning
false, registered onClick methods will have been notified and will have
begun execution even though the user intended for the event to be handled as a
double-click event rather than a single-click event.  Unlike in standard
Java, when those methods execute, there is no obvious way for them to know that
the user intended for the event to be handled as a double-click event instead of
a single-click event.  Obviously, the erroneous execution of single-click
event handlers can lead to undesirable results.

Another problem

Another problem that is not obvious in Figure 11 is that even though the
onClick
method can’t differentiate between single and double-click events, there is
no onDoubleClick method.  The only way that I have found to
handle a double-click event is to execute an onClick method that was
specifically
designed to behave appropriately for double-click events.


Application GUI at startup for GwtApp023

Figure 12 shows the application GUI at startup before any click events have
been fired.

Figure 12. Application GUI at startup for GwtApp023.

The main thing to note about Figure 12 is that both buttons display
upper-case text.


Application GUI after clicking both buttons

Figure 13 shows the GUI after the user has double-clicked the top button and
has single-clicked the bottom button.

Figure 13. Application GUI after clicking both
buttons.

As you will see later, an event handler is registered on the top button that
causes the text to toggle between upper-case and lower case each time the user
double-clicks the top button.  The event handler ignores single-click
events.  Therefore, performing a single-click on the top button has no
effect on the output.

A very important difference

Unlike the standard Java example shown earlier in Figure 9 and Figure 10,
this event handler is unable to distinguish between single-click events and
double-click events and to execute a different action on the basis of which type
of event was fired.  Instead, the event handler is forced to simply ignore
single-click events (the handler method isn’t even executed for the case of single-click
events)
and to respond only to double-click events.

An event handler on the bottom button

An event handler is registered on the bottom button in Figure 12 to cause the
text on the button to toggle between upper-case and lower case each time the
button fires a single-click event.


The state of focus of the top button

A focus listener is also registered on the top button to monitor and to display
the current state of focus of that button in the label
that separates the two buttons.  For example, Figure 14 shows the result of
repeatedly pressing the tab key until the top button gains the focus.

Figure 14. The state of focus of the top button.

The top button in Figure 14 shows a visual indication of focus, and the label
indicates that the top button has gained the focus.

Why did I write this extra code?

My reasons for writing the code to provide the focus monitoring capability
and to provide the bottom button that responds to single-click events will
become clear later when I explain the code for this application. 
Basically, it was done to keep me honest with respect to my handling of
double-click events on the top button.

Description of the application

This application forces a Button to ignore single-click events but
respond to double-click events.

It places two buttons and a label in a VerticalPanel and places the
VerticalPanel
in the RootPanel as shown in Figure 12.  The top
button in Figure 12 is referred to in the code as buttonA and the bottom button is
referred to as buttonB.

An EventPreview filter

An EventPreview listener is used to filter events on buttonA
This listener is designed to simply pass events fired by any component other than
buttonA along to their respective event handlers.  It examines all events fired by buttonA passing focus
events and keyboard events through unchanged to their respective event handlers. 

The filter causes a click event
handler that is registered on buttonA to respond only to double-click
events.  It cancels real single-click events on buttonA and
converts double-click events on buttonA into artificial single-click events so that
they will be handled by the single-click handler.  (As far as I know,
it is not possible, or at least not easy to create a double-click handler with the GWT.)

Single-click events on buttonB

The other button, buttonB, responds to single-click events.  Its
purpose is solely to demonstrate that it is not impacted by the EventPreview
filter that is applied to buttonA.

A focus listener

A focus listener is also registered on buttonA to display the current
focus state of buttonA in the label.  The purpose of the focus
listener is solely to demonstrate that the EventPreview filter doesn’t have any
impact on any event types on buttonA other than single-click and
double-click events.

Display on command-line screen.
One of the advantages of testing in hosted mode is that you have access to a
command-line screen where you can display useful test information.

Display information on a command-line screen

The application displays information such as that shown in Figure 11 on
a
command-line screen in hosted mode to explain what is happening as the
application executes.

Testing

The application was tested using J2SE 5.0, GWT version 1.2.22, and
jakarta-tomcat-5.0.27 running as a localhost server under WinXP.


Familiar code

The application begins in Listing 17 with a large amount of very familiar
code.

Listing 17. Familiar code.

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;

public class GwtApp023 implements EntryPoint{
  
  Button buttonA;//This button handles double-click events
  Button buttonB;//This button handles single-click events
  Label label;
  EventPrevue eventPrevue;

  public void onModuleLoad(){
    //Instantiate a container for two buttons.
    VerticalPanel panel = new VerticalPanel();
    RootPanel.get().add(panel);
    
    //Instantiate a Button object. This button will 
    // ignore single-click events and handle only double
    // click events.
    buttonA = new Button("A");
    panel.add(buttonA);
    
    //Register a click listener on buttonA that causes the
    // text on buttonA to toggle between A and a each time
    // it is clicked.  Note that this handler doesn't know
    // the difference between single-clicks and double
    // clicks.  However, an event preview object filters
    // all events on this button and allows it to handle
    // only double-click events as though they were 
    // single-click events.
    buttonA.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          Button source = (Button)sender;
          if(source.getText().equals("A")){
            source.setText("a");
          }else{
            source.setText("A");
          }//end else

          //The EventPreview object was removed long
          // enough for this event to be processed.
          // Restore it.
          eventPrevue = new EventPrevue();
          DOM.addEventPreview(eventPrevue);

        }//end onClick
      }//end constructor
    );//end addClickListener
    //==================================================//
    
    //Register a FocusListener on buttonA to display the
    // focus status of buttonA in a label.  The purpose is
    // to demonstrate that focus events on buttonA are not
    // impacted by the event preview filter on buttonA.

    label = new Label("Text at startup");
    panel.add(label);
    
    buttonA.addFocusListener(
      new FocusListener(){
        public void onFocus(Widget sender){
          label.setText("Gained Focus");
        }//end onFocus
        //----------------------------------------------//
        
        public void onLostFocus(Widget sender){
          label.setText("Lost Focus");
        }//end onLostFocus
      }//end constructor
    );//end addFocusListener
    //==================================================//
    
    //Instantiate another button that will handle single
    // click events in the normal manner.  The purpose of
    // this button is to demonstrate that the filter in
    // the event preview applies only to buttonA.
    buttonB = new Button("B");
    panel.add(buttonB);
    
    //Register a click listener on the button that will
    // toggle the text on the face of the button between
    // B and b each time that it is clicked.
    buttonB.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          Button source = (Button)sender;
          if(source.getText().equals("B")){
            source.setText("b");
          }else{
            source.setText("B");
          }//end else
        }//end onClick
      }//end constructor
    );//end addClickListener
    //==================================================//

With the exception of the two statements shown in boldface, all of the code
in Listing 17 should be very familiar to you by now.  I will refer back to and
explain the two boldface statements later.


Register an EventPreview filter

Listing 18 uses a static method of the DOM class to register an
EventPreview
listener object.

Listing 18. Register an EventPreview filter.

    eventPrevue = new EventPrevue();
    DOM.addEventPreview(eventPrevue);
    
  }//end onModuleLoad method

This listener object is designed to ignore events fired by any component
other than buttonA.  It filters all events fired by buttonA
and causes a registered click event handler to respond only to double-click
events.  It accomplishes this by canceling single-click events on
buttonA
and converting double-click events into single-click events so that
they will be handled by the single-click event handler.


Beginning of the EventPreview filter code

An inner class from which an object is instantiated and registered in
Listing 18 to filter events on buttonA begins in Listing 19.

Listing 19. Beginning of the EventPreview filter
code.

  class EventPrevue implements EventPreview{
    public boolean onEventPreview(Event event){
      //Make sure the event was fired by buttonA.
      if(DOM.eventGetTarget(event).
                            equals(buttonA.getElement())){

The if statement that begins in Listing 19 is used to make certain
that the event being processed was fired by buttonA.  As you will
see later, if it was not fired by buttonA, it will be passed through the
method without modification.  For example, events fired by the bottom
button in Figure 14 pass through the method unchanged.

Display on command-line screen

The code in Listing 20 displays the event type on the command-line screen as
shown in Figure 11 unless the type is ONMOUSEMOVE.  This code doesn’t
display ONMOUSEMOVE events because they occur in great quantity and quickly fill the screen.

Listing 20. Display on command-line screen.

        if(DOM.eventGetType(event) != Event.ONMOUSEMOVE){
          System.out.print(
                    DOM.eventGetTypeString(event) + ": ");
        }//end if

Note that the code in Listing 20 only displays the left portion of a line of
text shown in Figure 11 and leaves the cursor dangling at that point.  The right portion of each line of text will be
display later in the program, and the text that is displayed will depend on the
disposition of the event based on its type.


Process double-click events

The nested if statement in Listing 21 determines if the event is a
double-click event, and if so, processes it in a specific manner.

Listing 21. Process double-click events.

        //Determine if the event was a double-click.
        if(DOM.eventGetType(event) == Event.ONDBLCLICK){

          //Temporarily disable the event preview filter.
          DOM.removeEventPreview(eventPrevue);

          //Fire a single-click event on buttonA.
          buttonA.click();

          //Display remainder of message in Figure 11.
          System.out.println("handled");

          //Return true or false.
          return true;

Temporarily disable the event preview filter

For the case where the event is a double-click event (on buttonA), the
code in Listing 21 begins by temporarily disabling the event preview filter in order to
allow one single-click event to bypass the filter and to processed by
the single-click event handler registered on buttonA in Listing 17. 
The event preview filter will be reinstated by the code in that single-click event handler after it completes its
work as shown by the two boldface statements in
Listing 17.

No double-click event handler method.
As I mentioned earlier, there is no method named onDoubleClick in the
GWT.  There is no way to register an event handler that will be
automatically invoked in the case of a double-click event.  Therefore,
it is necessary for the programmer to force double-click events to be
converted into single-click events for purposes of event handling. 
Otherwise, double-click events are simply ignored and do not cause any event handler to be
notified that the event has been fired.

Force buttonA to fire a click event

After
temporarily disabling the event preview filter, the code in Listing 21 invokes the
click
method on buttonA to cause it to fire a single-click event. 
This causes the single-click event handler that was registered on buttonA
in Listing 17 to be executed once as a result of this double-click event.  This,
in turn, causes the text on the face of buttonA to toggle between "A" and "a"
each time the user executes a double-click on buttonA.

Display the rest of the message in Figure 11

Then the code in Listing 21 causes the right portion of the last line of text
in Figure 11 to be displayed on the command-line screen.

Return true or false

Finally, the code in Listing 21 returns true.  As near as I have been
able to determine, in the case of a
double-click event, it doesn’t matter it returns true or false because nothing normally happens as a result of a double-click event
anyway.  In other words, there can’t be any double-click event handlers
that are automatically executed as a result of the filter returning true in the
case of a double-click event.


Not a double-click event

The else clause in Listing 22 shows the code that is executed by the
event preview filter for the case where the event was fired by buttonA
but was not a double-click event
on buttonA.

Listing 22. Not a double-click event.

        }else{
          
          if(DOM.eventGetType(event) == Event.ONCLICK){
            //Complete the message and cancel single-click
            // events on buttonA.
            System.out.println("cancelled");
            return false;
          }else{
            //Don't cancel other event types on buttonA.
            if(DOM.eventGetType(event) != 
                                       Event.ONMOUSEMOVE){
              //Complete the message.
              System.out.println("passed through");
            }//end if
            
            return true;
          }//end else

        }//end else
      }//end if
      return true;//Wasn't buttonA, just ignore it.
    }//end onEventPreview
  }//end class EventPrevue

}//end class GwtApp023

The case of a single-click event

The code in Listing 22 begins by testing to determine if the event was a
single-click event.  If so, it displays the right half of the fourth line
of text in Figure 11 and returns false to cancel the event and prevent it
from being delivered to registered click event handlers.  Thus,
single-click events on buttonA are cancelled by the event preview filter
and prevented from having any impact on the behavior of the program.

Other event types fired by buttonA

Don’t display ONMOUSEMOVE.
As explained earlier, however, no text is displayed on the command-line screen
for ONMOUSEMOVE events.

If the event was not a double-click event and was not a single-click event,
then it is simply passed through the filter by returning true from the
else
clause shown in Italics near the middle of Listing 22.  In that case, the line of
text on the command-line screen shown in Figure 11 is completed with the words
"passed through."  This is illustrated by focus events and
mouseup
events in Figure 11.

Not buttonA

Finally, if the component that fired the event was not buttonA
(buttonB for example)
, the last return statement in Listing 22 is executed to
return true, causing the event to simply pass through the method and to
be delivered to registered event handlers.

End of class GwtApp023

Listing 22 also signals the end of the code for the class named GwtApp023,
and the end of the discussion of the application having the same name.

Run the programs

I encourage you to copy the code from Listing 23 through Listing 33 into your
text editor, compile it, and execute it.  Experiment with it, making changes,
and observing the results of your changes.

Learn how to write web applications using this exciting new technology. Above
all, enjoy the process. Programming can be fun.

Summary

In this lesson, I taught you how to write the Java code necessary to make
effective use of the DOM class in the GWT.

What’s next?

Future lessons will concentrate on the Java programming techniques required
to produce rich Ajax web applications using the GWT framework.  This will
include discussions and explanations of such topics as the available GWT user
interface components, possibly some more on event-driven programming using the
GWT, possibly some more on styling, possibly some more on the behavior of drop
targets, and a little about Remote Procedure Calls with the GWT.  I may
even try to do a little on the JavaScript Native Interface, (JSNI).  At this point,
however, I’m not certain what the order of the topics will be.

Complete program listings


Complete listings of the programs discussed in this lesson are shown in Listing
23 through Listing 33 below.

Listing 23. HTML host page for GwtApp019.

<!--------------------------------------------------------
File GwtApp019.html
GWT host page.
--------------------------------------------------------->
<html>
<head>
<title>Wrapper HTML for GwtApp019</title>
<meta name='gwt:module' content='GwtApp.GwtApp019'>

</head>

<!--Assign an ID to the body element to make it accessible
by the Java code-->
<body id="rootNode">
<script language="javascript" src="gwt.js"></script>
<iframe id="__gwt_historyFrame" 
              style="width:0;height:0;border:0"></iframe>

<h3>GwtApp019</h3>

<!--A paragraph element will be placed here in the output 
HTML by the Java code-->


</body>
</html>

Listing 24. Java code for GwtApp019.

/*File GwtApp019.java
The purpose of this app is to demonstrate a very simple
operation using the DOM class.

Note that an ID attribute is assigned to the body element
in the host HTML page to make it accessible to the Java
code.

The application begins by using a static method of the DOM
class to get and save a handle on the root node of the DOM
tree (the body element).

Then it uses two more static methods of the DOM class to
create and populate a new paragraph element.

Finally, it uses a static method of the DOM class to 
append the new node (the new paragraph element) to the DOM
tree.

Then when the application is executed, the new paragraph
element is displayed.

Tested using J2SE 5.0, GWT version 1.2.22, and 
jakarta-tomcat-5.0.27 running as a localhost server
under WinXP.
*********************************************************/

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;

public class GwtApp019 implements EntryPoint{

  //This is the entry point method.
  public void onModuleLoad(){
    
    //Get a handle on the root node of the DOM tree.
    Element rootNode = DOM.getElementById("rootNode");
    
    //Text to be displayed in the paragraph element that 
    // will be generated using Java code.
    String para = "This paragraph element was generated "
                + "by the Java code.";
    
    //Create and populate the new paragraph element.
    Element pElement = DOM.createElement("<p>");
    DOM.setInnerText(pElement,para);
    
    //Append the new paragraph element to the DOM tree.
    DOM.appendChild(rootNode,pElement);
    
  }//end onModuleLoad method
  //====================================================//

}//end class GwtApp019

Listing 25. HTML host page for GwtApp020.

<!--------------------------------------------------------
File GwtApp020.html
GWT host page.
Revised: 11/26/06
--------------------------------------------------------->
<html>
<head>
<title>Wrapper HTML for GwtApp020</title>
<meta name='gwt:module' content='GwtApp.GwtApp020'>

</head>

<body>
<script language="javascript" src="gwt.js"></script>
<iframe id="__gwt_historyFrame" 
              style="width:0;height:0;border:0"></iframe>

<h3>GwtApp020</h3>

<p>The purpose of this application is to demonstrate the 
event preview capability of the DOM class.</p>


</body>
</html>

Listing 26. Java code for GwtApp020.

/*File GwtApp020.java
Copyright 2006 R.G.Baldwin

The purpose of this application is to demonstrate the 
event preview capability of the DOM class.

An object of a class that implements the EventPreview 
interface is registered using a static method of the DOM 
class to preview all events. When an event is fired, a 
reference to the event is saved in an instance variable 
named theEvent. This reference is used later by the 
onClick method of a ClickListener object registered on a
GUI button to determine the state of the Alt key when the
click event was fired.

Tested using J2SE 5.0, GWT version 1.2.22, and 
jakarta-tomcat-5.0.27 running as a localhost server
under WinXP.
*********************************************************/

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;

public class GwtApp020 implements EntryPoint{
  //The contents of this label are modified by the onClick
  // method when the user clicks a GUI button.
  Label label = new Label("Startup");
  
  //The following variable is used to store a reference to
  // each event that is fired.  When the GUI button fires
  // a click event, this reference is used to determine
  // the state of the Alt key when the user clicked the
  // GUI button with the mouse.
  Event theEvent;

  public void onModuleLoad(){
    //Instantiate a new Button object and register a click
    // listener on it.
    Button button = new Button("Click Me");
    button.addClickListener(new ClickLstnr());

    //Use a static method of the DOM class to register an
    // EventPreview listener object.
    DOM.addEventPreview(new EventPrevue());

    //Add the GUI button and the label to the RootPanel.
    RootPanel.get().add(button);
    RootPanel.get().add(label);
    
  }//end onModuleLoad method
  //====================================================//
  
  //Inner listener class.  An object of this class is
  // registered on the GUI button.  When the user clicks
  // the GUI button with the mouse, the code in this event
  // handler uses a static method of the DOM class along
  // with a reference to the event to determine and
  // display the state of the Alt key when the event was
  // fired.  The text in the label is set to reflect the
  // state of the Alt key.
  class ClickLstnr implements ClickListener{
    public void onClick(Widget sender){

      if(DOM.eventGetAltKey(theEvent)){
        label.setText("Alt key is down.");
      }else{
        label.setText("Alt key is up.");
      }//end else

    }//end onClick
  }//end class ClickLstnr
  //====================================================//
  
  //Inner listener class. An object of this class is
  // registered using a static method of the DOM class to
  // preview all events. When an event is fired, a
  // reference to the event is saved in the instance
  // variable named theEvent. This reference is used later
  // by the onClick method to determine and display the
  // state of the Alt key when the event was fired. The
  // onEventPreview method returns true to prevent the
  // event from being cancelled.  If it were to return
  // false, the event would be cancelled and would not be
  // seen by the ClickListener object that is registered
  // on the GUI button.
  class EventPrevue implements EventPreview{
    public boolean onEventPreview(Event event){
      theEvent = event;
      return true;//Don't cancel the event.
    }//end onEventPreview
  }//end class EventPrevue
  //====================================================//

}//end class GwtApp020

Listing 27. HTML host page for GwtApp021.

<!--------------------------------------------------------
File GwtApp021.html
GWT host page.
--------------------------------------------------------->
<html>
<head>
<title>Wrapper HTML for GwtApp021</title>
<meta name='gwt:module' content='GwtApp.GwtApp021'>

</head>

<body>
<script language="javascript" src="gwt.js"></script>
<iframe id="__gwt_historyFrame" 
              style="width:0;height:0;border:0"></iframe>

<h3>GwtApp021</h3>

<p>The purpose of this application is to demonstrate the 
ability to determine which mouse button was pressed 
when a mouse event is fired.</p>


</body>
</html>

Listing 28. Java code for GwtApp021.

/*File GwtApp021.java
Copyright 2006 R.G.Baldwin

The purpose of this application is to demonstrate the 
ability to determine which mouse button was pressed when a
mouse event is fired.

An object of a class that implements the EventPreview 
interface is registered using a static method of the DOM 
class to preview all events. When an event is fired, a 
reference to the event is saved in an instance variable 
named theEvent. This reference is used later by the 
onMouseDown method of a MouseListener object registered on
a GUI inputButton to determine and display which mouse 
button was pressed. Note that the GUI inputButton is a 
custom button that knows how to fire mouse events.

Tested using J2SE 5.0, GWT version 1.2.22, and 
jakarta-tomcat-5.0.27 running as a localhost server
under WinXP.
*********************************************************/

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;

public class GwtApp021 implements EntryPoint{
  //The contents of this label are modified by the 
  // onMouseDown method when the user clicks a GUI 
  // inputButton causing the inputButton to fire a mouse
  // event.
  Label outputLabel = new Label("Startup");
  
  //The following variable is used to store a reference
  // to each event that is fired.  When the GUI
  // inputButton fires a mouse event, this reference is
  // used to determine which mouse button was pressed.
  Event theEvent;

  public void onModuleLoad(){
    //Instantiate a new custom button object and register
    // a mouse listener on it. This custom button knows
    // how to fire mouse events.
    Button button = new Button("Mouse Me");
    button.setSize("100px","50px");
    FocusPanel inputButton = new FocusPanel(button);
    inputButton.setSize("100px","50px");
    
    //Cause the focus to skip the FocusPanel and go
    // straight to the button that is wrapped in the
    // FocusPanel.
    inputButton.setTabIndex(-1);
    
    //Register a mouse listener on the GUI inputButton.
    inputButton.addMouseListener(new MouseLstnr());

    //Use a static method of the DOM class to register an
    // EventPreview listener object.
    DOM.addEventPreview(new EventPrevue());

    //Add the GUI inputButton and the outputLabel to the
    // RootPanel.
    RootPanel.get().add(inputButton);
    RootPanel.get().add(outputLabel);
    
  }//end onModuleLoad method
  //====================================================//
  
  //Inner listener class.  An object of this class is
  // registered on the GUI inputButton.  When the user
  // clicks the GUI inputButton with the mouse, the code
  // in this event handler uses a static method of the DOM
  // class along with a reference to the Event object to
  // determine and display an identification of the mouse
  // button that was pressed.
  class MouseLstnr extends MouseListenerAdapter{
    public void onMouseDown(Widget sender,int x,int y){
      int theMouseButton = DOM.eventGetButton(theEvent);
      if(theMouseButton == Event.BUTTON_LEFT){
        outputLabel.setText("Left Mouse Button");
      }else if(theMouseButton == Event.BUTTON_MIDDLE){
        outputLabel.setText("Middle Mouse Button");
      }else if(theMouseButton == Event.BUTTON_RIGHT){
        outputLabel.setText("Right Mouse Button");
      }else{
        outputLabel.setText("Don't Know");
      }//end else
    }//end onMouseDown
  }//end class MouseLstnr
  //====================================================//
  
  //Inner listener class. An object of this class is
  // registered using a static method of the DOM class to
  // preview all events. When an event is fired, a
  // reference to the event is saved in the instance
  // variable named theEvent. This reference is used later
  // by the onMouseDown method to determine and display
  // which mouse button was pressed. The onEventPreview
  // method returns true to prevent the event from being
  // cancelled.
  class EventPrevue implements EventPreview{
    public boolean onEventPreview(Event event){
      theEvent = event;
      return true;//Don't cancel the event.
    }//end onEventPreview
  }//end class EventPrevue
  //====================================================//

}//end class GwtApp021

Listing 29. HTML host page for GwtApp022.

<!--------------------------------------------------------
File GwtApp022.html
GWT host page
--------------------------------------------------------->
<html>
<head>
<title>Wrapper HTML for GwtApp022</title>
<meta name='gwt:module' content='GwtApp.GwtApp022'>

</head>

<body>
<script language="javascript" src="gwt.js"></script>
<iframe id="__gwt_historyFrame" 
              style="width:0;height:0;border:0"></iframe>

<h3>GwtApp022</h3>

<p>The purpose of this App is to use static methods of 
the DOM class to dynamically control the style of GUI 
components.</p>

</body>
</html>

Listing 30. Java code for GwtApp022.

/*File GwtApp022.java
Copyright 2006 R.G.Baldwin

The purpose of this application is to use static methods 
of the DOM class to dynamically control the style of GUI 
components at runtime.

The application instantiates a Button object, uses a 
static method of the DOM class to set its style to red, 
and adds it to the root panel.

Note that even if you set the color style to #FF0000, it 
will later be found to have a value of #ff0000.  
Therefore, any testing that is done on the hexadecimal 
(when treated as a String) value must use the lower-case 
representation of the hexadecimal values.
    
Then the application registers a click listener on the 
button that causes the text on the button to cycle through
the colors of red, green, and blue each time the button 
is clicked.

Tested using J2SE 5.0, GWT version 1.2.22, and 
jakarta-tomcat-5.0.27 running as a localhost server
under WinXP.
*********************************************************/

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;

public class GwtApp022 implements EntryPoint{

  public void onModuleLoad(){
    //Instantiate a Button object, set its style to red,
    // and add it to the root panel.
    Button button = new Button("Button");
    DOM.setStyleAttribute(
                   button.getElement(),"color","#ff0000");
    RootPanel.get().add(button);
    
    //Register a click listener on the button that causes
    // the text on the button to cycle through the colors
    // red, green, and blue each time the button is
    // clicked.
    button.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          //Get a reference to the element that
          // represents the button, and then get the
          // current value of the color style for that
          // element.
          Element element = sender.getElement();
          String attr = 
                   DOM.getStyleAttribute(element,"color");

          //Execute the logic that cycles the color style
          // through red, green, and blue each time the
          // button is clicked.
          if(attr.equals("#ff0000")){
            DOM.setStyleAttribute(
                               element,"color","#00ff00");
          }else if(attr.equals("#00ff00")){
            DOM.setStyleAttribute(
                               element,"color","#0000ff");
          }else{
            DOM.setStyleAttribute(
                               element,"color","#ff0000");
          }//end else

        }//end onClick
      }//end constructor
    );//end addClickListener
    
  }//end onModuleLoad method

}//end class GwtApp022

Listing 31. Java code for DoubleClick01.

/*File DoubleClick01.java
Copyright 2006, R.G.Baldwin

Illustrates the extreme simplicity of differentiating
between single and double-click events on a Button in
J2SE 5.0.

Tested using J2SE5.0 under WinXP.
*********************************************************/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class DoubleClick01 extends JFrame{

  public static void main(String[] args){
    new DoubleClick01();
  }//end main
  //----------------------------------------------------//
  
  Button button = new Button("Click me");
  Label label = new Label("Single-click");

  DoubleClick01(){
    setLayout(new FlowLayout());
    add(button);
    add(label);
    setSize(250,100);
    setTitle("Copyright 2006,R.G.Baldwin");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    
    button.addMouseListener(
      new MouseAdapter(){
        public void mouseClicked(MouseEvent event){
          switch(event.getClickCount()){
            case 1:label.setText("Single-click");break;
            case 2:label.setText("Double-click");break;
            default: label.setText("Don't know");
          }//end switch
        }//end mouseClicked
      }//end constructor
    );//end addMouseListener
  }//end constructor
}//end class DoubleClick01

Listing 32. HTML host page for GwtApp023.

<!--------------------------------------------------------
File GwtApp023.html
GWT host page
--------------------------------------------------------->
<html>
<head>
<title>Wrapper HTML for GwtApp023</title>
<meta name='gwt:module' content='GwtApp.GwtApp023'>

</head>

<body>
<script language="javascript" src="gwt.js"></script>
<iframe id="__gwt_historyFrame" 
              style="width:0;height:0;border:0"></iframe>

<h3>GwtApp023</h3>

<p>This application causes a Button to ignore single-
click events but respond to double-click events.</p>


</body>
</html>

Listing 33. Java code for GwtApp023.

/*File GwtApp023.java
Copyright 2006 R.G.Baldwin

This application causes a Button to ignore single-click 
events but respond to double-click events.

This application places two buttons and a label in a 
VerticalPanel and places the VerticalPanel in the 
RootPanel. One button is referred to as buttonA and the 
other button is referred to as buttonB.

An EventPreview listener is used to filter events on 
buttonA. This listener is designed to ignore events fired
by any component other than buttonA. It filters all events
fired by buttonA passing focus events and keyboard events
through unchanged. It causes a click event handler that is
registered on buttonA to respond only to double-click 
events. In effect, it cancels single-click events on 
buttonA but converts double events on buttonA into single-
click events so that they will be handled by the single-
click handler.  As far as it know, it is not possible to
create a double-click handler with the GWT.

The other button, buttonB, responds to single-click 
events. Its purpose is simply to demonstrate that it is 
not impacted by the EventPreview filter that is applied to
buttonA.

A focus listener is registered on buttonA to display the 
current focus state of buttonA in the label. The purpose 
is to demonstrate that the EventPreview filter doesn't 
have any impact on any event types on buttonA other than 
single-click events.

The application displays information on the command-line
screen to explain what is happening as it executes.

Tested using J2SE 5.0, GWT version 1.2.22, and 
jakarta-tomcat-5.0.27 running as a localhost server
under WinXP.
*********************************************************/

package GwtApp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;

public class GwtApp023 implements EntryPoint{
  
  Button buttonA;//This button handles double-click events
  Button buttonB;//This button handles single-click events
  Label label;
  EventPrevue eventPrevue;

  public void onModuleLoad(){
    //Instantiate a container for two buttons.
    VerticalPanel panel = new VerticalPanel();
    RootPanel.get().add(panel);
    
    //Instantiate a Button object. This button will 
    // ignore single-click events and handle only double
    // click events.
    buttonA = new Button("A");
    panel.add(buttonA);
    
    //Register a click listener on buttonA that causes the
    // text on buttonA to toggle between A and a each time
    // it is clicked.  Note that this handler doesn't know
    // the difference between single-clicks and double
    // clicks.  However, an event preview object filters
    // all events on this button and allows it to handle
    // only double-click events.
    buttonA.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          Button source = (Button)sender;
          if(source.getText().equals("A")){
            source.setText("a");
          }else{
            source.setText("A");
          }//end else

          //The EventPreview object was removed long
          // enough for this event to be processed.
          // Restore it.
          eventPrevue = new EventPrevue();
          DOM.addEventPreview(eventPrevue);

        }//end onClick
      }//end constructor
    );//end addClickListener
    //==================================================//
    
    //Register a FocusListener on buttonA to display the
    // focus status of buttonA in a label.  The purpose is
    // to demonstrate that focus events on buttonA are not
    // impacted by the event preview filter on buttonA.

    label = new Label("Text at startup");
    panel.add(label);
    
    buttonA.addFocusListener(
      new FocusListener(){
        public void onFocus(Widget sender){
          label.setText("Gained Focus");
        }//end onFocus
        //----------------------------------------------//
        
        public void onLostFocus(Widget sender){
          label.setText("Lost Focus");
        }//end onLostFocus
      }//end constructor
    );//end addFocusListener
    //==================================================//
    
    //Instantiate another button that will handle single
    // click events in the normal manner.  The purpose of
    // this button is to demonstrate that the filter in
    // the event preview applies only to buttonA.
    buttonB = new Button("B");
    panel.add(buttonB);
    
    //Register a click listener on the button that will
    // toggle the text on the face of the button between
    // B and b each time that it is clicked.
    buttonB.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          Button source = (Button)sender;
          if(source.getText().equals("B")){
            source.setText("b");
          }else{
            source.setText("B");
          }//end else
        }//end onClick
      }//end constructor
    );//end addClickListener
    //==================================================//
    
    //Use a static method of the DOM class to register an
    // EventPreview listener object. This listener object
    // is designed to ignore events fired by any component
    // other than buttonA.  It filters all events fired by
    // buttonA and causes a registered click event
    // handler to respond only to double-click events. In
    // effect, it cancels single-click events on buttonA
    // but converts double events into single-click events
    // so that they will be handled by the single-click
    // handler.  As far as it know, it is not possible to
    // create a double-click handler.
    eventPrevue = new EventPrevue();
    DOM.addEventPreview(eventPrevue);
    
  }//end onModuleLoad method
  //----------------------------------------------------//
  
  //Inner class that filters events on buttonA.  See the
  // description above.
  class EventPrevue implements EventPreview{
    public boolean onEventPreview(Event event){
      //Make sure the event was fired by buttonA.
      if(DOM.eventGetTarget(event).
                            equals(buttonA.getElement())){
        //Display the event type on the command-line
        // screen unless the type is ONMOUSEMOVE. Don't
        // display ONMOUSEMOVE events because they quickly
        // fill the screen. This is the beginning of a
        // message that is completed later.
        if(DOM.eventGetType(event) != Event.ONMOUSEMOVE){
          System.out.print(
                    DOM.eventGetTypeString(event) + ": ");
        }//end if                              

        //Determine if the event was a double-click.
        if(DOM.eventGetType(event) == Event.ONDBLCLICK){
          //The event was a double-click on buttonA.
          // Disable this event preview to allow one
          // single-click event to get through the filter.
          // The event preview will be reinstated by the
          // single-click event handler after it completes
          // its work.
          DOM.removeEventPreview(eventPrevue);
          //Cause buttonA to fire a single-click event
          // to cause the single-click event handler
          // method to be executed as a result of this
          // double-click event.
          buttonA.click();
          System.out.println("handled");//Complete the msg
          //Return true or false, it doesn't matter which,
          // because nothing normally happens as a result
          // of a double-click event anyway.
          return true;
        }else{
          
          if(DOM.eventGetType(event) == Event.ONCLICK){
            //Complete the message and cancel single-click
            // events on buttonA.
            System.out.println("cancelled");
            return false;
          }else{
            //Don't cancel other event types on buttonA.
            if(DOM.eventGetType(event) != 
                                       Event.ONMOUSEMOVE){
              //Complete the message.
              System.out.println("passed through");
            }//end if
            
            return true;
          }//end else

        }//end else
      }//end if
      return true;//Wasn't buttonA, just ignore it.
    }//end onEventPreview
  }//end class EventPrevue
  //====================================================//

}//end class GwtApp023


Copyright

Copyright 2007, Richard G. Baldwin.  Reproduction in whole or in part in any
form or medium without express written permission from Richard Baldwin is
prohibited.

Download

Resources

About the author

Richard Baldwin is a
college professor (at Austin Community College in Austin, TX) and private
consultant whose primary focus is a combination of Java, C#, and XML. In
addition to the many platform and/or language independent benefits of Java and
C# applications, he believes that a combination of Java, C#, and XML will become
the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he
frequently provides onsite training at the high-tech companies located in and
around Austin, Texas.  He is the author of Baldwin’s Programming
Tutorials, which have gained a
worldwide following among experienced and aspiring programmers. He has also
published articles in JavaPro magazine.

In addition to his programming expertise, Richard has many years of
practical experience in Digital Signal Processing (DSP).  His first job after he
earned his Bachelor’s degree was doing DSP in the Seismic Research Department of
Texas Instruments.  (TI is still a world leader in DSP.)  In the following
years, he applied his programming and DSP expertise to other interesting areas
including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has
many years of experience in the application of computer technology to real-world
problems.

Baldwin@DickBaldwin.com

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories