Java Enterprise Java Focus Events, Click Events, and Drag-and Drop in AJAX Using the GWT...

Focus Events, Click Events, and Drag-and Drop in AJAX Using the GWT and Java

Java Programming Notes # 2556


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.

Fourth
in a series

This is the fourth 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 perform drag-and-drop operations in AJAX using the
GWT and Java.  In addition, I will teach you hot to use of the
FocusListener
and ClickListener interfaces.

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. The application GUI at startup.
  • Figure 2. The application GUI after clicking the
    TextBox.
  • Figure 3. The application GUI after clicking the
    Right button.
  • Figure 4. Gaining the focus with the tab key.
  • Figure 5. Firing a click event with the space
    bar.
  • Figure 6. The application GUI at startup.
  • Figure 7. Firing a click event with the space
    bar.
  • Figure 8. Results for mouse events.
  • Figure 9. Application GUI for GwtApp018 at
    startup.
  • Figure 10. Application GUI after dragging the
    custom 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

Focus events

What is focus?

No matter how many applications are running concurrently on a computer and no
matter how many GUIs are showing on the desktop, only one component in one GUI
belonging to one application can respond to the keyboard at any point in time. 
The component that can respond to keyboard input is said to have the focus.

Focus event handling has a long history

Focus events have been available in standard Java since at lease version 1.1 in 1997.
With the release of J2SE version 1.4, Sun completely revamped the focus
subsystem.  Because they added a large number of new capabilities at that
time, dealing with focus in standard Java became much more difficult with the
release of J2SE version 1.4.

Some resources on focus event handling

For an explanation of what is currently possible and an indication of the
complexity of the Focus subsystem in standard Java, see "The AWT Focus
Subsystem" in Resources.

For additional information on the use of the revamped focus subsystem in
standard Java, see
the following tutorials in Resources:

  • "Focus Traversal Policies in Java Version 1.4"
  • "Focusability in Java Version 1.4"
  • "Changing Focus Traversal Keys in Java V1.4"

Something a little less complicated

For a somewhat less complex discussion of focus and the handling of focus
events, see my early tutorial named "Event Handling in JDK 1.1, Requesting the
Focus" in Resources.

That early tutorial was published
long before the release of the revamped focus subsystem in version 1.4. 
However, much of the material in that tutorial maps directly into the GWT focus
subsystem, which is much simpler than the revamped focus subsystem in standard
Java.  The focus subsystem in the GWT looks a lot more like the early focus
subsystem in standard Java than the revamped focus subsystem in J2SE
v1.4.

Handling focus events

The programming process
for handling focus events in the GWT is essentially the same as the process
in standard Java except for the names of a couple of methods and
the types of parameters that those methods receive.

Focus event handlers in standard Java

The focus event handling methods and parameter types in standard Java are:

  • void focusGained(FocusEvent e)
  • void focusGained(FocusEvent e)

The programming process

The programming process
for handling focus events in the GWT consists of the following steps:

  • Define a class that implements the FocusListener interface.
  • Override and provide concrete definitions for the following abstract
    methods that are declared in the interface.  The behavior that results
    from the firing of a focus event is established by the code in the
    overridden methods.
    • void onFocus(Widget sender)
    • void onLostFocus(Widget sender)

  • Instantiate an object of the new class and register it on the GUI
    component that is expected to fire the focus event.
The GWT API Map
The GWT API Map in Resources is a very helpful tool
for supplementing the javadocs when searching for this kind of information.

Which GUI components can fire focus events?

Any GUI component that either defines or inherits the registration method
named addFocusListener can fire focus events.  This includes at
least the following GWT GUI components and possibly some others that I
overlooked in my search:

  • ListBox
  • Frame
  • PasswordTextBox
  • TextBox
  • TextArea
  • Button
  • Checkbox
  • RadioButton
  • FocusPanel
  • Tree

The sample applications in this lesson will concentrate on focus events fired
by Button, TextBox, and FocusPanel objects.

Focus events often occur in pairs

Recall that only one component can
have the focus at any point in time.  When a component gains
the focus, it will fire an onFocus event as a result of gaining the
focus.  If some other component had the focus before, it will fire an
onLostFocus
event as the result of losing the focus.  Therefore, focus
events often occur in pairs.

Don’t always occur in pairs

Be aware, however, that there are situations where one component can lose the focus
without another component (in the same application at least) gaining the
focus.  Similarly, there are situations where a component can gain the
focus but there was no component in the same application that previously had the
focus.  An example of this latter situation is the case where the
application first starts running and a component gains the focus at startup. 
Since the application was not previously running, it is not possible that some
component belonging to that application could have had the focus.

A visual indication of focus

Most GUI components provide a visual indication to the user that the
component has the focus.  (Note the
sidebar
later in this document that discusses an apparent bug in the GWT
regarding the visual indication of focus, or the lack thereof.)
  The actual visual indicator will depend on the
look and feel ascribed to the components being used.

Perhaps the most consistent visual indication of focus among all of the GUI
components across many operating systems is the existence of a blinking cursor
in components that allow the user to enter text into the component.  Just
about everyone who uses a computer recognizes the blinking cursor as an
indication that it is OK to enter text.  You will see some visual
indications of focus in the sample applications in this tutorial.

Focus traversal

In most cases, repeatedly pressing the tab key will cause the focus to move
among the components in a GUI according to a specified traversal path.  Also,
in most cases, holding down the Shift key and repeatedly pressing the tab key
will cause the focus to move among the same components in the reverse of the
specified
traversal path.

Two ways to establish the traversal path

Standard Java is more complex
If you have looked into the Sun document named "The AWT Focus Subsystem"
(see Resources),
you have probably noticed that
the techniques for establishing the traversal path in post-v1.4 standard
Java are much more sophisticated and much more complicated than those
described here for the GWT.  The techniques described here for the GWT
are very similar to those that existed for pre-v1.4 standard Java.

There appear to be at least two ways for the programmer to establish the
focus traversal path in the GWT.  The most straightforward way is to allow
the traversal path to be established automatically on the basis of the order in
which the components are placed in their container.

The setTabIndex method

A more complicated way of establishing the traversal path is to invoke a method named setTabIndex on each
component in the GUI passing an int value as a parameter to the method. 
According to the GWT documentation, this

"Sets the widget’s position in the tab index. If more than one widget
has the same tab index, each such widget will receive focus in an arbitrary
order. Setting the tab index to -1 will cause this widget to be
removed from the tab order."

Having set a tab index value on each component, repeatedly pressing the tab
key will cause the focus to move among the components in increasing numeric
tab-index order.  Holding down the Shift key while repeatedly pressing the
tab key will reverse the traversal path.

Click events

What is a click event?

A click event is an event that is fired by a component to indicate that a
specific action has occurred with respect to the component.  The most common way
to cause a component to fire a click event is to click it with the mouse
(hence the interface name addClickListener and the method name onClick)

In addition, some components can fire click events as a result of certain
keyboard actions while the component has the focus.

Two examples of keyboard actions and click events

For example, pressing the space bar when a Button object has the focus
will cause the button to fire a click event in the GWT and will cause the button
to fire an ActionEvent in standard Java.  (A click event in the
GWT is analogous to an action event in standard Java.)

On the other hand, pressing the Enter key when a standard Java TextField
object has the focus will cause it to fire an ActionEvent, but pressing
the Enter key when a GWT Textbox object has the focus will not cause it
to fire a click event.  (The similarity between the two breaks down in this case.)

ActionEvent handling in standard Java

Click events in the GWT are analogous to Action events in standard Java. 
The programming process for handling Action events consists of the following steps:

  • Define a class that implements the ActionListener interface.
  • Override and provide a concrete definition for the following abstract
    method that is declared in the interface.  The behavior that results
    from the firing of an Action event is established by the code in the
    overridden method.
    • void actionPerformed(ActionEvent e)

  • Instantiate an object of the new class and register it on the GUI
    component that is expected to fire the Action event.

Handling click events

The programming process for handling click events in the GWT is essentially the same as the process
in standard Java except for the name of the interface, the name of the single
event handling method, and
the type of parameter that the event handling method receives. 

The programming process

The programming process
for handling click events in the GWT consists of the following steps:

  • Define a class that implements the ClickListener interface.
  • Override and provide a concrete definition for the following abstract
    method that is declared in the interface.  The behavior that results
    from the firing of a click event is established by the code in the
    overridden method.
    • void onClick(Widget sender)

  • Instantiate an object of the new class and register it on the GUI
    component that is expected to fire the click event.

Which GUI components can fire click events?

