/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.util.gui;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.net.*;
import javax.swing.text.*;
/**
HTMLBrowser is a simple web browser which lets the user click on links and which provides
a Back button when appropriate. That's it!
*/
public class HTMLBrowser extends JPanel
{
java.util.Stack stack = new java.util.Stack();
JEditorPane infoPane;
JScrollPane scroll;
public void setText(Object HTMLTextOrURL)
{
if (HTMLTextOrURL == null) HTMLTextOrURL = "<html><body bgcolor='white'></body></html>";
stack = new java.util.Stack();
// delete any notion of a URL. What a pain -- this is so backwards!
// This is because JEditorPane's setText doesn't eliminate the
// stream description property of the text (a bug), so the system
// still thinks the URL is valid.
infoPane.setContentType("text/html");
Document d = infoPane.getEditorKit().createDefaultDocument();
//if (d instanceof AbstractDocument)
// {
// ((AbstractDocument)d).setAsynchronousLoadPriority(1);
// }
infoPane.setDocument(d);
if (HTMLTextOrURL instanceof String)
infoPane.setText((String)HTMLTextOrURL);
else if (HTMLTextOrURL instanceof URL)
try
{
infoPane.setPage((URL)HTMLTextOrURL);
}
catch (IOException e)
{
e.printStackTrace();
infoPane = new JEditorPane();
}
else
{
new RuntimeException("Info object was neither a string nor a URL").printStackTrace();
infoPane = new JEditorPane();
}
// override a bug in JEditorPane which scrolls to the bottom on all subsequent Consoles
infoPane.getCaret().setDot(0);
}
/** Constructs an HTMLBrowser using either an HTML string or a URL */
public HTMLBrowser(final Object HTMLTextOrURL)
{
infoPane = new JEditorPane();
setText(HTMLTextOrURL);
infoPane.setEditable(false);
scroll = new JScrollPane(infoPane);
setLayout(new BorderLayout());
add(scroll,BorderLayout.CENTER);
// override a bug in JEditorPane which scrolls to the bottom on all subsequent Consoles
infoPane.getCaret().setDot(0);
// add a back button and
JButton backButton = new JButton("Back");
final Box backButtonBox = new Box(BoxLayout.X_AXIS);
backButtonBox.add(backButton);
backButtonBox.add(Box.createGlue());
// make the hyperlinks active
infoPane.addHyperlinkListener(new HyperlinkListener()
{
public void hyperlinkUpdate( HyperlinkEvent he )
{
HyperlinkEvent.EventType type = he.getEventType();
if (type == HyperlinkEvent.EventType.ENTERED)
{
infoPane.setCursor(Cursor.getPredefinedCursor( Cursor.HAND_CURSOR) );
}
else if (type == HyperlinkEvent.EventType.EXITED)
{
infoPane.setCursor( Cursor.getDefaultCursor() );
}
else // clicked on it!
{
java.net.URL url = he.getURL();
try
{
infoPane.getEditorKit().createDefaultDocument();
infoPane.setPage(url);
if (stack.isEmpty())
{
// show back button
add(backButtonBox,BorderLayout.SOUTH);
revalidate();
}
stack.push(url);
}
catch (Exception e)
{
e.printStackTrace();
java.awt.Toolkit.getDefaultToolkit().beep();
}
}
}
});
// code for when the user presses the "Back" button
backButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
try
{
stack.pop();
if (stack.isEmpty())
{
// hide back button
remove(backButtonBox);
revalidate();
setText(HTMLTextOrURL);
}
else infoPane.setPage((java.net.URL)(stack.peek()));
}
catch (Exception e)
{
System.err.println("WARNING: This should never happen." + e);
}
}
});
}
}