FileDocCategorySizeDatePackage
Browser4.javaAPI DocExample5640Mon Oct 16 19:44:08 BST 2000None

Browser4.java

// File: Browser4.java
// Tim Balls : Sept 1999

// Extends the scrolling Browser in Browser3.java
// to include a more complex model - one that
// can track a history of URLs
// Uses java.util.ArrayList to store the data

import javax.swing.*;
import javax.swing.event.*;
import java.net.*;
import java.io.IOException;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class Browser4 extends JFrame implements HyperlinkListener,
																ActionListener
{	public static void main( String[] args )
	{	if( args.length == 0 )
		{	new Browser4( "NoURL" );
		}
		else
		{	new Browser4( args[0] );
		}
	}

	private JEditorPane html = new JEditorPane();
	private JTextField location;
	private JLabel statusLine = new JLabel( "", JLabel.LEFT );
   private JButton back = new JButton( "<<" );
  	private JButton forward = new JButton( ">>" );
	private HistoryList historyList = new HistoryList();

	public Browser4( String site )
	{	setSize( 550, 450 );
		setTitle( "Simple Web Browser #4" );
		addWindowListener( new WindowAdapter() {
			public void windowClosing( WindowEvent e )
			{	System.exit( 0 );
			}
		});

		// Build more interesting interface
		location = new JTextField( site, 25 );  // 25 cols
		JPanel topLine = new JPanel();
		topLine.setLayout( new FlowLayout( FlowLayout.LEFT ) );
      topLine.add( back );
      topLine.add( forward );
		topLine.add( new JLabel( "URL:" ) );
		topLine.add( location );
		location.addActionListener( this );
      back.addActionListener( this );
      forward.addActionListener( this );
		
		// for the JFrame:
		this.getContentPane().setLayout( new BorderLayout() );
		this.getContentPane().add( topLine, BorderLayout.NORTH );
		this.getContentPane().add( statusLine, BorderLayout.SOUTH );

		if( !site.equals( "NoURL" ) )
		{	loadURL( site );
		}
		
		JScrollPane scroller = new JScrollPane();
		JViewport viewport = scroller.getViewport();
		viewport.add( html );
		
		this.getContentPane().add( scroller, BorderLayout.CENTER );
		html.setEditable( false ); // to allow links to be activated
		html.addHyperlinkListener( this );
		
		setVisible( true );		
	}

	// When a hyperlink is "clicked" :-
	public void hyperlinkUpdate( HyperlinkEvent e )
	{	if( e.getEventType() == HyperlinkEvent.EventType.ACTIVATED )
		{	loadURL( e.getURL().toString() );
			location.setText( "" + e.getURL() );
		}
		if( e.getEventType() == HyperlinkEvent.EventType.ENTERED )
		{	statusLine.setText( "" + e.getURL() );
		}
		if( e.getEventType() == HyperlinkEvent.EventType.EXITED )
		{	statusLine.setText( "" );
		}
	}
	
	// When a new URL is entered (and return pressed)
	public void actionPerformed( ActionEvent e )
	{	// need to check which object called us
      if( e.getSource() == location )
      {  String site = location.getText();
		   loadURL( site );
      }
      if( e.getSource() == back )
      {	historyList.back();
      	try
			{
				html.setPage( historyList.getCurrent() );
			}
			catch( IOException ioe )
			{	System.out.println( "Can't load url: " + historyList.getCurrent() );
				System.exit( 0 );
			}
			location.setText( historyList.getCurrent().toString() );
     	}
      if( e.getSource() == forward )
      {	historyList.forward();
      	try
			{	html.setPage( historyList.getCurrent() ); 
			}
			catch( IOException ioe )
			{	System.out.println( "Can't load url: " + historyList.getCurrent() );
				System.exit( 0 );
			}
			location.setText( historyList.getCurrent().toString() );
      }
	}

	// Attempt to load the html JEditorPane from the URL at "site"
	private void loadURL( String site )
	{	URL url = null;
	   try
		{	url = new URL( site );
		}
		catch( MalformedURLException e )
		{	System.out.println( "Invalid URL specified" );
			System.exit( 0 );
		}
		try
		{	html.setPage( url ); // load page
		}
		catch( IOException e )
		{	System.out.println( "Can't load url: " + url );
			System.exit( 0 );
		}
		// must be OK so add to history
		historyList.add( url );
	}

	/* Encapsulate the behaviour of a history list for URLs
	   Enable/Disable the arrow controls so that
	      illegal operations are impossible
	   This class is (too) strongly coupled to its outer class
	
	   Maintain position in list, ensure that adding a new item
	      deletes any that would have followed (becomes new tail)
	*/
	private class HistoryList
	{	private ArrayList history = new ArrayList();
		private int current = 0;

		public HistoryList()
		{	back.setEnabled( false );
			forward.setEnabled( false );
		}

		public void add( URL url )
		{	if( history.size() > (current+1) )
			{	history.subList( current+1, history.size() ).clear();
			}
			history.add( url );
			current = history.size()-1;
			if( current != 0 )
			{	back.setEnabled( true );
			}
			forward.setEnabled( false );
		}

		/* Decrement the current pointer
		   PreCondition: must not be at start of list
		*/
		public void back()
		{	current--;
			if( current == 0 )
			{	back.setEnabled( false );
			}
			if( current < (history.size()-1) )
			{	forward.setEnabled( true );
			}
		}

		/* Increment the current pointer
		   PreCondition: must not be at end of list
		*/
		public void forward()
		{	current++;
			if( current > 0 )
			{	back.setEnabled( true );
			}
			if( current == (history.size()-1) )
			{	forward.setEnabled( false );
			}
		}

		/* Return the URL access by the current pointer
		*/
		public URL getCurrent()
		{	return (URL)(history.get( current ));
		}
	}

}