Any component that either defines or inherits the registration method named
addClickListener can fire a click event.  This includes at least the
following GWT GUI components and possibly some others that I overlooked during
my search:

  • ListBox
  • Frame
  • PasswordTextBox
  • TextBox
  • TextArea
  • Button
  • Checkbox
  • RadioButton
  • FocusPanel
  • Hyperlink
  • Image
  • Label
  • HTML

The first sample application in this lesson will concentrate on click events
fired by Button and TextBox objects.

Drag-and-drop

Credit to Mr. Eric Sessoms

The GWT drag-and-drop sample application in this
lesson is not a creation of my own design.  Rather,
the technical information and the ideas behind the sample application were taken
(with written permission via Email) from the original author whose name
is Eric Sessoms.  (See Drag and Drop using the GWT in
Resources.)

Will defer to Eric Sessoms blog for background
information

Mr. Sessoms does a much better job than I could do with regard to the
General background information on performing drag-and-drop with the GWT. 
Therefore, I will refer you to his blog for that information.  I will
content myself with attempting to explain how and why the sample application
behaves as it does.

Depends heavily on handling mouse events

I will point out, however, that the drag-and-drop technique described herein depends heavily
on the use of mouse events, the MouseListener interface, and the
MouseListenerAdapter
class.  If you haven’t already studied my earlier
lesson named "Event driven programming in AJAX using the GWT and Java" (see
Resources)
where I explain the handling of mouse
events in some detail, now would be a good time to do so.

Preview

Three sample GWT
web applications

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

  • GwtApp016 – Focus events and click events.
  • GwtApp017 – Creating a custom button component that fires mouse events.
  • GwtApp018 – Performing drag-and-drop operations on the custom button
    component.

Discussion
and sample code


Complete program listings

I will discuss
the code for the following applications in fragments.  A complete listings
of each application is provided in Listing 22 through Listing 27 near the end of the
lesson.

The HTML host pages

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. 
Therefore, I won’t discuss them in this lesson.  However, a complete listing of
each HTML host page is provided in Listing 22
through Listing 27 along with the Java source code for the application.

GwtApp016 – Focus events and
click events

The application GUI at startup

Figure 1 shows a screen shot of the application named GwtApp016 at
startup when running in Internet Explorer 6.

Figure 1. The application GUI at startup.

The row of Label objects shown at the bottom in Figure 1 contains column
headers for three columns that will contain the following information:

  • Which component (if any) lost the focus?
  • Which component (if any) gained the focus?
  • Which component (if any) fired a click event?

There is no information showing under those column headers at startup because
no component has yet gained the focus, no component has yet lost the focus, and
no component has yet fired a click event.


The application GUI after clicking the TextBox

Figure 2 shows the state of the GUI after the user started the application
running and then clicked the TextBox object once with the mouse.

Figure 2. The application GUI after clicking the
TextBox.

The information in the middle column shows that this caused the text box to
gain the focus.  However, the left column is still blank because at this
point, no component lost the focus because no component had the focus at
startup.

The right column in Figure 2 shows that the text box fired a click event when
the user clicked the text box with the mouse.

The application GUI after clicking the Right button

Figure 3 shows the state of the GUI as a result of the user clicking the
Right button while the text box had the focus.

Figure 3. The application GUI after clicking the
Right button.

Why no visual indication of focus?
Note that even though the Right button has the focus in Figure 3, the button
is not displaying a visual indication of focus.  This problem manifests
itself when the application is run in either IE6 or hosted mode. 
However, the problem does not manifest itself when the application is run in Firefox. 
A visual indication of focus appears as it should when the application is
run in Firefox.  This
strongly suggests that this is a bug in the GWT, and a fairly serious one
from a user perspective.

The left column in Figure 3 shows that the text box lost the focus.  The
middle column shows that the Right button gained the focus.  The right
column shows that the Right button also fired a click event as a result of the
user clicking the Right button with the mouse.


Gaining the focus with the tab key

Figure 4 shows the result of restarting the application and pressing the tab
key repeatedly until the Right button gains the focus.

Figure 4. Gaining the focus with the tab key.

A visual indication of focus.
Note that unlike Figure 3, there is a visual indication of focus on the
Right button in Figure 4.  This is what we would expect to always be the case when the
button has the focus.  However, it appears that clicking the button in
either IE6 or hosted mode does not cause the button to provide a visual
indication of focus, even though it clearly gains the focus.  As
mentioned earlier, this is not a problem in Firefox.

The focus traversal path

Because of the order in which the components were placed in their container,
the forward focus traversal path for the tab key is from left to right across
the two buttons and the text box.  Thus, when the Right button gained the
focus, the text box lost the focus as shown by the information in the two left
columns in Figure 4.

No click event showing

Note that the right column in Figure 4 is still blank because no click events have been fired since the application was restarted.


Firing a click event with the space bar

Figure 5 shows the result of pressing the space bar while the Right button
has the focus as shown in Figure 4.

Figure 5. Firing a click event with the space bar.

A click event was fired

The right column in Figure 5 shows that a click event was fired by the Right
button as a result of pressing the space bar on the keyboard while the Right
button had the focus.

Description of the application

This application demonstrates FocusListener, ClickListener, and
tool tips.

It places two Button objects and a TextBox object in a
HorizontalPanel
object as shown in Figure 1.

Listeners

The application defines inner classes (not anonymous inner classes)
that implement listener interfaces.  One inner class implements the
FocusListener
interface and the other class implements the ClickListener
interface.

The application instantiates and registers FocusListener and
ClickListener
objects on each of the buttons and on the text box.

Titles for tooltips

The application also sets a title on each button and on the text box to cause each of
them to show tooltips whenever the mouse pointer hovers over the
component.  (Figure 2 shows a tooltip immediately below the Right
button.  Note however, that the screen shot did not capture the image of
the mouse pointer in Figure 2.)

A simple table to display event information

As shown in Figure 3, the application uses HorizontalPanel objects,
Label
objects, and a VerticalPanel object to create a simple table
that shows which components fired events of the following types (going from
left to right in Figure 3)
:

  • onLostFocus
  • onFocus
  • onClick
Not always reliable
Note: The table does not display reliable focus lost and focus gained
information in those cases where the focus leaves all three of the components
shown in Figure 3.

The tooltip titles are also used to identify the components that fired each
specific event when the information is displayed in the table.

Application 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.


Beginning of the class definition

Listing 1 shows the beginning of the class definition and the beginning of
the onModuleLoad method for the application named
GwtApp016.

Listing 1. Beginning of the class definition for
GwtApp016.

package GwtApp.client;

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

public class GwtApp016 implements EntryPoint{
  //These three labels are used for text output. They are
  // declared as instance variables to make them accessible
  // by the methods in the inner classes.
  private Label label20;
  private Label label21;
  private Label label22;

