/* * Copyright (C) 2008 Clam <clamisgood@gmail.com> * Copyright (C) 2011 IsmAvatar <IsmAvatar@gmail.com> * Copyright (C) 2014 Robert B. Colton * * This file is part of LateralGM. * LateralGM is free software and comes with ABSOLUTELY NO WARRANTY. * See LICENSE for details. */ package org.lateralgm.components; import java.awt.Desktop; import java.awt.Dimension; import java.awt.Frame; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import org.lateralgm.main.LGM; import org.lateralgm.main.Prefs; import org.lateralgm.messages.Messages; public class ErrorDialog extends JDialog implements ActionListener { private static final long serialVersionUID = 1L; private static final int DEBUG_HEIGHT = 200; private static ErrorDialog INSTANCE = null; private String submitURI = Prefs.issueURI; protected JTextArea debugInfo; protected JButton copy; protected JButton submit; protected JButton cancel; protected JScrollPane scroll; protected JOptionPane optionpane; public static ErrorDialog getInstance() { if (INSTANCE == null) { INSTANCE = new ErrorDialog(LGM.frame, Messages.getString("ErrorDialog.UNCAUGHT_TITLE"), //$NON-NLS-1$ Messages.getString("ErrorDialog.UNCAUGHT_MESSAGE"), //$NON-NLS-1$ Prefs.issueURI); //$NON-NLS-1$ } return INSTANCE; } public static String generateAgnosticInformation() { String ret = "Operating System: " + System.getProperty("os.name"); ret += "\nVersion: " + System.getProperty("os.version"); ret += "\nArchitecture: " + System.getProperty("os.arch"); ret += "\n\nJava Name: " + System.getProperty("java.vm.name"); ret += "\nJava Vendor: " + System.getProperty("java.vendor"); ret += "\nVersion: " + System.getProperty("java.version"); ret += "\n\nAvailable processors (cores): " + Runtime.getRuntime().availableProcessors(); ret += "\nFree memory (bytes): " + Runtime.getRuntime().freeMemory(); long maxMemory = Runtime.getRuntime().maxMemory(); ret += "\nMaximum memory (bytes): " + (maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory); ret += "\nTotal memory available to JVM (bytes): " + Runtime.getRuntime().totalMemory(); /* Get a list of all filesystem roots on this system */ File[] roots = File.listRoots(); /* For each filesystem root, print some info */ for (File root : roots) { ret += "\n\nFile system root: " + root.getAbsolutePath(); ret += "\nTotal space (bytes): " + root.getTotalSpace(); ret += "\nFree space (bytes): " + root.getFreeSpace(); ret += "\nUsable space (bytes): " + root.getUsableSpace(); } ret += "\n\nStack trace:"; return ret; } public void setMessage(String message) { optionpane.setMessage(new Object[] { message, scroll }); } public void setDebugInfo(String text) { debugInfo.setText("\n" + text); debugInfo.setCaretPosition(0); } public void setDebugInfo(Throwable e) { debugInfo.setText("\n" + throwableToString(e)); debugInfo.setCaretPosition(0); } public void appendDebugInfo(String text) { debugInfo.append("\n" + text); } public void appendDebugInfo(Throwable e) { debugInfo.append("\n" + throwableToString(e)); } private static JButton makeButton(String key, ActionListener listener) { JButton but = new JButton(Messages.getString(key),LGM.getIconForKey(key)); but.addActionListener(listener); return but; } public ErrorDialog(Frame parent, String title, String message, String url) { this(parent,title,message,"",url); } public ErrorDialog(Frame parent, String title, String message, Throwable e, String url) { this(parent,title,message,throwableToString(e),url); } public ErrorDialog(Frame parent, String title, String message, Throwable e) { this(parent,title,message,throwableToString(e),Prefs.issueURI); } public ErrorDialog(Frame parent, String title, String message, String debugText, String uri) { super(parent, title); setResizable(false); setModalExclusionType(ModalExclusionType.TOOLKIT_EXCLUDE); submitURI = uri; this.debugInfo = new JTextArea(); debugInfo.setEditable(false); // show the caret anyway debugInfo.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { debugInfo.getCaret().setVisible(true); debugInfo.getCaret().setSelectionVisible(true); } @Override public void focusLost(FocusEvent e) { debugInfo.getCaret().setVisible(false); debugInfo.getCaret().setSelectionVisible(false); } }); debugInfo.setText(ErrorDialog.generateAgnosticInformation()); this.appendDebugInfo(debugText); scroll = new JScrollPane(debugInfo); Dimension dim = new Dimension(scroll.getWidth(),DEBUG_HEIGHT); scroll.setPreferredSize(dim); copy = makeButton("ErrorDialog.COPY",this); //$NON-NLS-1$ submit = makeButton("ErrorDialog.SUBMIT",this); //$NON-NLS-1$ cancel = makeButton("ErrorDialog.CANCEL",this); //$NON-NLS-1$ dim = new Dimension(Math.max(copy.getPreferredSize().width, cancel.getPreferredSize().width), copy.getPreferredSize().height); submit.setPreferredSize(dim); copy.setPreferredSize(dim); cancel.setPreferredSize(dim); optionpane = new JOptionPane(new Object[] { message, scroll }, JOptionPane.ERROR_MESSAGE, JOptionPane.DEFAULT_OPTION, null, new JButton[] { copy, submit, cancel }); setContentPane(optionpane); setSize(640, 480); setLocationRelativeTo(parent); } protected static String throwableToString(Throwable e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); return sw.toString(); } public void actionPerformed(ActionEvent e) { if (e.getSource() == submit) { try { Desktop.getDesktop().browse(java.net.URI.create(submitURI)); } catch (IOException e1) { JOptionPane.showMessageDialog(this, Messages.format("ErrorDialog.DESKTOP_MESSAGE", submitURI), Messages.getString("ErrorDialog.DESKTOP_TITLE"), JOptionPane.ERROR_MESSAGE); } } else if (e.getSource() == copy) { Toolkit.getDefaultToolkit().getSystemClipboard().setContents( new StringSelection(debugInfo.getText()), null); } else if (e.getSource() == cancel) { dispose(); } } }