
org.pepsoft.worldpainter.ErrorDialog Maven / Gradle / Ivy
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/*
* ErrorDialog.java
*
* Created on Apr 17, 2011, 8:22:55 PM
*/
package org.pepsoft.worldpainter;
import java.awt.Desktop;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import org.pepsoft.worldpainter.layers.Layer;
/**
*
* @author pepijn
*/
public class ErrorDialog extends javax.swing.JDialog {
/** Creates new form ErrorDialog */
public ErrorDialog(Dialog parent) {
super(parent, true);
init(parent);
}
/** Creates new form ErrorDialog */
public ErrorDialog(Frame parent) {
super(parent, true);
init(parent);
}
public void setException(Throwable exception) {
logger.error(exception.getClass().getSimpleName() + ": " + exception.getMessage(), exception);
Throwable rootCause = exception;
while (rootCause.getCause() != null) {
rootCause = rootCause.getCause();
}
if (rootCause instanceof OutOfMemoryError) {
setTitle("Out of Memory");
jTextArea1.setText("Not enough memory available for that operation!\n\n"
+ "WorldPainter is already using the recommended maximum\n"
+ "amount of memory, so it is not recommended to give it\n"
+ "more. To be able to perform the operation you should\n"
+ "install more memory.");
jButton1.setEnabled(false);
jButton1.setToolTipText("Not necessary to mail details of out of memory errors");
jButton3.setEnabled(false);
} else {
String message = rootCause.getMessage();
if ((message != null) && (message.length() > 250)) {
message = message.substring(0, 247) + "...";
}
String text = "An unexpected error has occurred.\n\n"
+ "Type: " + rootCause.getClass().getName() + "\n"
+ "Message: " + message + "\n\n"
+ "Please help debug the problem by using the button below to email the details of this error to the creator of this program.\n\n"
+ "The program may now be in an unstable state. It is recommended to restart it as soon as possible.";
jTextArea1.setText(text);
}
pack();
StringBuilder sb = new StringBuilder();
String eol = System.getProperty("line.separator");
sb.append(exception.getClass().getName());
sb.append(": ");
sb.append(exception.getMessage());
sb.append(eol);
StackTraceElement[] stackTrace = exception.getStackTrace();
for (int i = 0; i < Math.min(stackTrace.length, 5); i++) {
sb.append("\tat ");
sb.append(stackTrace[i].getClassName());
sb.append('.');
sb.append(stackTrace[i].getMethodName());
sb.append('(');
sb.append(stackTrace[i].getFileName());
sb.append(':');
sb.append(stackTrace[i].getLineNumber());
sb.append(')');
sb.append(eol);
}
sb.append(eol);
if (rootCause != exception) {
sb.append("Root cause:");
sb.append(eol);
sb.append(rootCause.getClass().getName());
sb.append(": ");
sb.append(rootCause.getMessage());
sb.append(eol);
stackTrace = rootCause.getStackTrace();
for (int i = 0; i < Math.min(stackTrace.length, 5); i++) {
sb.append("\tat ");
sb.append(stackTrace[i].getClassName());
sb.append('.');
sb.append(stackTrace[i].getMethodName());
sb.append('(');
sb.append(stackTrace[i].getFileName());
sb.append(':');
sb.append(stackTrace[i].getLineNumber());
sb.append(')');
sb.append(eol);
}
sb.append(eol);
}
sb.append("WorldPainter version: " + Version.VERSION + " (" + Version.BUILD + ")" + eol);
sb.append(eol);
for (String propertyName: SYSTEM_PROPERTIES) {
sb.append(propertyName);
sb.append(": ");
sb.append(System.getProperty(propertyName));
sb.append(eol);
}
sb.append(eol);
Runtime runtime = Runtime.getRuntime();
sb.append("Free memory: " + runtime.freeMemory() + " bytes" + eol);
sb.append("Total memory size: " + runtime.totalMemory() + " bytes" + eol);
sb.append("Max memory size: " + runtime.maxMemory() + " bytes" + eol);
// The app may be in an unstable state, so if an exception occurs while
// interrogating it, swallow it to prevent endless loops
try {
App app = App.getInstanceIfExists();
World2 world = (app != null) ? app.getWorld() : null;
Dimension dimension = (app != null) ? app.getDimension() : null;
if ((world != null) && (dimension != null)) {
sb.append(eol);
sb.append("World name: " + world.getName() + eol);
sb.append("Seed: " + dimension.getSeed() + eol);
sb.append("Bounds: " + dimension.getLowestX() + ", " + dimension.getLowestY() + " => " + dimension.getHighestX() + ", " + dimension.getHighestY() + eol);
sb.append("Height: " + world.getMaxHeight() + eol);
sb.append("Number of tiles: " + dimension.getTiles().size() + eol);
Set layers = new HashSet<>();
for (Tile tile : dimension.getTiles()) {
layers.addAll(tile.getLayers());
}
sb.append("Layers in use: ");
boolean first = true;
for (Layer layer : layers) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(layer.getName());
}
sb.append(eol);
sb.append("Border: " + dimension.getBorder() + " @ " + dimension.getBorderLevel() + eol);
sb.append("Sub surface material: " + dimension.getSubsurfaceMaterial() + eol);
TileFactory tileFactory = dimension.getTileFactory();
if (tileFactory instanceof HeightMapTileFactory) {
HeightMapTileFactory heightMapTileFactory = (HeightMapTileFactory) tileFactory;
sb.append("Water height: " + heightMapTileFactory.getWaterHeight() + eol);
}
if (world.getImportedFrom() != null) {
sb.append("World imported from " + world.getImportedFrom() + eol);
}
if (!world.isAllowMerging()) {
sb.append("World created in old coordinate system" + eol);
}
}
if (app != null) {
sb.append(eol);
sb.append("Operation: " + app.getActiveOperation() + eol);
sb.append("Radius: " + app.getRadius() + eol);
// sb.append("Brush shape: " + app.getBrushShape() + "/" + app.getToolBrushShape() + eol);
sb.append("Brush: " + app.getBrush() + "/" + app.getToolBrush() + eol);
sb.append("Level: " + app.getLevel() + "/" + app.getToolLevel() + eol);
sb.append("Zoom: " + app.getZoom() + eol);
sb.append("Hidden layers: " + app.getHiddenLayers());
}
} catch (Throwable t) {
logger.error("Secondary exception occurred while interrogating app for exception report", t);
}
body = sb.toString();
if (! "true".equals(System.getProperty("org.pepsoft.worldpainter.devMode"))) {
logger.error(body);
}
}
private void init(Window parent) {
initComponents();
getRootPane().setDefaultButton(jButton2);
if ((! Desktop.isDesktopSupported()) || (! Desktop.getDesktop().isSupported(Desktop.Action.MAIL))) {
jButton1.setEnabled(false);
jButton1.setToolTipText("Emailing not supported on this system; please use the \"copy to clipboard\" button and mail the details to [email protected].");
}
ActionMap actionMap = rootPane.getActionMap();
actionMap.put("cancel", new AbstractAction("cancel") {
public void actionPerformed(ActionEvent e) {
dispose();
}
private static final long serialVersionUID = 1L;
});
InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel");
setLocationRelativeTo(parent);
}
private void close() {
dispose();
}
private void email() {
try {
URI uri = new URI("mailto", "[email protected]?subject=WorldPainter error report&body=" + body, null);
Desktop desktop = Desktop.getDesktop();
desktop.mail(uri);
JOptionPane.showMessageDialog(this, "A new email message should have been opened now for you to send.\nIf it did not work, please use the \"copy to clipboard\" button\nand manually mail the information to [email protected].", "Email Created", JOptionPane.INFORMATION_MESSAGE);
} catch (URISyntaxException e) {
logger.error("URI syntax error while trying to send email", e);
JOptionPane.showMessageDialog(this, "Could not create email message with error details!\nPlease use the \"copy to clipboard\" button and mail\nthe information to [email protected].", "Could Not Create Email", JOptionPane.ERROR_MESSAGE);
} catch (IOException e) {
logger.error("I/O error while trying to send email", e);
JOptionPane.showMessageDialog(this, "Could not create email message with error details!\nPlease use the \"copy to clipboard\" button and mail\nthe information to [email protected].", "Could Not Create Email", JOptionPane.ERROR_MESSAGE);
}
}
private void copyToClipboard() {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection data = new StringSelection(body);
clipboard.setContents(data, data);
JOptionPane.showMessageDialog(this, "The information has been copied to the clipboard. Please paste\nit in a new email and send it to [email protected].", "Information Copied", JOptionPane.INFORMATION_MESSAGE);
}
public static void main(String[] args) {
ErrorDialog dialog = new ErrorDialog((Frame) null);
dialog.setException(new OutOfMemoryError("test"));
dialog.setVisible(true);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jTextArea1 = new javax.swing.JTextArea();
jButton3 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Unexpected Error");
jButton1.setText("Email Details...");
jButton1.addActionListener(this::jButton1ActionPerformed);
jButton2.setText("Close");
jButton2.addActionListener(this::jButton2ActionPerformed);
jTextArea1.setEditable(false);
jTextArea1.setFont(getFont());
jTextArea1.setLineWrap(true);
jTextArea1.setRows(10);
jTextArea1.setWrapStyleWord(true);
jTextArea1.setOpaque(false);
jButton3.setText("Copy details to clipboard");
jButton3.addActionListener(this::jButton3ActionPerformed);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jTextArea1, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jButton2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton1)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(jTextArea1)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton1)
.addComponent(jButton2)
.addComponent(jButton3))
.addContainerGap())
);
pack();
}// //GEN-END:initComponents
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
email();
}//GEN-LAST:event_jButton1ActionPerformed
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
close();
}//GEN-LAST:event_jButton2ActionPerformed
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
copyToClipboard();
}//GEN-LAST:event_jButton3ActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton3;
private javax.swing.JTextArea jTextArea1;
// End of variables declaration//GEN-END:variables
private String body;
private static final double GB = 1024.0 * 1024.0 * 1024.0;
private static final String[] SYSTEM_PROPERTIES = {
"java.version",
"java.vendor",
"java.vm.version",
"java.vm.vendor",
"java.vm.name",
"os.name",
"os.arch",
"os.version",
"user.home",
"user.dir",
"user.country",
"user.language",
};
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ErrorDialog.class);
private static final long serialVersionUID = 1L;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy