/*
* Copyright (c) 2005-2016 Flamingo Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of Flamingo Kirill Grouchnikov nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
* A dialog for displaying a list of messages (in a scroll panel).
*
* @author Kirill Grouchnikov
*/
public final class MessageListDialog extends JDialog {
/**
* Indicates whether the dialog disposal should cause application shutdown.
*/
private boolean toExitOnDispose;
/**
* Simple constructor. Made private to enforce use of
* {@link #showMessageDialog(Frame, String, LinkedList)} and
* {@link MessageListDialog#showMessageDialog(java.awt.Frame, String, Throwable)}
* .
*
* @param owner
* The owner frame (<code>this</code> dialog is modal).
* @param mainMessage
* The main message (displayed in the top portion of the dialog).
* @param messages
* The list of messages to display in a scroll panel.
*/
private MessageListDialog(Frame owner, String mainMessage,
LinkedList<String> messages) {
super(owner, "Message list");
JLabel messageLabel = new JLabel(mainMessage);
JList messageList = new JList(messages.toArray());
messageList.setForeground(Color.red);
messageList.setFont(UIManager.getFont("Panel.font").deriveFont(
Font.BOLD));
JScrollPane mesScrollPane = new JScrollPane(messageList);
JButton closeButton = new JButton("Close");
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
dispose();
if (toExitOnDispose)
System.exit(0);
}
});
}
});
this.setLayout(new BorderLayout());
JPanel upperPanel = new JPanel();
upperPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
upperPanel.add(messageLabel);
bottomPanel.add(closeButton);
this.add(upperPanel, BorderLayout.NORTH);
this.add(mesScrollPane, BorderLayout.CENTER);
this.add(bottomPanel, BorderLayout.SOUTH);
int width = 400;
int height = 250;
Dimension thisDim = new Dimension(width, height);
this.setSize(thisDim);
this.setPreferredSize(thisDim);
this.setResizable(true);
if (owner != null) {
Dimension ownerDim = owner.getSize();
Point ownerLoc = owner.getLocation();
int xc = ownerLoc.x + ownerDim.width / 2;
int yc = ownerLoc.y + ownerDim.height / 2;
this.setLocation(xc - width / 2, yc - height / 2);
} else {
// retrieve the physical screen dimension
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
// center the configuration screen in the physical screen
this.setLocation((d.width - width) / 2, (d.height - height) / 2);
}
this.getRootPane().setDefaultButton(closeButton);
this.toExitOnDispose = false;
}
/**
* Shows a message dialog.
*
* @param owner
* The owner frame (<code>this</code> dialog is modal).
* @param mainMessage
* The main message (displayed in the top portion of the dialog).
* @param messages
* The list of messages to display in a scroll panel.
* @return The shown message dialog.
*/
public static MessageListDialog showMessageDialog(Frame owner,
String mainMessage, LinkedList<String> messages) {
MessageListDialog mld = new MessageListDialog(owner, mainMessage,
messages);
mld.setModal(owner != null);
mld.setVisible(true);
return mld;
}
/**
* Shows a message dialog for exception.
*
* @param owner
* The owner frame (<code>this</code> dialog is modal).
* @param message
* The main message (displayed in the top portion of the dialog).
* @param throwable
* An exception. The stack trace of the exception will be shown
* in a scroll panel.
* @return The shown message dialog.
*/
public static MessageListDialog showMessageDialog(Frame owner,
String message, Throwable throwable) {
LinkedList<String> errors = new LinkedList<String>();
while (true) {
String mainMessage = throwable.getClass().getName() + " : "
+ throwable.getMessage();
errors.addLast(mainMessage);
StackTraceElement[] stack = throwable.getStackTrace();
for (StackTraceElement ste : stack) {
String className = ste.getClassName();
String methodName = ste.getMethodName();
String lineNumber = "" + ste.getLineNumber();
String steMessage = " in " + className + "." + methodName
+ "(); [line " + lineNumber + "]";
errors.addLast(steMessage);
}
throwable = throwable.getCause();
if (throwable == null)
break;
errors.addLast("Caused by");
}
return showMessageDialog(owner, message, errors);
}
/**
* Sets indication whether the dialog disposal should cause application
* shutdown.
*
* @param toExitOnDispose
* If <code>true</code>, the dialog disposal will cause
* application shutdown.
*/
public void setToExitOnDispose(boolean toExitOnDispose) {
this.toExitOnDispose = toExitOnDispose;
}
}