diff --git a/swing/src/net/sf/openrocket/gui/components/DescriptionArea.java b/swing/src/net/sf/openrocket/gui/components/DescriptionArea.java index 2c68b129c..324c186f2 100644 --- a/swing/src/net/sf/openrocket/gui/components/DescriptionArea.java +++ b/swing/src/net/sf/openrocket/gui/components/DescriptionArea.java @@ -1,16 +1,30 @@ package net.sf.openrocket.gui.components; import java.awt.Color; +import java.awt.Desktop; import java.awt.Dimension; import java.awt.Font; import java.awt.Rectangle; +import java.net.URI; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; import javax.swing.JEditorPane; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; +import net.sf.openrocket.util.BugException; + @SuppressWarnings("serial") public class DescriptionArea extends JScrollPane { @@ -65,7 +79,71 @@ public class DescriptionArea extends JScrollPane { Font font = editorPane.getFont(); editorPane.setFont(font.deriveFont(font.getSize2D() + size)); editorPane.setEditable(false); - + editorPane.addHyperlinkListener(new HyperlinkListener() { + public void hyperlinkUpdate(HyperlinkEvent e) { + if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + URI uri = null; + try { + uri = e.getURL().toURI(); + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + + // If the uri scheme indicates this is a resource in a jar file, + // extract and write to a temporary file + if (uri.getScheme().equals("jar")) { + + // get the resource + String uriString = uri.toString(); + String resourceName = uriString.substring(uriString.indexOf("!") + 1); + final BufferedInputStream is = new BufferedInputStream(getClass().getResourceAsStream(resourceName)); + + // construct filename from resource name + String prefix = resourceName.substring(1); + String suffix = null; + final int dotIndex = prefix.lastIndexOf("."); + if (dotIndex > 0) { + prefix = resourceName.substring(0, dotIndex); + suffix = resourceName.substring(dotIndex+1); + } + + // create temporary file and copy resource to it + File of = null; + BufferedOutputStream os = null; + try { + of = File.createTempFile(prefix, suffix); + os = new BufferedOutputStream(new FileOutputStream(of)); + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + of.deleteOnExit(); + uri = of.toURI(); + + try { + int avail = is.available(); + while (avail > 0) { + byte buffer[] = new byte[avail]; + int bytesread = is.read(buffer, 0, avail); + os.write(buffer, 0, bytesread); + avail = is.available(); + } + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + try { + Desktop.getDesktop().browse(uri); + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + } + } + }); if (!opaque) { Color bg = new JPanel().getBackground(); editorPane.setBackground(new Color(bg.getRed(), bg.getGreen(), bg.getBlue()));