TOC PREV NEXT INDEX




Step 3 - Navigation


This step makes the browser more useful by adding navigational aids for the user.

Adding Navigation Elements to the GUI

Add a location bar and navigation buttons to the BrowserFrame with the following code:

private Button backButton, forwardButton, reloadButton, stopButton;

private Panel panel;

private StormBase base;

private String viewportId;

private Label status;

private TextField locationTextField;
 

The following code is the final part of the constructor:

statusPanel.add(statusLabel);
 
backButton = createButton("<<", font);

backButton.setEnabled(false);

forwardButton = createButton(">>", font);

forwardButton.setEnabled(false);

stopButton = createButton("stop", font);

reloadButton = createButton("reload", font);
 
Panel navigationPanel = new Panel();

gridBagLayout = new GridBagLayout();

gridBagConstraints = new GridBagConstraints();

gridBagConstraints.fill = GridBagConstraints.NONE;

navigationPanel.setLayout(gridBagLayout);

gridBagLayout.setConstraints(backButton, gridBagConstraints);

navigationPanel.add(backButton);

gridBagLayout.setConstraints(forwardButton, gridBagConstraints);

navigationPanel.add(forwardButton);

gridBagLayout.setConstraints(stopButton, gridBagConstraints);

navigationPanel.add(stopButton);

gridBagLayout.setConstraints(reloadButton, gridBagConstraints);

navigationPanel.add(reloadButton);
 
locationTextField = new TextField(30);

locationTextField.setFont(font);

locationTextField.setBackground(Color.white);

locationTextField.setForeground(Color.blue);

locationTextField.addActionListener(this);
 
gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;

gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;

gridBagConstraints.weightx = 1.0;

gridBagLayout.setConstraints(locationTextField, gridBagConstraints);

navigationPanel.add(locationTextField);
 
controlPanel.add(navigationPanel, BorderLayout.NORTH);

controlPanel.add(statusPanel, BorderLayout.SOUTH);
 

The createButton( ) method is defined with this code:

private Button createButton(String label, Font font) {

    Button button = new Button(label);

    button.setFont(font);

    button.setBackground(Color.lightGray);

    button.addActionListener(this);

    

    return button;

}
 
Adding Navigation Functionality

Since the application has already registered with all the new widgets as java.awt.events.ActionListener, that interface needs to be implemented.

These lines ensure that the classes are imported:

import java.awt.event.*;
 

The class definition is changed as follows:

class BrowserFrame extends Frame

implements ActionListener, PropertyChangeListener {
 

The interface defines one method, actionPerformed, which is called whenever one of the new widgets is activated:

public void actionPerformed(ActionEvent event) {

    Object source = event.getSource();
 
    if (source == backButton) {

        stormBase.getHistoryManager().goBack(viewportId);

    } else if (source == forwardButton) {

        stormBase.getHistoryManager().goForward(viewportId);

    } else if (source == stopButton) {

        stormBase.stopLoading(viewportId);

    } else if (source == reloadButton) {

            stormBase.getHistoryManager().reload(viewportId);

        } else if (source == locationTextField) {

            String location = locationTextField.getText();



            if (location.startsWith("www.")) {

                location = "http://" + location;

            }



            stormBase.renderContent(location, null, viewportId);

    }

}
 

To handle navigation and histories of all the Viewports, the ice.storm.HistoryManager is used. It defines a public API that can be called from other classes as well as from StormBase. The code does the following:

In addition, a few more property change events are taken into account. The new method is as follows:

public void propertyChange(PropertyChangeEvent event) {

    Viewport viewport = (Viewport)event.getSource();

    String propertyName = event.getPropertyName();

    String newValue;
 
    if (event.getNewValue() instanceof String) {

        newValue = (String)event.getNewValue();

    } else {

        newValue = "";

    }
 
    if (propertyName.equals(PropertyConstants.STATUS_LINE)) {

        statusLabel.setText(newValue);

    } else if (propertyName.equals(PropertyConstants.OUTSTANDING_IMAGES)) {

        if (!newValue.equals("0")) {

            statusLabel.setText("loading images: " + newValue + " left");

        } else {

            statusLabel.setText("loading images: done");

        }

    } else if (propertyName.equals(PropertyConstants.CONTENT_LOADING)) {

        if (newValue.equals(PropertyConstants.ERROR)) {

            ContentLoader contentLoader = (ContentLoader)event.getOldValue();

            if (contentLoader != null) {

                statusLabel.setText(

                    viewport.getName() + ": " +

                    contentLoader.getException());

            } else {

                statusLabel.setText(viewport.getName() + ": loading error");

            }

        } else if (newValue.equals(PropertyConstants.BEGIN)) {

            backButton.setEnabled(

                stormBase.getHistoryManager().canGoBack(viewportId));

            forwardButton.setEnabled(

                stormBase.getHistoryManager().canGoForward(viewportId));

        }

    } else if ((propertyName.equals(PropertyConstants.LOCATION)) &&

        (viewport.getId().equals(viewportId))) {



        locationTextField.setText(newValue);

    } else if ((propertyName.equals(PropertyConstants.TITLE)) &&

        (viewport.getId().equals(viewportId))) {



        setTitle(" " + newValue);

    }

}
 

The check viewport.getId( ).equals(viewportID) is introduced to see if the Viewport is actually firing the events, and not one of its children. If it is, the title of the window is set upon receiving the title event. The text in the location field is set to the value of the location event. Last, the navigation buttons are enabled or disabled when the contentLoading,begin event is fired. When this happens, the HistoryManager has updated the history of the source of the event, and that is a good time to call the canGoBack/Forward( ) methods.

Now the browser has a more useful GUI and underlying functionality.



Copyright 2005. ICEsoft Technologies, Inc.
http://www.icesoft.com

TOC PREV NEXT INDEX