  //This is the entry point method.
  public void onModuleLoad(){
    //Create the basic structure of the GUI.
    HorizontalPanel topPanel = new HorizontalPanel();
    topPanel.setSpacing(5);
    
    HorizontalPanel middlePanel = new HorizontalPanel();
    middlePanel.setSpacing(5);
    
    HorizontalPanel bottomPanel = new HorizontalPanel();
    bottomPanel.setSpacing(5);    
    
    VerticalPanel vertPanel = new VerticalPanel();
    vertPanel.add(topPanel);
    vertPanel.add(middlePanel);
    vertPanel.add(bottomPanel);

I have explained code similar to the code in Listing 1 in numerous sample
applications in previous lessons.  Therefore, there should be no need for a
further explanation of the code in Listing 1 beyond the explanation provided by
the embedded comments.


Populate the top HorizontalPanel object

Listing 2 populates the top HorizontalPanel object with two Button
objects and a TextBox object.

Listing 2. Populate the top HorizontalPanel object.

    //Populate the topPanel with two buttons and a TextBox
    Button button00 = new Button("Left");
    TextBox textBox = new TextBox();
    textBox.setText("TextBox");
    Button button02 = new Button("Right");

    //Make the buttons the same width.
    button00.setWidth("50px");
    button02.setWidth("50px");

    //Add the three components to the horizontal panel
    topPanel.add(button00);
    topPanel.add(textBox);
    topPanel.add(button02);

Once again, there is nothing new in Listing 2, so I won’t discuss it further.


Some more common code

Listing 3 populates the middle and bottom panels using code similar to the
code that you have seen in numerous previous sample applications. 
Therefore, I won’t discuss the code in Listing 3 any further.

Listing 3. Some more common code.

    //Populate the middle panel with three labels. These
    // labels serve simply to explain the contents of the
    // three labels below them.
    Label label10 = new Label("Lost Focus");
    Label label11 = new Label("Gained Focus");
    Label label12 = new Label("Was Clicked");
    label10.setWidth("85px");
    label11.setWidth("85px");
    label12.setWidth("85px");
    middlePanel.add(label10);
    middlePanel.add(label11);
    middlePanel.add(label12);
    
    //Populate the bottom panel with three output labels.
    // The contents of these three labels are modified by
    // the code in the event handlers to explain the
    // events.
    label20 = new Label("");
    label21 = new Label("");
    label22 = new Label("");
    label20.setWidth("85px");
    label21.setWidth("85px");
    label22.setWidth("85px");
    bottomPanel.add(label20);
    bottomPanel.add(label21);
    bottomPanel.add(label22);


Set the tooltip text

We’ve finally gotten to some code that is new to this lesson.  The code
in Listing 4 sets the tooltip text for each of the three components, by invoking
the setTitle method on each of the components.  Invoking the
setTitle
method on a component in the GWT is all that is required to cause
the component to display a tooltip.

Listing 4. Set the tooltip text.

    button00.setTitle("Left Button");
    textBox.setTitle("TextBox");
    button02.setTitle("Right Button");

The titles that are set in Listing 4 serve not only as tooltip text, but also
serve as text identifiers for the components that gain the focus, lose the focus, and
fire click events.  These text identifiers are displayed in the table shown in Figure 3.


Register listener objects

Listing 5 begins by instantiating a listener object of the inner class named
FocusLstnr.  Then it registers that single common listener object on
each of the buttons and on the text box.

Listing 5. Register listener objects.

    //Register a common focus listener on each button and
    // on the text box.
    FocusLstnr focusLstnr = new FocusLstnr();

    button00.addFocusListener(focusLstnr);
    textBox.addFocusListener(focusLstnr);
    button02.addFocusListener(focusLstnr);
    
    //Register a common click listener on each button and
    // on the text box.
    ClickLstnr clickLstnr = new ClickLstnr();

    button00.addClickListener(clickLstnr);
    textBox.addClickListener(clickLstnr);
    button02.addClickListener(clickLstnr);
    
    //Add the vertical panel to the browser window. The
    // vertical panel serves as a backbone and the three
    // horizontal panels serve as ribs.
    RootPanel.get().add(vertPanel);
    
  }//end onModuleLoad method

The code in Listing 5 also instantiates a common listener object of the
inner class named ClickLstnr.  Then it registers that common
listener object on each of the buttons and on the text box.  As a result,
both a focus listener and a click listener are registered on both buttons and on
the text box.

Add the VerticalPanel to the RootPanel and end the
method

Finally, the code in Listing 5 adds the populated VerticalPanel object
to the RootPanel, thereby completing the construction of the application
GUI.

Listing 5 also signals the end of the onModuleLoad method.


Define the inner class named ClickLstnr

A member class
An inner class is also known as a member class.  (See "The
Essence of OOP using Java, Member Classes" in
Resources
for more information.)

Listing 6 defines the inner class named ClickLstnr.  It was defined as an inner
class in this application so that the interface method named onClick would have direct access to one of the three output Label objects.

As you can see, this class implements the ClickListener interface and
defines the onClick method that is declared in that interface.  This
is the only method that is declared in the ClickListener interface.

Listing 6. Define the inner class named ClickLstnr.

  class ClickLstnr implements ClickListener{
    public void onClick(Widget sender){
      label22.setText(sender.getTitle());
    }//end onClick
  }//end class ClickLstnr

Need to identify the source of the event

The onClick method in Listing 6 is executed any time that any of the
three components fires a click event.  Therefore, it is necessary for the
method to
identify the component that fired the event.  Fortunately, the incoming parameter named
sender of type Widget points back to the component that fired the
event.

The code in Listing 6 invokes the getTitle method on that reference to
get the tooltip title that was established for the component earlier. 
Then it displays that title in the rightmost column in the table in Figure 3 to
identify the component that fired the click event.


Define member class named FocusLstnr

Listing 7 defines the inner (member) class named FocusLstnr
This class implements the interface named FocusListener and defines the
two event handler methods declared in that class.  As before, this class
was made an inner class so that the code in the each method would have
direct access to the label used to display results for that method.

Listing 7. Define member class named FocusLstnr.

  class FocusLstnr implements FocusListener{
    
    public void onLostFocus(Widget sender){
      label20.setText(sender.getTitle());
    }//end onLostFocus
    //---------------------------------------------------//
    
    public void onFocus(Widget sender){
      label21.setText(sender.getTitle());
    }//end onFocus
  }//end class FocusLstnr
  //=====================================================//

}//end class GwtApp016

When are the two methods executed?

As you probably already know, one of the methods in Listing 7 is executed when a
component loses the focus and fires an event whose type corresponds to the onLostFocus
method.  The other
method is executed when a component gains the focus and fires an event whose
type corresponds to the onFocus method.

The code in each of the methods in Listing 7 is essentially the same as the code in Listing 6,
except that the identification of the component that fired the event is
displayed in one of the two columns on the left in Figure 3.

The end of the class

Listing 7 also signals the end of the class named GwtApp016.

At this point, you have learned much of what there is to know about the focus
subsystem in the GWT.  What you have learned will be useful in
understanding the next two sample applications.

A few things that you haven’t learned

As indicated earlier, the GWT focus subsystem is much simpler than the focus
subsystem in post-v1.4 standard Java.  However, there are a few features of
the GWT focus subsystem that weren’t discussed here.  You can learn about
them by going to the index in the javadocs, searching for the word "focus" and
reading about any interesting methods that you turn up in that process.

GwtApp017 –
Creating a custom button component

Do you understand the handling of GWT mouse events?

In order to understand the material in this application, you will need to
understand quite a lot about the handling of mouse events in the GWT.  I
explained mouse event handling in the earlier lesson named "Event driven
programming in AJAX using the GWT and Java" (see
Resources
)
.  If you haven’t studied that lesson yet, I suggest that
you do so at this time.

Which components can fire mouse events?

Any component that either defines or inherits the registration method named
addMouseListener can fire a mouse event.  This includes the following GWT
GUI components and possibly some others that I may have missed in my
search:

  • Label
  • HTML
  • Image
  • FocusPanel
  • Tree

All in all, that is a rather short list, at least in comparison to the number
of GUI components that can fire mouse events in standard Java.

Forcing a GUI component to fire mouse events

Other event types
This application is written around the concept of forcing a component to fire
mouse events, but it could just as well have been written around the concept of forcing
a component to fire click events or focus events.

What if you have a need for a GWT GUI component to fire mouse events but that
component is not included
in the above list
I’m going to show you how to force a Button to fire mouse events in this
application.  I will show you why you may want to do that in the next
application.

Not restricted to Button objects

The technique that I will describe here is not restricted to Button objects.  You should
be able to use what I am going to show you in this application to force any
component to fire mouse events, click events, or focus events.

The application GUI at startup

Figure 6 shows the application GUI at startup.  The large button in
Figure 6 is a custom button that fires mouse events.

Figure 6. The application GUI at startup.

The output data

The five labels below the button show the results of handling mouse events
and click events that are fired by the button as the user manipulates the mouse and the keyboard with
respect to the button.  Each of the labels shows the default values at
startup in Figure 6.

The five labels display the following information:

  1. Whether the mouse pointer is inside or outside the area occupied by the
    custom button.  As you can see the default value is Out
    This label will display In when the mouse pointer is inside the
    custom button’s
    area.
  2. The coordinates of the last location recorded as the mouse is moved
    within the area occupied by the custom button.  These coordinate values
    are dynamic values that continuously change as the mouse is moved within
    that area.  As you can see, the default coordinate values at startup
    are both 0.  The coordinate values are given in pixels relative to the
    upper left corner of the custom button.
  3. The coordinates of a point within the custom button’s area where a mouse button was most
    recently pressed.  These coordinate values change each time the user
    presses a mouse button while the mouse pointer is inside the area occupied
    by the custom button.
  4. The identification of the component (if any) that fired the most recent click
    event.
  5. The identification of another component (if any) that fired the most recent click
    event.  The meaning of these two output values will become clearer
    once you understand the code that is used to create the custom button.


Firing a click event with the space bar

Figure 7 shows the result of:

  • Starting the program.
  • Repeatedly pressing the tab key until the custom button gains the focus.
  • Pressing the space
    bar.

Figure 7. Firing a click event with the space bar.

No mouse events

As you can see, the top three labels that are used to show the results of handling mouse events
still have their default values in Figure 7.  That is because no mouse
events had yet been fired when the screen shot was taken.  However, using the tab key to cause the custom
button to gain the focus and then pressing the space bar caused two components
to fire click events as shown by the bottom two labels.

Why two components?

It is probably time to provide a little more explanation about the two
components that fired click events.  A you can see, the two components are identified in Figure 7
as:

  • Button
  • Custom Button

The custom button is actually the composite of a Button object and a
FocusPanel object.  The button is wrapped in the focus panel,
and the composite of the two is considered to be the custom button. 
However, there are two separate components involved and each has the native ability
to fire a click event.

The Button referred to in Figure 7 is the ordinary button that is
wrapped in the focus panel.  The Custom Button that is referred to
in Figure 7 is actually the FocusPanel that wraps the Button
These are the two components for which click events are recorded in the bottom
two labels in Figure 7.


Results for mouse events

Where is the mouse pointer?
Note that the process of capturing the screen shot in Figure 8 did not capture
the image of the mouse pointer, which was pointing to the "n" when the
screen shot was taken.

Figure 8 shows the result of using the mouse to point to and click on the
upper-case "C" in the button caption, and then moving the mouse pointer to the
right and letting it rest on the lower-case "n".

Figure 8. Results for mouse events.

How many components fired mouse events?
Unlike the click events discussed earlier, in this case only the FocusPanel
that wraps the standard Button object fired mouse events, because the Button
object does not have the native ability to fire Mouse Events.

Are you in or out?

The first label under the button shows that the mouse pointer was In
the area occupied by the custom button when the screen shot was taken.

The Last Move Location

The second label under the button shows the coordinates of the lower-case
"n", which was the location of the mouse pointer when the screen shot was taken. 

The Last Down Location

Mouse moved versus mouse dragged
The mouse-event results
would have been the same if the mouse button had been held down while making the
move, because unlike standard Java, the GWT makes no distinction between
"mouse moved"
and "mouse dragged."

The third label under the button shows the coordinates of the upper-case "C",
which was the location of the mouse pointer when the mouse button was pressed
and then released before moving it to the lower-case "n".

The click event

The bottom two labels show the results of the click event that was fired when
the mouse button was pressed and then released.

Description of the application

This application demonstrates the creation of a custom button that can fire mouse events and
otherwise behaves more or less like a standard Button component.

What is a FocusPanel?
According to the javadocs, a FocusPanel object is "A simple panel that makes its contents focusable, and adds the ability to catch mouse and keyboard events."

One way to establish the contents of a FocusPanel is to pass another
object’s reference as a parameter to the constructor when the panel is
constructed.

Wrap a Button in a FocusPanel

The application wraps a standard Button
object in a FocusPanel object to create the custom button.  An object of the
FocusPanel that wraps the standard button then behaves more or less like a standard
button except that it can fire mouse events in addition to click events and focus events.

Set tooltip titles

Which tooltip is displayed?
The tool tip that is displayed is the title that is set on the standard button
and is not the title that is set on the custom button

The application sets titles on
the standard button and the custom button in order to display tool tips when the
mouse pointer hovers on the custom button.

Another use for tooltip titles

The titles are also used to identify the component that fires a
click event when the mouse button is pressed in the area occupied by the custom
button or when the space bar is pressed while the standard button wrapped in the
FocusPanel has the focus.  When this happens, both the standard button and the
custom button fire a click event.

Construction of the GUI

The application puts the custom button along with five Label
objects in a VerticalPanel object as shown in Figure 6.  The labels are used to display the following
output data when the user manipulates the custom button with the mouse or the
keyboard:

  1. Whether the mouse pointer is inside or outside the area occupied by
    the custom button.
  2. The mouse pointer location as the mouse is moved within the
    area occupied by the custom button.
  3. The location of the mouse pointer when a
    mouse button is pressed within the area occupied by the custom button.
  4. The title of the standard button that fired a click event when the mouse button
    was
    pressed within the area occupied by the custom button or when the space bar was
    pressed while the standard button that is wrapped in the FocusPanel had the focus.
  5. The title of the custom button that fired a click event when the mouse button
    was
    pressed within the area occupied by the custom button or when the space bar was
    pressed while the standard button that is wrapped in the FocusPanel had the focus.

Register a mouse listener

The application registers an
anonymous MouseListener object on the custom button to provide the information
displayed in the first three labels described above.

Register a click listener

The application also registers an anonymous ClickListener object on the standard button to provide the information displayed
in the fourth label described above.  This information demonstrates that the standard button
fires click events despite the fact that it is wrapped in a FocusPanel object.

Register another click listener

Finally, the application also registers an anonymous ClickListener object on the custom button to
provide the information for the fifth label.  This information demonstrates that the custom
button also fires click events when the mouse button is pressed while the mouse
pointer is inside the area occupied by the custom button.  It also demonstrates
that the custom button fires a click event if the user presses the space bar
while the standard button that is wrapped in the FocusPanel has the focus.

Firing a click event from the keyboard

When a
standard button has the focus and the user presses the space bar, the standard
button fires a click event.  When the standard button that is wrapped in the
FocusPanel representing the custom button has the focus and the user presses the
space bar, the standard button and the custom button both fire a click event. 
Therefore, a click listener that is registered on the custom button will see
the event.

Causing the standard button to gain the focus

One way to cause the standard button that is wrapped in the FocusPanel
to gain the focus is to click it with the mouse.  That will, of course,
cause both a click event and a focus event to be fired. 

Another way to cause the standard button to gain the focus is to press the
tab key repeatedly.  When you do that, you will see the standard
button that is wrapped in the FocusPanel gain the focus.  However,
you will not see the FocusPanel gain the focus.  (The application
purposely uses the setTabIndex method to disable the ability of the FocusPanel to
gain the focus.)

Application 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.

Beginning the class definition for GwtApp017

The class definition for the application named GwtApp017 begins in
Listing 8.

Listing 8. Begin class definition for GwtApp017.

package GwtApp.client;

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

public class GwtApp017 implements EntryPoint{

  //This is the entry point method.
  public void onModuleLoad(){
    //Create a VerticalPanel to contain a custom button
    // along with several labels that are used to display
    // output data.
    VerticalPanel vertPanel = new VerticalPanel();
    
    //Create labels used to display output data. Must be
    // final to make them accessible by an object of an
    // anonymous inner class.
    final Label inOrOut = new Label("In or Out: Out");
    final Label lastMoveLocation = 
             new Label("Last Move Location: x = 0, y = 0");
    final Label lastDownLocation = 
             new Label("Last Down Location: x = 0, y = 0");
    final Label clickSenderA = 
                          new Label("Click SenderA: None");
    final Label clickSenderB = 
                          new Label("Click SenderB: None");

The code in Listing 8 is the same as, or very similar to code that you have
seen in numerous previous applications.  Therefore, no explanation beyond
the embedded comments should be needed at this point.


Create the custom button

The code in Listing 9 creates a custom button that will respond to mouse events by wrapping a standard button in a
FocusPanel object.

Listing 9. Create the custom button.

    Button button = new Button("Custom Button");
    button.setSize("100px","50px");
    
    FocusPanel customButton = new FocusPanel(button);
    customButton.setSize("100px","50px");

Listing 9 also forces the FocusPanel object to be the same size as the standard button
that it contains.


Cause the focus to skip the FocusPanel

When you repeatedly press the tab key in this case, you don’t want the focus to first land
on the FocusPanel and then move to the standard button on the next press of
the tab key.  Rather, you want the focus to skip the FocusPanel and
land directly on the standard button.

Listing 10. Cause the focus to skip the FocusPanel.

    customButton.setTabIndex(-1);
The setTabIndex method
According to the javadocs, the setTabIndex method "Sets the widget’s
position in the tab index. … Setting the tab index to -1 will
cause this widget to be removed from the tab order."

The code in Listing 10 causes the focus to skip the FocusPanel and go straight to the button that is wrapped in the
FocusPanel.


Miscellaneous code

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

Listing 11. Miscellaneous code.

    //Set titles that are used for tootips and are also
    // used to identify the source of click events.
    button.setTitle("Button");
    customButton.setTitle("Custom Button");

    //Add the components to the vertical panel.
    vertPanel.add(customButton);
    vertPanel.add(inOrOut);
    vertPanel.add(lastMoveLocation);
    vertPanel.add(lastDownLocation);
    vertPanel.add(clickSenderA);
    vertPanel.add(clickSenderB);
    
    //Add the vertical panel to the browser window.
    RootPanel.get().add(vertPanel);


Register a mouse listener on the custom button

Listing 12 registers a mouse listener on the custom button by defining and instantiating an object of an anonymous inner class that extends the class named
MouseListenerAdapter.

Listing 12. Register a mouse listener on the custom
button.

    //Register a MouseListener on the custom button.
    customButton.addMouseListener(
      new MouseListenerAdapter(){
        public void onMouseEnter(Widget sender){
          inOrOut.setText("In or Out: In");
        }//end onMouseEnter
        //-----------------------------------------------//
        
        public void onMouseLeave(Widget sender){
          inOrOut.setText("In or Out: Out");
          
          //Clear the clickSender labels when the mouse
          // pointer moves out of the area occupied by the
          // custom button to prepare for displaying the
          // results of the next click event.
          clickSenderA.setText("Click SenderA: None");
          clickSenderB.setText("Click SenderB: None");
        }//end onMouseLeave
        //-----------------------------------------------//
        
        public void onMouseMove(Widget sender,int x,int y){
          lastMoveLocation.setText(
            "Last Move Location: x = " + x + ", y = " + y);
        }//end onMouseMove
        //-----------------------------------------------//
        
        public void onMouseDown(Widget sender,int x,int y){
          lastDownLocation.setText(
            "Last Down Location: x = " + x + ", y = " + y);
        }//end onMouseMove
        //-----------------------------------------------//
      }//end constructor
    );//end addMouseListener

By now, the code in Listing 12 should be "old stuff" to you.  If it
isn’t, see the earlier lesson named "The Essence of OOP using Java, Anonymous
Classes" in Resources.


Register click listeners on the standard button and the custom button

Listing 13 registers click listeners on the standard button and the custom
button.

Listing 13. Register click listeners on the standard
button and the custom button.

    //Register a ClickListener on the standard button. This
    // listener demonstrates that you can still receive
    // click events from the standard button despite the
    // fact that it is wrapped in a FocusPanel object.
    button.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          clickSenderA.setText(
                    "Click SenderA: " + sender.getTitle());
        }//end onClick
      }//end constructor
    );//end addClickListener
    //===================================================//
    
    //Register a ClickListener on the custom button. This
    // listener demonstrates that you can also receive
    // click events from the custom button.
    customButton.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          clickSenderB.setText(
                    "Click SenderB: " + sender.getTitle());
        }//end onClick
      }//end constructor
    );//end addClickListener
    //===================================================//
    
  }//end onModuleLoad method
  //=====================================================//

}//end class GwtApp017

