net.sf.sfac.gui.ExceptionDialog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sfac-core Show documentation
Show all versions of sfac-core Show documentation
This project is the core part of the Swing Framework and Components (SFaC).
It contains the Swing framework classes and the graphical component classes.
The newest version!
/*-------------------------------------------------------------------------
Copyright 2009 Olivier Berlanger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-------------------------------------------------------------------------*/
package net.sf.sfac.gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import net.sf.sfac.lang.LanguageSupport;
import net.sf.sfac.lang.MultiLingualText;
/**
* Dialog used to report exceptions to the user.
* This utility class looks in the exception chain (the exception, its cause, the cause of the cause ...) for exceptions
* implementing the MultiLingualText interface. All the multilingual text found are displayed in the dialog.
*
* Use the provided static methods to show an ExceptionDialog.
*
*
* @author Olivier Berlanger
*/
@SuppressWarnings("serial")
public class ExceptionDialog extends JDialog {
/** The reported exception. */
private Throwable underlyingException;
/** The 'Details' button in the dialog. */
private JButton detailButton;
/** The content pane of the dialog. */
private JPanel contentPane;
/** The panel used to show the exception stack trace. */
private JComponent detailPane;
/** The frame owning this dialog. */
private Frame parentFrame;
// --------------------- static helpers ------------------------------------------
/**
* Show the given exception in a dialog box.
* If no MultiLingualText is found in the exception chain, a default error message (like 'internal error') is displayed.
*
* @param cmp
* the component owning this dialog (can be null)
* @param t
* the exception to display
*/
public static void showDefaultDialog(Component cmp, Throwable t) {
showDefaultDialog(cmp, null, t);
}
/**
* Show the exception. If no MultiLingualText is found in the exception chain, a default error message (like 'internal error
* during action "action"') is displayed.
*
* @param cmp
* the component owning this dialog (can be null)
* @param executedActionTag
* the executed action name (or a bundle key for it).
* @param t
* the exception to display
*/
public static void showDefaultDialog(Component cmp, String executedActionTag, Throwable t) {
Frame frm = JOptionPane.getFrameForComponent(cmp);
String messageTag = "INTERNAL_ERROR";
Object[] params = null;
if (executedActionTag != null) {
messageTag = "INTERNAL_ERROR_IN_ACTION";
String actionText = LanguageSupport.getLocalizedString(executedActionTag);
params = new Object[] { actionText };
}
ExceptionDialog exDial = new ExceptionDialog(frm, "ERROR", messageTag, params, false, t);
exDial.setVisible(true);
}
/**
* Show the exception in a dialog with provided title and text. If some MultiLingualText are found in the exception chain, they
* are added to the dialog text.
*
* @param cmp
* the component owning this dialog (can be null)
* @param titleTag
* the dialog title (or a bundle key for it).
* @param messageTag
* the dialog message (or a bundle key for it).
* @param t
* the exception to display
*/
public static void showExceptionDialog(Component cmp, String titleTag, String messageTag, Throwable t) {
Frame frm = JOptionPane.getFrameForComponent(cmp);
ExceptionDialog exDial = new ExceptionDialog(frm, titleTag, messageTag, null, true, t);
exDial.setVisible(true);
}
/**
* Show the exception in a dialog with provided title and text. If some MultiLingualText are found in the exception chain, they
* are added to the dialog text.
*
* @param cmp
* the component owning this dialog (can be null)
* @param titleTag
* the dialog title (or a bundle key for it).
* @param messageTag
* the dialog message (or a bundle key for it).
* @param params
* the dialog message parameters (they can be instance of MultiLingualText).
* @param t
* the exception to display
*/
public static void showExceptionDialog(Component cmp, String titleTag, String messageTag, Object[] params, Throwable t) {
Frame frm = JOptionPane.getFrameForComponent(cmp);
ExceptionDialog exDial = new ExceptionDialog(frm, titleTag, messageTag, params, true, t);
exDial.setVisible(true);
}
// --------------------- Implementation ------------------------------------------
public ExceptionDialog(Frame frm, String titleTag, String messageTag, Object[] params, boolean merge, Throwable t) {
super(frm, LanguageSupport.getLocalizedString(titleTag), true);
parentFrame = frm;
contentPane = new JPanel(new BorderLayout(5, 5));
underlyingException = t;
// add error icon
JPanel upperPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0));
Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
upperPanel.add(new JLabel(errorIcon), BorderLayout.WEST);
// add text
String text = getDisplayText(messageTag, params, merge, t);
JComponent textPanel = getMultiLineComponent(text, 20);
upperPanel.add(textPanel, BorderLayout.CENTER);
contentPane.add(upperPanel, BorderLayout.NORTH);
// add buttons
JPanel buttonsPanel = new JPanel();
JButton okButton = new JButton(LanguageSupport.getOptionalLocalizedString("OK", "Ok"));
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
dispose();
}
});
buttonsPanel.add(okButton);
detailButton = new JButton(LanguageSupport.getOptionalLocalizedString("DETAILS", "Details"));
detailButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
showDetails();
}
});
buttonsPanel.add(detailButton);
contentPane.add(buttonsPanel, BorderLayout.SOUTH);
// pack
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
setContentPane(contentPane);
resetBounds();
}
private String getDisplayText(String messageTag, Object[] params, boolean merge, Throwable t) {
String baseText = LanguageSupport.getLocalizedString(messageTag, params);
List exceptionText = getExceptionText(t);
if (exceptionText == null) {
return baseText;
} else {
if (merge) exceptionText.add(0, baseText);
int len = exceptionText.size();
if (len == 1) {
return exceptionText.get(0);
} else {
StringBuffer sb = new StringBuffer();
for (String text : exceptionText) {
if (sb.length() > 0) sb.append("\n\n");
sb.append(text);
}
return sb.toString();
}
}
}
private List getExceptionText(Throwable t) {
List texts = null;
Locale loc = LanguageSupport.getCurrentLocale();
while (t != null) {
if (t instanceof MultiLingualText) {
if (texts == null) texts = new ArrayList();
texts.add(((MultiLingualText) t).getText(loc));
}
t = t.getCause();
}
return texts;
}
void showDetails() {
detailButton.setEnabled(false);
detailPane = getMultiLineComponent(getStringTrace(), 20);
contentPane.add(detailPane, BorderLayout.CENTER);
contentPane.revalidate();
resetBounds();
}
private String getStringTrace() {
StringWriter stringTrace = new StringWriter();
underlyingException.printStackTrace(new PrintWriter(stringTrace, true));
String trace = stringTrace.toString();
trace = trace.replace('\t', ' ');
trace = trace.replace('\r', ' ');
return trace;
}
private void resetBounds() {
pack();
int posX = 20;
int posY = 20;
if (parentFrame != null) {
Rectangle rect = parentFrame.getBounds();
Dimension size = getSize();
posX = rect.x + (rect.width - size.width) / 2;
if (posX < 20) posX = 20;
posY = rect.y + (rect.height - size.height) / 2;
if (posY < 20) posY = 20;
}
setLocation(posX, posY);
}
private static JComponent getMultiLineComponent(String text, int nbrMax) {
StringTokenizer st = new StringTokenizer(text, "\n");
int len = st.countTokens();
JPanel linesPanel = new JPanel(new GridLayout(len, 1));
for (int i = 0; i < len; i++) {
String line = st.nextToken();
linesPanel.add(new JLabel(line));
}
if (len <= nbrMax) return linesPanel;
// Put the linesPanel on a scroll pane
Dimension dim = linesPanel.getPreferredSize();
JScrollPane scroll = new JScrollPane(linesPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setPreferredSize(new Dimension(dim.width + 16, (dim.height * nbrMax) / len));
return scroll;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy