package zander.ui; import java.awt.BorderLayout; import java.awt.Window; import java.awt.event.KeyEvent; import java.io.PrintWriter; import java.io.StringWriter; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingConstants; import javax.swing.UIManager; public class ErrorDialog extends JDialog { private static final long serialVersionUID = 7389430189757589219L; private Throwable error; private final JLabel iconLabel; private final JLabel messageLabel; private final JPanel messagePanel; private final JTextArea errorBox; private final JScrollPane errorScroll; private final JButton advancedButton; private final JButton closeButton; private final JPanel buttonPanel; private final JPanel content; public ErrorDialog(String title, String message, Throwable error) { this(null, title, message, error); } public ErrorDialog(Window parent, String title, String message, Throwable error) { super(parent, title); this.error = error; iconLabel = new JLabel(UIManager.getIcon("OptionPane.errorIcon")); messageLabel = new JLabel(message, SwingConstants.CENTER); messagePanel = new JPanel(); messagePanel.setLayout(new BoxLayout(messagePanel, BoxLayout.X_AXIS)); messagePanel.add(iconLabel); messagePanel.add(messageLabel); errorBox = new JTextArea(getErrorMessage()); errorBox.setRows(getErrorBoxRows()); errorBox.setColumns(getErrorBoxColumns()); errorBox.setEditable(false); errorScroll = new JScrollPane(errorBox); errorScroll.setVisible(false); advancedButton = new JButton("Show More..."); advancedButton.setMnemonic(KeyEvent.VK_S); advancedButton.addActionListener((e) -> { errorScroll.setVisible(!errorScroll.isVisible()); pack(); }); closeButton = new JButton("Close"); advancedButton.setMnemonic(KeyEvent.VK_C); closeButton.addActionListener((e) -> { dispose(); }); buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); buttonPanel.add(advancedButton); buttonPanel.add(Box.createHorizontalGlue()); buttonPanel.add(closeButton); content = new JPanel(new BorderLayout()); content.setLayout(new BorderLayout()); content.add(messagePanel, BorderLayout.PAGE_START); content.add(errorScroll, BorderLayout.CENTER); content.add(buttonPanel, BorderLayout.PAGE_END); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setContentPane(content); setModalityType(JDialog.DEFAULT_MODALITY_TYPE); setAlwaysOnTop(true); pack(); UIUtils.centerWindow(this, parent); } private int getErrorBoxRows() { int nlc = 0; for (char c : errorBox.getText().toCharArray()) { if (c == '\n') { ++nlc; } } return Math.min(nlc, 15); } private int getErrorBoxColumns() { String[] lines = errorBox.getText().split("\\n"); int longest = 0; for (String line : lines) { if (line.length() > longest) { longest = line.length(); } } return Math.min(longest, 35); } public String getMessage() { return messageLabel.getText(); } public void setMessage(String message) { messageLabel.setText(message); } private String getErrorMessage() { if (error == null) { return "No error information available"; } final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); error.printStackTrace(pw); return sw.toString(); } }