Once again, by now, the code in Listing 13 should also be "old stuff" to you. 
If it isn’t, see the earlier lesson named "The Essence of OOP using Java,
Anonymous Classes" in Resources.

End of the GwtApp017 class

Listing 13 also signals the end of the definition of the class named
GwtApp017
, and the end of the discussion of the application having the same
name.

GwtApp018 –
Drag-and-drop on a custom button component


Application GUI for GwtApp018 at startup

Figure 9 shows the application GUI at startup.

Figure 9. Application GUI for GwtApp018 at startup.

The custom button
The custom button used in this application is the same as the custom button
used in the earlier application named GwtApp017.

The GUI for this application is fairly simple.  It consists of a custom
button that can be dragged using the mouse along with a couple of labels that
were purposely placed there to show what happens when the component being
dragged encounters another component.


Application GUI after dragging the custom button

Figure 10 shows a screen shot of the application GUI after the custom button
has been dragged down the screen far enough to encounter the two Label
objects.

Figure 10. Application GUI after dragging the custom
button.

As you can see, the custom button in its new location appears to be on top of
one of the Label objects and under the other Label object.  I
will explain how this comes about once we get into the code.

Description of the application

This application demonstrates the use of mouse events to perform a
drag-and-drop operation on a custom button component.

Not very smooth in hosted mode
The drag operation is not very smooth when the application is run in hosted
mode.  However, it runs smoothly in both Firefox 1.5.0.8 and Internet
Explorer 6.0.29

Create a custom button

The application creates a custom button that can fire mouse events and
otherwise behave more or less like a standard button.  The ability to fire
mouse events is critical to the operation of the drag-and-drop algorithm
implemented by this application.

Wrap a standard Button in a FocusPanel

A standard Button
object is wrapped in a FocusPanel object to create the custom button. 
The FocusPanel object then behaves more or less like a standard button
except that it can fire mouse events in addition to click events and focus
events.

Application 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.

Begin the class definition

The class definition begins in Listing 14.

Listing 14. Begin the class definition for GwtApp018.

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 GwtApp018 implements EntryPoint{

  //This is the entry point method.
  public void onModuleLoad(){
    
    //Create a custom button that will fire mouse events
    // by wrapping a standard button in a FocusPanel.
    // Force the FocusPanel to be the same size as the
    // standard button.
    Button button = new Button("Custom Button");
    button.setSize("120px","50px");
    FocusPanel customButton = new FocusPanel(button);
    customButton.setSize("120px","50px");

    //Cause the focus to skip the FocusPanel and go
    // straight to the button that is wrapped in the
    // FocusPanel.
    customButton.setTabIndex(-1);

There is nothing new in Listing 14 so I won’t discuss it further.

Define an anonymous class

Listing 15 shows the beginning of the code that defines an anonymous
MouseListener
class and registers an anonymous MouseListener object instantiated from
the anonymous class on the custom button. The methods of this class will be used to perform a
drag-and-drop operation on the custom button.

Listing 15. Define an anonymous class.

    customButton.addMouseListener(
      new MouseListenerAdapter(){
        
        //Declare some local working varibles.
        private boolean dragging;
        private int     xOffset;
        private int     yOffset;

The code in Listing 15 declares some local working variables that will be
used later to implement the drag-and-drop operation on the custom button.


The setCapture method

Listing 16 shows the beginning of the onMouseDown method and the
invocation of the static setCapture method of the Dom class.

Listing 16. The setCapture method.

        public void onMouseDown(Widget sender,int x,int y){
          DOM.setCapture(sender.getElement());

The use of the Dom class is new to this lesson.  According to the
javadocs, 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."

Many static methods

The Dom class defines dozens of static methods, including the method
named setCapture.  According to the javadocs, the setCapture
method:

"Sets mouse-capture on the given element. This element will directly
receive all mouse events until releaseCapture(Element) is called on
it."

Capturing the custom button

The custom button in this application is captured for dragging when any of the three mouse buttons is pressed while the mouse pointer is inside the area occupied by the custom button.  Note, however, that pressing any mouse button other than the left button may
also cause browser-specific behavior associated with the button to occur.

A somewhat complicated discussion

You need to be aware that at this point, the discussion fuses the concepts of
Java objects and HTML elements.  This is because the Java source code is
ultimately compiled into JavaScript code that acts on HTML elements.

What Java object?
I suppose that in reality, the Java object that fires the onMouseDown event
mentioned here never really exists.  The Java source code is compiled
directly into JavaScript code before the application is executed and Java
objects don’t exist unless Java source code is compiled and executed under
control of a Java virtual machine.  Having thought about and talked
about Java objects for years, I find it a little difficult to wrap my mind
around the concept of writing Java source code that will never be executed
by a Java virtual machine but will still result in a program that executes
and behaves the way I expect it to behave.  Those folks at Google are
pretty smart.

Capturing an HTML element

Invocation of the setCapture method in Listing 16 sets mouse-capture
on the HTML element that is represented by the Java object that fired the
onMouseDown
event.

Receive all mouse events

As described earlier, the specified element (the custom button in this
case)
will directly receive all mouse events until the method named
releaseCapture
is called on it.  (The releaseCapture method will
be called later in the onMouseUp event handler method.)

Stop receiving all mouse events

In other
words, when the user releases the mouse button to drop the custom button in a
new location, this will cause the custom button to fire an onMouseUp
event, the releaseCapture method will be called on the custom button, and
the custom button will no longer receive all mouse events.

Getting back to the getElement method…

Now let’s get back to the getElement method used in Listing 16.  According
to the javadocs, the Element object returned by the getElement
method provides an opaque handle to a native DOM Element when the Java
code is compiled into JavaScript later.

Why did I set mouse event capture?

In this case, the mouse event capture feature was set so that the custom button will not lose the
mouse events if it is dragged under another component.  For example, if you
disable the statement in Listing 16 and run the application, the custom button will sometimes get stuck when you drag
it under the Bottom Obstacle label shown in Figure 10.


Remaining code in the onMouseDown method

Listing 17 shows the remaining code in the onMouseDown event handler
method.

Listing 17. Remaining code in the onMouseDown
method.

          xOffset = x;
          yOffset = y;

          dragging  = true;
        }//end onMouseDown

Listing 17 records the location of the mouse pointer relative to the
upper-left corner of the custom button when the mouse button is pressed. 
These two values will be needed later to determine the absolute location of the
custom button as it is dragged across the screen.

Listing 17 also set the dragging flag to indicate that a drag
operation is underway.  This flag will be tested later by the
onMouseMove
method.


Implement the actual drag operation

Listing 18 shows the beginning of the onMouseMove event handler
method.  This is the method that actually implements the operation of
dragging the custom button across the screen.

Listing 18. Implement the actual drag operation.

        public void onMouseMove(Widget sender,int x,int y){
          if (dragging){
            int xAbs = x + sender.getAbsoluteLeft();
            int yAbs = y + sender.getAbsoluteTop();

The two statements in Listing 18 (and other statements to follow) are
executed only if a drag operation is in progress as indicated by the state of
the dragging flag.

The two statements in Listing 18 compute the absolute location of the mouse pointer
relative to the upper-left corner of the browser window by adding the x and y
coordinate offset values (relative to the upper left corner of the custom
button)
to the absolute coordinate values of the upper left corner of the
custom button.


Redraw the custom button in a new location

As the user attempts to move the mouse across the custom button, the custom
button attempts to fire a series of onMouseMove
events.  However, each time an onMouseMove event is fired, the custom
button is redrawn in a new location slightly displaced from its previous
location by the code in Listing 19.  This causes the upper left corner of
the custom button to maintain the same distance and direction from the mouse
pointer that it had when the mouse button was first pressed to begin the
dragging operation.

Listing 19. Redraw the custom button in a new
location.

            ((RootPanel)sender.getParent()).
                   setWidgetPosition(
                     sender,xAbs - xOffset,yAbs - yOffset);
          }//end if
        }//end onMouseMove

Thus, the purpose of the statement in Listing 19 is to relocate the custom
button to a new position determined by the absolute location of the mouse
pointer each time an onMouseMove event is fired.

How does this work?

The sender is the object that fired the onMouseMove event, which is the custom
button in this case.

When getParent is invoked on the reference to the custom button, a
reference to the container of the custom button is returned as type Widget
(In this case, the container of the custom button is the RootPanel
object.)

Moving the custom button to a new location

The custom button is relocated as described above by invoking the setWidgetPosition
method on the container, passing the custom button’s reference as a parameter to
the method along with a specification of the coordinates of the new position.

A downcast is required

In order to invoke the setWidgetPosition method on the reference of
type Widget returned by the getParent method, the reference must
be downcast at least as far as AbsolutePanel, which is the class in the
hierarchy where the setWidgetPosition method is defined.  However,
in Listing 19, the reference is cast all the way down to RootPanel,
(which is a subclass of AbsolutePanel)
, and is the type of the container of the custom button.

An interesting exercise.
As an interesting exercise, and also as a demonstration of the responsiveness
of AJAX, start the application so as to produce a screen as shown in
Figure 9.  Expand the browser to fill the entire screen.  Use the
mouse to highlight a few characters in the text immediately above the custom
button.

Then drag the custom button around in ovals as fast as you can to
see if you can cause the mouse pointer to get ahead of the custom button or
to lose the custom button. 

On my machine, which is relatively slow, I am unable to cause the mouse
pointer to get ahead of, or lose the custom button running under either IE6
or Firefox.

Also note that the highlighted text remains highlighted when you do this,
demonstrating that the page is not being repeatedly downloaded to cause the
custom button to appear in a different location on the page.

The coordinates of the new location for the custom
button

The new position for the upper-left corner of the custom button is computed
by subtracting the offset coordinates of the mouse pointer (relative to the
upper-left corner of the custom button)
from the absolute coordinates of the
mouse pointer relative to the upper-left corner of the RootPanel
The RootPanel completely fills the browser window.  Therefore, these
new coordinates specify the new position relative to the upper left corner of
the browser window as well.

End of the onMouseMove method

Listing 19 also signals the end of the onMouseMove event handler
method.


The onMouseUp method

The onMouseUp method is shown in its entirety in Listing 20.

Listing 20. The onMouseUp method.

        public void onMouseUp(Widget sender,int x,int y){
          DOM.releaseCapture(sender.getElement());
          dragging = false;
        }//end onMouseUp
        //-----------------------------------------------//

      }//end constructor
    );//end addMouseListener

When the user releases the mouse button, the custom button has been relocated
to the new location by the code in Listing 19.

For the reasons described earlier, the code in Listing 20 invokes the
releaseCapture
method on the custom button.

Listing 20 also sets the dragging flag to false to indicate
that the drag operation is terminated.

End of anonymous class definition

Listing 20 also signals the end of the definition of the anonymous class that
began in Listing 15.


Add two labels as drag obstacles

Listing 21 adds two Label objects to the GUI to illustrate what
happens when a component that is being dragged physically encounters another
component in the same space.

Listing 21. Add two labels as drag obstacles.

    //Add a label.
    RootPanel.get().add(new Label("Top Obstacle"),75,200);
    
    //Add the custom button to the browser window.
    RootPanel.get().add(customButton);
    
    //Add another label.
    RootPanel.get().add(new Label(
                                "Bottom Obstacle"),75,225);
    
  }//end onModuleLoad method
  //=====================================================//

}//end class GwtApp018
Who’s on top?
Whether a component that is being dragged passes over or under another component depends on the
order in which they are added to the RootPanel.  The component being dragged will
pass over those components added to the RootPanel before the component being
dragged was added, and will pass under those components added to the RootPanel
after the component being dragged was added.

Behavior when encountering obstacles

Listing 21 begins by adding the Label object that reads Top Obstacle
to the RootPanel, which places it in the browser window as shown in
Figure 9.  The custom button will pass over this Label when being dragged.

Then
Listing 21 adds the custom button to the RootPanel.

After adding the custom button, Listing 21 adds another Label object that reads Bottom
Obstacle
to the RootPanel.  The custom button will pass under this Label
when being dragged.

End of class definition for GwtApp018

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

Only half the story

In this lesson, I taught you how to write a simple application that you
can use to drag a component that fires mouse events across the browser window,
changing its position coordinates from point A to point B.  Note, however
that this is only half the story.  While moving components around on the
screen may look impressive, in order for drag-and-drop to be really useful,
there are many issues associated with the drop operation that were not addressed
here.

Copy, cut, and paste
Copy, cut, and paste is what appears to take place from a functional
viewpoint, but the drag-and-drop operation probably doesn’t actually make
another physical copy of the file.  Rather, the operation is probably
implemented by manipulating pointers on the disk instead.

Dragging and dropping a file

For example, if you drag a file from one directory to another directory with
the Windows operating system, you are doing much more than simply causing a
small icon to move from one location on the screen to another location on the
screen.  For this to be really useful, the target directory must be willing
to accept and assimilate the file behind the icon, and the source directory must
be willing to give it up.  In effect, such a drag and drop operation
appears to execute a copy, cut, and paste operation.  In other words, the
operation appears to copy the file from the original directory, cut the file
out of the original directory, and paste the copy into the new directory.

Future plans regarding drag-and-drop with the GWT
and Java

I plan to write a sequel to this lesson, which will teach you how to
expand the drag-and-drop behavior that you learned about in this lesson to
produce new behavior that is somewhat more substantive.

Run the program

I encourage you to copy the code from Listing 22 through Listing 27 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 perform
drag-and-drop operations in AJAX using the GWT.  Along the way, I taught you
about the use of the FocusListener and ClickListener interfaces.

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 issues 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. 

At this point, I’m not certain
what the order of the topics in above list will be, but I have decided that the
next lesson will concentrate on the use of the methods in the DOM class
for a variety of purposes.

Complete program listings


A complete listing of each of the applications discussed in this lesson is provided in
Listing 22 through Listing 27 below.

Listing 22. Java code for GwtApp016.

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

This application demonstrates FocusListener, ClickListener,
and tool tips.

Places two Button objects and a TextBox object in a 
HorizontalPanel object.

Defines inner classes that implement FocusListener and
ClickListener.

Registers FocusListener and ClickListener objects on each
of the two buttons and the text box.

Sets a title on each button and on the text box to cause
each of them to show tooltips.

Uses HorizontalPanel objects, Label objects, and a 
VerticalPanel object to create a simple table to show which
components fired events of the following types:

onFocus
onLostFocus
onClick

The tooltip titles are used to identify the components in
the table that fired each specific event. 

Note: The table does not display reliable focus lost and
focus gained information in those cases where the focus
leaves all three of the components.

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.ui.*;

public class GwtApp016 implements EntryPoint{
  //These three labels are used for text output. They are
  // declared as instance variables to make them accessible
  // by the methods in the inner classes.
  private Label label20;
  private Label label21;
  private Label label22;

  //This is the entry point method.
  public void onModuleLoad(){
    //Create the basic structure of the GUI.
    HorizontalPanel topPanel = new HorizontalPanel();
    topPanel.setSpacing(5);
    
    HorizontalPanel middlePanel = new HorizontalPanel();
    middlePanel.setSpacing(5);
    
    HorizontalPanel bottomPanel = new HorizontalPanel();
    bottomPanel.setSpacing(5);    
    
    VerticalPanel vertPanel = new VerticalPanel();
    vertPanel.add(topPanel);
    vertPanel.add(middlePanel);
    vertPanel.add(bottomPanel);
    
    //Populate the topPanel with two buttons and a TextBox
    Button button00 = new Button("Left");
    TextBox textBox = new TextBox();
    textBox.setText("TextBox");
    Button button02 = new Button("Right");
    //Make the buttons the same width.
    button00.setWidth("50px");
    button02.setWidth("50px");
    //Add the three components to the horizontal panel
    topPanel.add(button00);
    topPanel.add(textBox);
    topPanel.add(button02);
    
    //Populate the middle panel with three labels. These
    // labels serve simply to explain the contents of the
    // three labels below them.
    Label label10 = new Label("Lost Focus");
    Label label11 = new Label("Gained Focus");
    Label label12 = new Label("Was Clicked");
    label10.setWidth("85px");
    label11.setWidth("85px");
    label12.setWidth("85px");
    middlePanel.add(label10);
    middlePanel.add(label11);
    middlePanel.add(label12);
    
    //Populate the bottom panel with three output labels.
    // The contents of these three labels are modified by
    // the code in the event handlers to explain the
    // events.
    label20 = new Label("");
    label21 = new Label("");
    label22 = new Label("");
    label20.setWidth("85px");
    label21.setWidth("85px");
    label22.setWidth("85px");
    bottomPanel.add(label20);
    bottomPanel.add(label21);
    bottomPanel.add(label22);
    
    //Set tooltips on the two buttons and the text box.
    // The title not only serves as a tooltip, it also
    // serves as an identifier for the component that
    // gains the focus, loses the focus, or fires a click
    // event.
    button00.setTitle("Left Button");
    textBox.setTitle("TextBox");
    button02.setTitle("Right Button");
    
    //Register a common focus listener on each button and
    // on the text box.
    FocusLstnr focusLstnr = new FocusLstnr();
    button00.addFocusListener(focusLstnr);
    textBox.addFocusListener(focusLstnr);
    button02.addFocusListener(focusLstnr);
    
    //Register a common click listener on each button and
    // on the text box.
    ClickLstnr clickLstnr = new ClickLstnr();
    button00.addClickListener(clickLstnr);
    textBox.addClickListener(clickLstnr);
    button02.addClickListener(clickLstnr);
    
    //Add the vertical panel to the browser window. The
    // vertical panel serves as a backbone and the three
    // horizontal panels serve as ribs.
    RootPanel.get().add(vertPanel);
    
  }//end onModuleLoad method
  //=====================================================//
  
  //This is an inner class.  It was defined as an inner
  // class so that the methods would have direct access to
  // two of the three output Label objects.
  class FocusLstnr implements FocusListener{
    
    public void onLostFocus(Widget sender){
      label20.setText(sender.getTitle());
    }//end onLostFocus
    //---------------------------------------------------//
    
    public void onFocus(Widget sender){
      label21.setText(sender.getTitle());
    }//end onFocus
  }//end class FocusLstnr
  //=====================================================//
  
  //This is another inner class. It was defined as an inner
  // class so that the method would have direct access to
  // one of the three output Label objects.
  class ClickLstnr implements ClickListener{
    public void onClick(Widget sender){
      label22.setText(sender.getTitle());
    }//end onClick
  }//end class ClickLstnr
}//end class

Listing 23. HTML host page for GwtApp016.

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

</head>

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

<h3>GwtApp016</h3>

<p>Demonstrates FocusListener, ClickListener, and
Tool Tips.</p>


</body>
</html>

Listing 24. Java code for GwtApp017.

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

Demonstrates the creation of a custom button that can fire 
mouse events and otherwise behaves more or less like a 
standard button.

Wraps a standard Button object in a FocusPanel object to 
create the custom button.  An object of the FocusPanel 
behaves more or less like a standard button except that it
can also fire mouse events in addition to click events and
focus events.

Sets titles on the standard button and the custom button in
order to display tool tips when the mouse pointer hovers
on the custom button.  The tool tip that is displayed is
the title that is set on the standard button and not the
title that is set on the custom button.  

The titles are also used to identify the component that 
fires a click event when the mouse button is pressed in the
area occupied by the custom button or when the space bar is
pressed while the standard button wrapped in the FocusPanel
has the focus. When this happens, both the standard button 
and the custom button fire a click event.

Puts the custom button along with five Label objects in
a VerticalPanel object.  The labels are used to display
the following output data when the user manipulates the
custom button with the mouse or the keyboard:

1. Whether the mouse pointer is inside or outside the area
occupied by the custom button.

2. The mouse pointer location as the mouse is moved within
the area occupied by the custom button.

3. The location of the mouse pointer when a mouse button is
pressed within the area occupied by the custom button.

4 and 5. The title of the component firing a click event 
when the mouse button is pressed within the area occupied 
by the custom button or when the space bar is pressed while
the standard button that is wrapped in the FocusPanel has 
the focus. (Two separate labels are used to display this 
information.)

Registers an anonymous MouseListener object on the custom
button to provide the information displayed in the first 
three labels described above.

Registers an anonymous ClickListener object on the standard
button to provide the information displayed in the fourth
label described above.  This demonstrates that the standard
button fires click events despite the fact that it is
wrapped in a FocusPanel object.

Registers an anonymous ClickListener object on the custom
button to provide the information for the fifth label. This
demonstrates that the custom button also fires click events
when the mouse button is pressed while the mouse pointer is
inside the area occupied by the custom button.  It also
demonstrates that the custom button fires a click event if
the user presses the space bar while the standard button
that is wrapped in the FocusPanel has the focus.

When a standard button has the focus and the user presses 
the space bar, the standard button fires a click event. 
When the standard button that is wrapped in the FocusPanel
representing the custom button has the focus and the user 
presses the space bar, the standard button and the custom 
button both fire a click event. Thus, a click listener that
is registered on the custom button will see the event. One
way to cause the standard button that is wrapped in the 
FocusPanel to gain the focus is to click it with the mouse.
Another way is to press the tab key several times in 
succession. When you do that, you will see the standard 
button that is wrapped in the FocusPanel gain the focus.

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.ui.*;

public class GwtApp017 implements EntryPoint{

  //This is the entry point method.
  public void onModuleLoad(){
    //Create a VerticalPanel to contain a custom button
    // along with several labels that are used to display
    // output data.
    VerticalPanel vertPanel = new VerticalPanel();
    
    //Create labels used to display output data. Must be
    // final to make them accessible by an object of an
    // anonymous inner class.
    final Label inOrOut = new Label("In or Out: Out");
    final Label lastMoveLocation = 
             new Label("Last Move Location: x = 0, y = 0");
    final Label lastDownLocation = 
             new Label("Last Down Location: x = 0, y = 0");
    final Label clickSenderA = 
                          new Label("Click SenderA: None");
    final Label clickSenderB = 
                          new Label("Click SenderB: None");
    
    //Create a custom button that will respond to mouse 
    // events by wrapping a standard button in a 
    // FocusPanel. Force the FocusPanel to be the same size
    // as the standard button.
    Button button = new Button("Custom Button");
    button.setSize("100px","50px");
    FocusPanel customButton = new FocusPanel(button);
    customButton.setSize("100px","50px");
    
    //Cause the focus to skip the FocusPanel and go
    // straight to the button that is wrapped in the
    // FocusPanel.
    customButton.setTabIndex(-1);
    
    //Set titles that are used for tootips and are also
    // used to identify the source of click events.
    button.setTitle("Button");
    customButton.setTitle("Custom Button");

    //Add the components to the vertical panel.
    vertPanel.add(customButton);
    vertPanel.add(inOrOut);
    vertPanel.add(lastMoveLocation);
    vertPanel.add(lastDownLocation);
    vertPanel.add(clickSenderA);
    vertPanel.add(clickSenderB);
        
    //Add the vertical panel to the browser window.
    RootPanel.get().add(vertPanel);
    
    //Register a MouseListener on the custom button.
    customButton.addMouseListener(
      new MouseListenerAdapter(){
        public void onMouseEnter(Widget sender){
          inOrOut.setText("In or Out: In");
        }//end onMouseEnter
        //-----------------------------------------------//
        
        public void onMouseLeave(Widget sender){
          inOrOut.setText("In or Out: Out");
          
          //Clear the clickSender labels when the mouse
          // pointer moves out of the area occupied by the
          // custom button to prepare for displaying the
          // results of the next click event.
          clickSenderA.setText("Click SenderA: None");
          clickSenderB.setText("Click SenderB: None");
        }//end onMouseLeave
        //-----------------------------------------------//
        
        public void onMouseMove(Widget sender,int x,int y){
          lastMoveLocation.setText(
            "Last Move Location: x = " + x + ", y = " + y);
        }//end onMouseMove
        //-----------------------------------------------//
        
        public void onMouseDown(Widget sender,int x,int y){
          lastDownLocation.setText(
            "Last Down Location: x = " + x + ", y = " + y);
        }//end onMouseMove
        //-----------------------------------------------//
      }//end constructor
    );//end addMouseListener
    //===================================================//
    
    //Register a ClickListener on the standard button. This
    // listener demonstrates that you can still receive
    // click events from the standard button despite the
    // fact that it is wrapped in a FocusPanel object.
    button.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          clickSenderA.setText(
                    "Click SenderA: " + sender.getTitle());
        }//end onClick
      }//end constructor
    );//end addClickListener
    //===================================================//
    
    //Register a ClickListener on the custom button. This
    // listener demonstrates that you can also receive
    // click events from the custom button.
    customButton.addClickListener(
      new ClickListener(){
        public void onClick(Widget sender){
          clickSenderB.setText(
                    "Click SenderB: " + sender.getTitle());
        }//end onClick
      }//end constructor
    );//end addClickListener
    //===================================================//
    
  }//end onModuleLoad method
  //=====================================================//

}//end class GwtApp017

Listing 25. HTML host page for GwtApp017.

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

</head>

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

<h3>GwtApp017</h3>

<p>Demonstrates a custom button that fires 
mouse events.</p>


</body>
</html>

Listing 26. Java code for GwtApp018.

/*File GwtApp018.java
This application was based substantially (with written 
permission via email) on a program that was published by 
Eric Sessoms at:

http://code.nubgames.com/index.cgi/gwt/drag-and-drop-with-
the-google-web-toolkit.html

Therefore, his copyright statement follows:

 * Copyright (c)2006 Nub Games, Inc.
 * 
 * Permission is hereby granted, free of charge, to any
 * person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the
 * Software without restriction, including without
 * limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the
 * following conditions:
 * 
 * The above copyright notice and this permission notice
 * shall be included in all copies or substantial portions
 * of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
 * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.

This application demonstrates the use of mouse events to
perform a drag-and-drop operation on a custom button 
component.

The application creates a custom button that can fire 
mouse events and otherwise behave more or less like a 
standard button.  A standard Button object is wrapped in
a FocusPanel object to create the custom button. An object 
of the FocusPanel then behaves more or less like a standard
button except that it can also fire mouse events in 
addition to click events and focus events.

Note, the operation is not smooth when the application is
run in hosted mode.  However, it runs smoothly in 
Firefox 1.5.0.8 and Internet Explorer 6.0.29x

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 GwtApp018 implements EntryPoint{

  //This is the entry point method.
  public void onModuleLoad(){
    
    //Create a custom button that will fire mouse events
    // by wrapping a standard button in a FocusPanel.
    // Force the FocusPanel to be the same size as the
    // standard button.
    Button button = new Button("Custom Button");
    button.setSize("120px","50px");
    FocusPanel customButton = new FocusPanel(button);
    customButton.setSize("120px","50px");

    //Cause the focus to skip the FocusPanel and go
    // straight to the button that is wrapped in the
    // FocusPanel.
    customButton.setTabIndex(-1);

    //Register an anonymous MouseListener object
    // instantiated from an anonymous class on the custom
    // button. The methods of this class will be used to
    // perform a drag-and-drop operation on the custom
    // button.
    customButton.addMouseListener(
      new MouseListenerAdapter(){
        
        //Declare some local working varibles.
        private boolean dragging;
        private int     xOffset;
        private int     yOffset;
          
        public void onMouseDown(Widget sender,int x,int y){
          //The custom button is captured for dragging when
          // any of the three mouse buttons is pressed
          // while the mouse pointer is inside the area
          // occupied by the custom button.  Note, however,
          // that pressing any mouse button other than the
          // left button may cause browser-specific
          // behavior associated with the button to also
          // occur.
          //The following statement sets mouse-capture on
          // the specified element. The specified element
          // will directly receive all mouse events until
          // releaseCapture(Element) is called on it later
          // in the onMouseUp method.
          //The Element object returned by the getElement
          // method provides an opaque handle to a native
          // DOM Element when the Java code is compiled 
          // into JavaScript later.
          //The capture is set so that the custom button
          // will not lose the mouse if it is dragged
          // under another component. If you disable this
          // statement, the custom button will sometimes
          // get stuck when you drag it under one of the
          // labels that are provided as obstacles in this
          // application.
          DOM.setCapture(sender.getElement());
          
          //Record the location of the mouse pointer 
          // relative to the upper-left corner of the
          // custom button when the mouse button is
          // pressed.
          xOffset = x;
          yOffset = y;
          
          //Set the dragging flag to indicate that a drag
          // operation is underway. This flag will be
          // tested later by the onMouseMove method.
          dragging  = true;
        }//end onMouseDown
        //-----------------------------------------------//
        
        public void onMouseMove(Widget sender,int x,int y){
          //Perform the following operations only if a drag
          // operation is in progress.
          if (dragging){
            //Compute the location of the mouse pointer
            // relative to the upper-left corner of the
            // browser window by adding the x and y
            // coordinate offset values to the absolute
            // coordinate values of the custom button.
            int xAbs = x + sender.getAbsoluteLeft();
            int yAbs = y + sender.getAbsoluteTop();
            
            //The purpose of the next statement is to
            // relocate the custom button to a new position
            // determined by the absolute location of the
            // mouse pointer when this event was fired.
            //The sender is the custom button. When
            // getParent is invoked on it, a reference to
            // the container of the custom button is
            // returned as type Widget. In order to invoke
            // the setWidgetPosition method on that
            // reference, it must be downcast at least as
            // far as AbsolutePanel, which is where the
            // setWidgetPosition method is defined. In
            // this case, the reference is cast all the way
            // down to RootPanel, which is a subclass of
            // AbsolutePanel, and is the actual container
            // of the custom button.
            //The new location for the upper-left corner of
            // the custom button is computed by subtracting
            // the offset coordinates of the mouse pointer
            // relative to the upper-left corner of the
            // custom button from the absolute coordinates
            // of the mouse pointer relative to the
            // upper-left corner of the RootPanel, which
            // completely fills the browser window.  
            ((RootPanel)sender.getParent()).
                   setWidgetPosition(
                     sender,xAbs - xOffset,yAbs - yOffset);
          }//end if
        }//end onMouseMove
        //-----------------------------------------------//
        
        public void onMouseUp(Widget sender,int x,int y){
          //The custom button has been relocated to the new
          // location when the user releases the mouse
          // button.
          //Release the mouse capture condition that was
          // established earlier in the onMouseDown method
          // and set the dragging flag to false to indicate
          // that the drag operation is terminated.
          DOM.releaseCapture(sender.getElement());
          dragging = false;
        }//end onMouseUp
        //-----------------------------------------------//

      }//end constructor
    );//end addMouseListener
    //===================================================//
    
    //Add a Label to the browser window to serve as an
    // obstacle. The custom button will pass over this
    // Label when being dragged. Whether one component
    // passes over or under another component depends on
    // the order in which they are added to the RootPanel.
    // The component being dragged will pass over those
    // components added to the RootPanel before the
    // component being dragged was added, and will pass
    // under those components added to the RootPanel after
    // the component being dragged was added.
    RootPanel.get().add(new Label("Top Obstacle"),75,200);
    
    //Add the custom button to the browser window.
    RootPanel.get().add(customButton);
    
    //Add another Label to the browser window to serve as
    // another obstacle. The custom button will pass under
    // this Label when being dragged.
    RootPanel.get().add(new Label(
                                "Bottom Obstacle"),75,225);
    
  }//end onModuleLoad method
  //=====================================================//

}//end class GwtApp018

Listing 27. HTML host page for GwtApp018.

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

</head>

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

<h3>GwtApp018</h3>

<p>Demonstrates drag-and-drop of a custom button 
component.</p>


</body>
</html>

Copyright

Copyright 2007, Richard G. Baldwin.  Except for the code in the
application named GwtApp018, reproduction in whole or in part in any
form or medium without express written permission from Richard Baldwin is
prohibited.  Reproduction rights for the code in the application named
GwtApp018 are governed by the copyright statement that appears at the beginning
of Listing 26.

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.

[email protected]

Latest Posts

Related Stories