package cz.cuni.lf1.lge.ThunderSTORM.UI;
import cz.cuni.lf1.lge.ThunderSTORM.JarFirstClassLoader;
import ij.IJ;
import ij.plugin.BrowserLauncher;
import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.EditorKit;
public class HelpButton extends JButton {
private static JDialog window = constructFrame();
private static JEditorPane htmlBrowser;
private static final int WINDOW_WIDTH = 600;
private static final int WINDOW_HEIGHT = 400;
URL url;
public HelpButton(URL helpUrl) {
//icon licence: CC 3.0, attribution required: http://p.yusukekamiyamane.com/icons/attribution/
super(new ImageIcon(IJ.getClassLoader().getResource("resources/help/images/question-button-icon.png")));
setBorder(BorderFactory.createEmptyBorder());
setBorderPainted(false);
setIconTextGap(0);
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
this.url = helpUrl;
addActionListener(new HelpButtonActionListener());
}
private static JDialog constructFrame() {
final JDialog frame = new JDialog();
try {
frame.addWindowFocusListener(new WindowAdapter() {
@Override
public void windowLostFocus(WindowEvent e) {
frame.setVisible(false);
}
});
if(IJ.isJava17()) {
frame.setType(Window.Type.UTILITY);
}
frame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); //for use within modal dialog
htmlBrowser = createEditorUsingOurClassLoader();
htmlBrowser.setBorder(BorderFactory.createEmptyBorder());
htmlBrowser.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
try {
if("jar".equals(e.getURL().getProtocol())) {
htmlBrowser.setPage(e.getURL());
} else {
BrowserLauncher.openURL(e.getURL().toString());
}
} catch(Exception ex) {
IJ.handleException(ex);
}
} else if(e.getEventType() == HyperlinkEvent.EventType.ENTERED) {
htmlBrowser.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else if(e.getEventType() == HyperlinkEvent.EventType.EXITED) {
htmlBrowser.setCursor(Cursor.getDefaultCursor());
}
}
});
JScrollPane scrollPane = new JScrollPane(htmlBrowser);
scrollPane.setPreferredSize(new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT));
frame.getContentPane().add(scrollPane);
} catch(Exception e) {
IJ.handleException(e);
}
return frame;
}
/**
* Create a BrowserPane object using a custom classloader that prefers
* classes in our jar
*/
public static JEditorPane createEditorUsingOurClassLoader() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
ClassLoader our = JarFirstClassLoader.getInstance();
Class c = Class.forName("org.fit.cssbox.swingbox.BrowserPane", true, our);
JEditorPane editor = (JEditorPane) c.newInstance();
Class c2 = Class.forName("org.fit.cssbox.swingbox.SwingBoxEditorKit", true, our);
editor.setEditorKit((EditorKit) c2.newInstance());
return editor;
}
/**
* shows the url in the static window, sizes and positions the window
* accordingly
*/
private void showInTextWindow() throws IOException {
window.setVisible(false);
// same height as parent window of the button, positioned next to it on left or right side
Window ancestor = SwingUtilities.getWindowAncestor(this);
window.setPreferredSize(new Dimension(WINDOW_WIDTH, Math.max(ancestor.getHeight(), WINDOW_HEIGHT)));
int screenEnd = ancestor.getGraphicsConfiguration().getBounds().width + ancestor.getGraphicsConfiguration().getBounds().x;
Point ancestorLocation = ancestor.getLocationOnScreen();
if(ancestorLocation.x + ancestor.getWidth() + window.getPreferredSize().width < screenEnd) {
window.setLocation(ancestorLocation.x + ancestor.getWidth(), ancestorLocation.y);
} else {
window.setLocation(ancestorLocation.x - window.getPreferredSize().width, ancestorLocation.y);
}
//set page shown in browser
if(url != null && !url.equals(htmlBrowser.getPage())) {
try {
htmlBrowser.setPage(url);
} catch(Exception e) {
htmlBrowser.setText("Could not load help file");
}
}
window.pack();
window.setVisible(true);
}
class HelpButtonActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
showInTextWindow();
} catch(IOException ex) {
IJ.handleException(ex);
}
}
}
}