/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2011, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.swing.dialog;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.geotools.swing.locale.LocaleUtils;
/**
* Displays an {@code Exception} to the user in a modal dialog. This class is not a Swing
* component itself, rather it provides static {@code showDialog} methods to create and
* display dialogs safely from any thread.
* <p>
*
* Example of use:
*
* <pre><code>
* try {
*
* // ...something awful happens in here...
*
* } catch (SomeException ex) {
* JExceptionReporter.showDialog(ex, "Bummer, it failed again");
* }
* </code></pre>
*
* @author Michael Bedward
* @since 8.0
* @source $URL$
* @version $Id$
*/
public class JExceptionReporter {
// Hidden constructor.
private JExceptionReporter() {}
/**
* Displays an exception in a dialog where the title is the
* exception class name and the body of the dialog shows the
* exception message.
* <p>
* It is safe to call this method from any thread.
*
* @param exception exception to display
*/
public static void showDialog(Throwable exception) {
showDialog(exception, null);
}
/**
* Displays an exception in a dialog where the title is the
* exception class name and the body of the dialog shows the
* given message.
* <p>
* It is safe to call this method from any thread.
*
* @param exception exception to display
* @param message message to display; if {@code null} or empty the
* message will be taken from the exception
*/
public static void showDialog(final Throwable exception, final String message) {
if (exception == null) {
throw new IllegalArgumentException("exception must not be null");
}
if (SwingUtilities.isEventDispatchThread()) {
doShowDialog(exception, message);
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
doShowDialog(exception, message);
}
});
}
}
private static void doShowDialog(Throwable exception, String message) {
String title = exception.getClass().getSimpleName();
if (empty(message)) {
message = exception.getLocalizedMessage();
if (empty(message)) {
message = LocaleUtils.getValue("Common", "UnspecifiedError");
}
}
ReportingDialog dialog = new ReportingDialog(title, message);
DialogUtils.showCentred(dialog);
}
private static boolean empty(String s) {
return s == null || s.trim().length() == 0;
}
/**
* The dialog used to display the {@code Exception}. It is package-private
* rather than private to enable unit tests.
*/
static class ReportingDialog extends AbstractSimpleDialog {
private static final int DEFAULT_WIDTH = 400;
private static final int DEFAULT_HEIGHT = 200;
private static final int MARGIN = 5;
private final String message;
private ReportingDialog(String title, String message) {
super(title);
this.message = message;
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
initComponents();
}
@Override
public JPanel createControlPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK),
BorderFactory.createEmptyBorder(MARGIN, MARGIN, MARGIN, MARGIN)));
String text = String.format("<html>%s</html>", message);
int w = DEFAULT_WIDTH - 2 * MARGIN;
Dimension dim = DialogUtils.getHtmlLabelTextExtent(text, w, true);
JLabel label = new JLabel(text);
label.setPreferredSize(dim);
panel.add(label);
panel.setPreferredSize(new Dimension(DEFAULT_WIDTH, dim.height + 4*MARGIN ));
return panel;
}
@Override
protected JPanel createButtonPanel() {
JPanel panel = new JPanel();
JButton button = new JButton("Close");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
onOK();
}
});
panel.add(button);
return panel;
}
@Override
public void onOK() {
closeDialog();
}
}
}