/*
* This file is part of the OSMembrane project.
* More informations under www.osmembrane.de
*
* The project is licensed under the GNU GENERAL PUBLIC LICENSE 3.0.
* for more details about the license see http://www.osmembrane.de/license/
*
* Source: $HeadURL$ ($Revision$)
* Last changed: $Date$
*/
package de.osmembrane.view.dialogs;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import de.osmembrane.Application;
import de.osmembrane.exceptions.ExceptionSeverity;
import de.osmembrane.tools.I18N;
import de.osmembrane.view.AbstractDialog;
/**
* the exception message dialog (the window you will see most of the time ;)
*
* @author tobias_kuhn
*
*/
public class ExceptionDialog extends AbstractDialog {
private static final long serialVersionUID = 3750775593370584501L;
/**
* The components that will describe the exception occured
*/
private JLabel icon;
private JLabel caption;
private JLabel exceptionMessage;
private JTextArea exceptionText;
private JScrollPane exceptionTextPane;
/**
* The OK and "Show stack trace" Button
*/
private JButton okButton;
private JButton showTraceButton;
/**
* Whether the exception was fatal and the application should exit now
*/
private boolean fatal;
/**
* The line break
*/
private final String NL = System.getProperty("line.separator");
/**
* Initializes the {@link ExceptionDialog}
*/
public ExceptionDialog(Window owner) {
super(owner);
// set the basics up
setLayout(new GridBagLayout());
icon = new JLabel();
caption = new JLabel();
caption.setFont(caption.getFont().deriveFont(Font.BOLD));
exceptionMessage = new JLabel();
exceptionText = new JTextArea();
exceptionText.setEditable(false);
exceptionTextPane = new JScrollPane(exceptionText);
exceptionTextPane.setPreferredSize(new Dimension(640, 480));
okButton = new JButton();
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (fatal) {
System.exit(0);
} else {
hideWindow();
}
}
});
showTraceButton = new JButton(I18N.getInstance().getString(
"View.ShowStackTrace"));
showTraceButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
exceptionTextPane.setPreferredSize(new Dimension(
(getWidth() > 648) ? getWidth() - 8 : 640, 480));
showTraceButton.setVisible(false);
exceptionTextPane.setVisible(true);
exceptionText.setCaretPosition(0);
pack();
centerWindow();
}
});
// grid bag layout
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(8, 8, 8, 8);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridheight = 2;
add(icon, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.gridheight = 1;
gbc.gridwidth = 1;
add(caption, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.gridwidth = 1;
add(exceptionMessage, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.gridwidth = 2;
add(exceptionTextPane, gbc);
gbc.gridx = 0;
gbc.gridy = 3;
gbc.gridwidth = 2;
JPanel buttons = new JPanel();
buttons.add(showTraceButton);
buttons.add(okButton);
if (showTraceButton.getPreferredSize().width > okButton
.getPreferredSize().width) {
okButton.setPreferredSize(showTraceButton.getPreferredSize());
} else {
showTraceButton.setPreferredSize(okButton.getPreferredSize());
}
add(buttons, gbc);
pack();
centerWindow();
}
/**
*
* @param ste
* the {@link StackTraceElement} to print into a string
* @return the human readable string representation of the stack trace
* element
*/
private String printStackTraceElement(StackTraceElement ste) {
return " " + I18N.getInstance().getString("View.ErrorDialog.At") + " "
+ ste.getClassName() + "." + ste.getMethodName() + "("
+ ste.getFileName() + ":" + ste.getLineNumber() + ")" + NL;
}
/**
* Displays a Throwable and handles the possibly necessary shutdown.
*
* @param t
* the occurred Throwable
* @param severity
* the kind of the exception
* @param causingObject
* the causing object or null, if unknown
*/
public void showException(Throwable t, ExceptionSeverity severity,
Object causingObject) {
// ensure valid pointers
if (t == null) {
Application.handleException(new NullPointerException());
}
if (causingObject == null) {
if (t.getStackTrace().length > 0) {
causingObject = t.getStackTrace()[0];
} else {
// empty stack traces are some sort of exception cause
causingObject = t.getStackTrace();
}
}
if (severity == null) {
severity = ExceptionSeverity.INVALID;
}
// set icon
switch (severity) {
case WARNING:
setWindowTitle(I18N.getInstance().getString(
"View.ErrorDialog.Warning"));
break;
case UNEXPECTED_BEHAVIOR:
setWindowTitle(I18N.getInstance().getString(
"View.ErrorDialog.UnexpectedException"));
break;
case CRITICAL_UNEXPECTED_BEHAVIOR:
setWindowTitle(I18N.getInstance().getString(
"View.ErrorDialog.CriticalUnexpectedException"));
break;
default:
setWindowTitle(I18N.getInstance().getString(
"View.ErrorDialog.Exception"));
}
caption.setText(I18N.getInstance().getString("View.ErrorDialog.In",
t.getClass().getCanonicalName(), causingObject.toString()));
// find a suitable description, if one exists
String message = t.getLocalizedMessage();
if (message == null) {
message = t.getMessage();
if (message == null) {
if (t.getCause() != null) {
message = t.getCause().getLocalizedMessage();
if (message == null) {
message = t.getCause().getMessage();
if (message == null) {
message = I18N.getInstance().getString(
"View.ErrorDialog.NoMessage");
}
}
} else {
message = I18N.getInstance().getString(
"View.ErrorDialog.NoMessage");
}
}
}
exceptionMessage.setText(message);
// general information
StringBuilder sb = new StringBuilder();
sb.append(I18N.getInstance().getString("View.ErrorDialog.Caused",
causingObject.toString(), t.toString())
+ NL + NL);
for (StackTraceElement ste : t.getStackTrace()) {
sb.append(printStackTraceElement(ste));
}
/*
* loop through the causes, find out if any of them was an instance of
* Error
*/
boolean causeWasError = false;
Throwable causedBy = t.getCause();
while (causedBy != null) {
sb.append(I18N.getInstance().getString("View.ErrorDialog.CausedBy",
causedBy.toString())
+ NL);
for (StackTraceElement ste : causedBy.getStackTrace()) {
sb.append(printStackTraceElement(ste));
}
if (causedBy instanceof Error) {
causeWasError = true;
}
causedBy = causedBy.getCause();
}
exceptionText.setText(sb.toString());
// determine whether it was a fatal error
fatal = (severity == ExceptionSeverity.CRITICAL_UNEXPECTED_BEHAVIOR)
|| (causeWasError);
icon.setIcon(UIManager.getIcon("OptionPane.warningIcon"));
if (fatal || (severity == null)) {
icon.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
}
if (fatal) {
okButton.setText(I18N.getInstance().getString("View.Quit"));
} else {
okButton.setText(I18N.getInstance().getString("View.OK"));
}
// normally hide the stack trace, for warnings hide most of the dialog
exceptionTextPane.setVisible(false);
showTraceButton.setVisible(severity != ExceptionSeverity.WARNING);
caption.setVisible(severity != ExceptionSeverity.WARNING);
okButton.requestFocusInWindow();
pack();
centerWindow();
showWindow();
}
}