/** * This file is part of JSkat. * * JSkat is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JSkat is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JSkat. If not, see <http://www.gnu.org/licenses/>. */ package org.jskat.gui.swing.help; import java.awt.BorderLayout; import java.awt.Desktop; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URI; import java.net.URISyntaxException; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.ScrollPaneConstants; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.text.html.HTMLEditorKit; import org.jskat.util.JSkatResourceBundle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Help dialog for JSkat */ public class JSkatHelpDialog extends JDialog { private static final long serialVersionUID = 1L; private static Logger log = LoggerFactory.getLogger(JSkatHelpDialog.class); protected final JSkatResourceBundle strings = JSkatResourceBundle.INSTANCE; private final JFrame parent; private JScrollPane scrollPane; private JTextPane textPane; private final String contentURL; /** * Creates new form JSkatHelpDialog * * @param parentFrame * The parent JFrame * @param title * Dialog title * @param contentPath * Path to dialog content */ public JSkatHelpDialog(final JFrame parentFrame, final String title, final String contentPath) { super(parentFrame, true); this.parent = parentFrame; this.contentURL = contentPath; initComponents(title); setLocationRelativeTo(this.parent); } /** * This method is called from within the constructor to initialize the form. */ private void initComponents(final String title) { JPanel northPanel = new JPanel(); JPanel southPanel = getButtonPanel(); JPanel westPanel = new JPanel(); JPanel eastPanel = new JPanel(); this.scrollPane = new JScrollPane(); this.textPane = new JTextPane(); setTitle(title); addWindowListener(new WindowAdapter() { @Override public void windowClosing(final WindowEvent evt) { closeDialog(); } }); getContentPane().add(northPanel, BorderLayout.NORTH); this.textPane.setEditorKit(new HTMLEditorKit()); this.textPane.addHyperlinkListener(this.hll); this.textPane.setEditable(false); setFile(this.contentURL); this.scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); this.scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); this.scrollPane.setViewportView(this.textPane); this.scrollPane.setPreferredSize(new Dimension(600, 300)); getContentPane().add(this.scrollPane, BorderLayout.CENTER); getContentPane().add(southPanel, BorderLayout.SOUTH); getContentPane().add(eastPanel, BorderLayout.EAST); getContentPane().add(westPanel, BorderLayout.WEST); pack(); } protected JPanel getButtonPanel() { JPanel southPanel = new JPanel(); JButton closeButton = new JButton(this.strings.getString("close")); //$NON-NLS-1$ closeButton.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent evt) { closeDialog(); } }); southPanel.add(closeButton); return southPanel; } private String getResource(final String url) { StringBuilder message = new StringBuilder(); try { InputStream is = ClassLoader.getSystemResourceAsStream(url); InputStreamReader isr = new java.io.InputStreamReader(is); BufferedReader bfr = new java.io.BufferedReader(isr); while (bfr.ready()) { message.append(bfr.readLine()).append("\n"); //$NON-NLS-1$ } } catch (java.io.IOException e) { log.warn("Error in loading message: ", e); } return message.toString(); } private void setToInitialState() { this.scrollPane.getVerticalScrollBar().setValue(0); setLocationRelativeTo(this.parent); } /** * Shows the Help dialog * * @param visible * Shows the dialog if set to TRUE */ @Override public void setVisible(final boolean visible) { if (visible) { setToInitialState(); } super.setVisible(visible); } /** Closes the dialog */ void closeDialog() { setVisible(false); dispose(); } /** * sets a single file, which will be inserted in the general html frame * * @param filename * html snippet file */ public void setFile(final String filename) { if (filename != null) { setFile(new String[] { filename }); } } /** * sets a list of files, which will be concatenated and inserted in the * general html frame * * @param filenames * list of html snippet files */ public void setFile(final String[] filenames) { StringBuilder sb = new StringBuilder(); sb.append(getResource("org/jskat/gui/help/frame.html")); int ix = sb.indexOf("@@insert@@"); if (ix < 0) { throw new IllegalArgumentException("frame.html contains no @@insert@@"); } for (String f : filenames) { sb.insert(ix, getResource(f)); ix = sb.indexOf("@@insert@@"); } sb.delete(ix, ix + 10); this.textPane.setText(sb.toString()); this.textPane.setCaretPosition(0); } /** * inserts a html snippet in the general frame of the HTMLDialog * * @param htmlSnippet * the html snippet to insert */ public void insertText(final String htmlSnippet) { StringBuilder sb = new StringBuilder(); sb.append(getResource("org/jskat/gui/help/frame.html")); int ix = sb.indexOf("@@insert@@"); if (ix < 0) { throw new IllegalArgumentException("frame.html contains no @@insert@@"); } sb.replace(ix, ix + 10, htmlSnippet); this.textPane.setText(sb.toString()); this.textPane.setCaretPosition(0); } /** * sets a specific html text to display in the dialog * * @param html * the html to display in the dialog */ public void setText(final String html) { this.textPane.setText(html); this.textPane.setCaretPosition(0); } protected final Action openExternalAction = new AbstractAction(this.strings.getString("open_external")) { private static final long serialVersionUID = 4233152199895964006L; @Override public void actionPerformed(final ActionEvent arg0) { File f = new File(System.getProperty("java.io.tmpdir") + File.separator + "JSkat_doc.html"); PrintWriter pw; try { pw = new PrintWriter(f); } catch (FileNotFoundException e) { log.warn("error in writing external html file:", e); return; } pw.print(externalizeLinks(JSkatHelpDialog.this.textPane.getText())); pw.flush(); pw.close(); try { Desktop.getDesktop().browse(new URI("file:///" + f.getAbsolutePath().replace("\\", "/"))); } catch (IOException e) { log.error("IOException", e); } catch (URISyntaxException e) { log.error("URI Fehler", e); } } }; String externalizeLinks(final String html) { return html.replace("a href=\"org/jskat/gui/help/", "a href=\"http://www.jskat.org/help/"); } private final HyperlinkListener hll = new HyperlinkListener() { @Override public void hyperlinkUpdate(final HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { String link = e.getDescription(); if (link.toLowerCase().startsWith("http:")) { try { Desktop.getDesktop().browse(new URI(link)); } catch (IOException ex) { log.warn("IOException", ex); JOptionPane.showMessageDialog(JSkatHelpDialog.this, "Error in loading external link:\n" + link + "\n" + (ex.getMessage() != null ? ex.getMessage() : "<???>"), "Externer Link", JOptionPane.ERROR_MESSAGE); } catch (URISyntaxException ex) { log.warn("URI exception", ex); JOptionPane.showMessageDialog(JSkatHelpDialog.this, "Error in loading external link:\n" + link + "\n" + (ex.getMessage() != null ? ex.getMessage() : "<???>"), "Externer Link", JOptionPane.ERROR_MESSAGE); } } else { setFile(link); } } } }; }