October 21, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Using the DOM class in AJAX with the GWT and Java

  • May 22, 2007
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

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






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel