Java Gui Builder
You are here: Home   >   Documentation   >   Tutorials   >   Basic Web Browser Example

Basic Web Browser Example

The complete example's file is available as webbrowser.xml.

Task Presentation

You have been tasked to create a basic web browser. This new application should have the usual controls: URL field, a Go button, a browser display area, and a menu.

With the previous example, as a guide, you could implement the whole window without effort. Where you would have problems is in the event handling department. Your application needs to respond to user-generated events: the enter key in the URL field, a click on the Go button, active links, item selections in the menus.

JGB Event Handling Implementation

The JGB framework implements event handling by having one or more objects be notified when interesting events occur. This is achieved through the Mediator Pattern.

The Mediator Pattern

The mediator pattern (PDF link) is a way for a set of objects to collaborate without all of them being aware of every other object.

The mediator pattern achieves this decoupling by having each objects in the set speak with only one other object, the mediator. The mediator is then responsible for managing the interactions between all other objects.

In the JGB framework, the mediator pattern is used to manage the interactions between the different controls in a window. The user is responsible for providing an implementation of this pattern.

Basic window controls

You decide to start easy by creating the framework upon which event handling will be attached later on. You start with the following:

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE window PUBLIC
    "-//SOURCEFORGE/Java Gui Builder DTD version 1.0//EN"
    "http://jgb.sourceforge.net/dtd/jgb.dtd">
<window id="webbrowser" type="jframe">
    <object id="view" class="javax.swing.JEditorPane">
        <constructor/>
        <property name="editable"><value type="boolean" data="false"/></property>
        <property name="page">
            <value type="string" data="http://jgb.sourceforge.net/"/>
        </property>
    </object>

    <controls>
        <layout class="BorderLayout"/>

        <constraints>
            <constant name="java.awt.BorderLayout.NORTH"/>
        </constraints>
        <panel layout="GridBagLayout">
            <label id="urllabel" text="URL:"/>
            <textfield id="url" reflabel="urllabel"/>
            <button id="go" mnemonic="g" text="Go !"/>
        </panel>

        <panel layout="GridBagLayout">
            <control class="javax.swing.JScrollPane">
                <property name="viewportView"><ref refid="view"/></property>
            </control>
        </panel>
    </controls>
</window>

If you execute this window sample, you will not get the same look as the final window. This example cuts to the heart of the matter by ignoring most layout management issues. You should consult the actual example source file to see the code in all of it's glory.

Run the XML sample by using the runexample batch file or shell script.

Adding the menu

Next, you decide it is time to add the menu. This too does not require event handling right now. So, you add the following:

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE window PUBLIC
    "-//SOURCEFORGE/Java Gui Builder DTD version 1.0//EN"
    "http://jgb.sourceforge.net/dtd/jgb.dtd">
<window id="webbrowser" type="jframe">
    <menuBar id="menu">
        <menu id="menu.file" text="File" mnemonic="f">
            <item id="menu.file.quit" text="Quit" accelerator="Ctrl+Q"
                    mnemonic="q"/>
        </menu>
    </menuBar>

    ...
</window>

Handling File\Quit

You decide to go easy on yourself yet again by handling the Quit item from the File menu first. So, you check the Event-Handling section of the JGB Elements Documentation Index.

You notice a register element which fits the bill. After reading the description of the element, you understand what you have to do now.

The first step is to modify the XML GUI description file to add the required elements:

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE window PUBLIC
    "-//SOURCEFORGE/Java Gui Builder DTD version 1.0//EN"
    "http://jgb.sourceforge.net/dtd/jgb.dtd">
<window id="webbrowser" type="jframe">
    <object id="eventManager" class="jgb.examples.WebBrowserEventManager">
        <constructor/>
    </object>

    ...
        <item id="menu.file.quit" text="Quit" accelerator="Ctrl+Q"
                mnemonic="q">
            <register class="java.awt.event.ActionListener"
                event="actionPerformed" manager="eventManager"
                method="quit"/>
        </item>
    ...
</window>

According to the documentation, event-handling will behave like this:

  1. The user selects the Quit item of the File menu;
  2. Swing generates an ActionEvent and calls registered ActionListeners;
  3. JGB receives the notification, turns around and calls the quit method of the eventManager object (an instance of jgb.examples.WebBrowserEventManager).

Now, we have to provide an implementation of WebBrowserEventManager.

package jgb.examples;

import jgb.builder.WindowContext;
import java.util.EventObject;

public class WebBrowserEventManager {
    public void quit(EventObject event, WindowContext context) {
        System.exit(1);
    }
}

Well, that was easy. So, you compile and run your application. Success ! The Quit option really closes down the application.

Handling Go

Let's continue by implementing the Go button. This button should take whatever is in the URL field and point the JEditorPane to this URL. You start by writing the necessary logic in the XML GUI description file:

    ...
    <button id="go" mnemonic="g" text="Go !">
        <register class="java.awt.event.ActionListener"
            event="actionPerformed" manager="eventManager" method="go"/>
    </button>
    ...

This time, whenever the JGB framework receives an actionPerformed event on the Go button, it will turn around and call the go method of the eventManager object. You provide the following go method implementation:

public void go(EventObject event, WindowContext context) {
    final JEditorPane view = (JEditorPane)context.getObject("view");
    final JTextField urlField = (JTextField)context.getObject("url");

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            try {
                view.setPage(urlField.getText());
            } catch (final IOException e) {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        JOptionPane.showMessageDialog(
                                view, e, "Error retrieving URL",
                                JOptionPane.ERROR_MESSAGE);
                    }
                });
            }
        }
    });
}

This time around, your code required access to the context. You had to get some objects from the context so that you could update their properties. In this instance, you retrieved the URL field and the browser view so that you could read the URL stored in the URL field and set the page property of the browser view. The rest is just exception handling.

Running the application again yields something very nice. Your application can quit and can respond to URL change requests.

Handling Hyperlinks

JEditorPane can notify registered listeners when users click on hyperlinks. We will use this capability to allow the user to click on links and open them up in the same window. As usual, you decide to start with the GUI XML description file:

    <object id="view" class="javax.swing.JEditorPane">
        ...
        <register class="javax.swing.event.HyperlinkListener" event="hyperlinkUpdate"
            manager="eventManager" method="hyperlinkUpdate"/>
    </object>
    ...

And the corresponding Java code:

public void hyperlinkUpdate(EventObject event, WindowContext context) {
    final JEditorPane view = (JEditorPane)context.getObject("view");
    final JTextField urlField = (JTextField)context.getObject("url");

    HyperlinkEvent hEvent = (HyperlinkEvent)event;
    if (hEvent.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
        URL newUrl = hEvent.getURL();
        urlField.setText(newUrl.toExternalForm());
        go(event, context);
    }
}

In this bit of code, you do two things: you set the URL field to the new URL, and you click on go. Since the go method did not depend on it's EventObject being a particular type, you can safely call this method and not bother with it.

After writing this and testing, you are confident that everything works fine. You decide to do a bit of refactoring, since you have the two same lines of code in two different methods.

The actual refactoring is left as an exercise to the reader...

Final Window

After adding appropriate layout directives, the window should look like this:

The All Java web browser on the Java GUI Builder's SourceForge.net's project summary.

Conclusion

This example was quite simple. Only a few methods were able to handle all of the required functionnality. In a larger example, it would probably be interesting to use the mediator pattern at a second level of abstraction: One mediator per window, and the different windows speaking to each other through another mediator.

I encourage you to take a look at the XML GUI description file and the actual WebBrowserEventManager implementation

Back to top
SourceForge Logo
Hosted on SourceForge.net
Valid XHTML 1.0!
Valid XHTML 1.0 !
Valid CSS!
Valid CSS !
Code Coverage by Clover
Code Coverage provided by Clover
 |  Home |  License |  Downloads |  Documentation |  Developers |  Mailing Lists |  Dependencies |  Links |  Privacy Policy |  SF Project Home |